orgstate / tests /test_delivery_bundle_cli.py
Legal-i's picture
Initial OrgState deploy via Stage 150 free-tier stack
d2d1903 verified
"""
Tests for Stage 70 β€” bundle CLI.
python -m delivery.bundle create DIR [--out PATH]
python -m delivery.bundle verify ZIP
Recipient who got a bundle.zip in an email can verify in one shell
command. Exit-code contract:
0 β€” create succeeded OR verify passed (manifest intact)
1 β€” verify failed (sha256 mismatch on at least one file)
2 β€” bad args / file not found / not a zip
"""
import json
import zipfile
from delivery.bundle import _cli, bundle_pilot_output
def _populate(tmp_path):
src = tmp_path / "pilot_out"
src.mkdir()
(src / "report.html").write_text("<h1>R</h1>", encoding="utf-8")
(src / "queue.html").write_text("<h1>Q</h1>", encoding="utf-8")
return src
def _run(capsys, *args):
capsys.readouterr()
rc = _cli(list(args))
out, err = capsys.readouterr()
body = json.loads(out) if out.strip() else None
err_body = json.loads(err) if err.strip() else None
return rc, body, err_body
# --- create ----------------------------------------------------------
def test_create_emits_bundle_path_and_writes_zip(tmp_path, capsys):
src = _populate(tmp_path)
rc, body, _ = _run(capsys, "create", str(src))
assert rc == 0
assert "bundle_path" in body
zip_path = tmp_path / "pilot_out.zip"
assert zip_path.exists()
def test_create_with_explicit_out(tmp_path, capsys):
src = _populate(tmp_path)
out = tmp_path / "custom.zip"
rc, body, _ = _run(capsys, "create", str(src), "--out", str(out))
assert rc == 0
assert body["bundle_path"] == str(out.resolve())
assert out.exists()
def test_create_missing_dir_exits_2(tmp_path, capsys):
rc, _, err = _run(capsys, "create", str(tmp_path / "nope"))
assert rc == 2
assert "does not exist" in err["error"]
# --- verify ----------------------------------------------------------
def test_verify_intact_bundle_exits_0(tmp_path, capsys):
src = _populate(tmp_path)
zip_path = bundle_pilot_output(src)
rc, body, _ = _run(capsys, "verify", str(zip_path))
assert rc == 0
assert body["ok"] is True
assert body["n_mismatches"] == 0
def test_verify_tampered_bundle_exits_1(tmp_path, capsys):
"""The recipient's smoking gun β€” if anyone modified a file in the
bundle, verify returns exit 1 + ok=false + the mismatching paths
in the JSON. Cron-friendly: pipe to ``jq .ok`` and gate on it."""
src = _populate(tmp_path)
src_zip = bundle_pilot_output(src)
tampered = tmp_path / "tampered.zip"
with zipfile.ZipFile(src_zip, "r") as zin, \
zipfile.ZipFile(tampered, "w", zipfile.ZIP_DEFLATED) as zout:
for name in zin.namelist():
data = zin.read(name)
if name == "report.html":
data = b"<h1>EVIL</h1>"
zout.writestr(name, data)
rc, body, _ = _run(capsys, "verify", str(tampered))
assert rc == 1
assert body["ok"] is False
assert body["n_mismatches"] == 1
assert body["mismatches"][0]["path"] == "report.html"
def test_verify_missing_file_exits_2(tmp_path, capsys):
rc, _, err = _run(capsys, "verify", str(tmp_path / "no_such.zip"))
assert rc == 2
assert "error" in err
def test_verify_non_zip_exits_2(tmp_path, capsys):
"""A path that exists but isn't a zip β€” exit 2 with a clear
'not a valid zip' message. Operator pointing at the wrong file
sees the right error, not a Python traceback."""
bad = tmp_path / "not_a_zip.txt"
bad.write_text("plain text not a zip", encoding="utf-8")
rc, _, err = _run(capsys, "verify", str(bad))
assert rc == 2
assert "not a valid zip" in err["error"]