import http.client import json import shutil import subprocess import threading import uuid from pathlib import Path from urllib.parse import urlencode import pytest from rtut import run as R1, run2 as R, ui ROOT = Path(__file__).resolve().parent.parent _scratch = [] @pytest.fixture def srv(tmp_path): for name, src in (("v1", "showcase-lighthouse"), ("v2", "showcase-lighthouse-v2")): d = tmp_path / "runbooks" / name; d.mkdir(parents=True) shutil.copy(ROOT / f"runbooks/{src}/pack.yaml", d / "pack.yaml") s = ui.serve([tmp_path], 0) threading.Thread(target=s.serve_forever, daemon=True).start() s.repo = tmp_path yield s s.shutdown() while _scratch: shutil.rmtree(_scratch.pop(), ignore_errors=True) def req(s, method, path, form=None): c = http.client.HTTPConnection("127.0.0.1", s.server_address[1]) body = urlencode(form) if form is not None else None c.request(method, path, body, {"Host": "127.0.0.1", "Content-Type": "application/x-www-form-urlencoded"}) r = c.getresponse() return r.status, r.getheader("Location"), r.read().decode() def post(s, path, **form): return req(s, "POST", path, {"_t": s.app.token, **form}) def start(s, pack_id): i = s.app.pack_index(pack_id) logdir = f"/tmp/rtut-lock-{uuid.uuid4().hex[:8]}" _scratch.append(logdir) st, loc, _ = post(s, f"/run/new/{i}", operator="bernd", p_logdir=logdir) assert st == 303 return loc.split("#")[0], i def run_of(s, base): return R1.load(s.app.packs[int(base.split("/")[2])], base.rsplit("/", 1)[1]) # ---- Home headlines are shortcuts --------------------------------------------------------------------------- def test_home_headlines_link_to_the_sidebar_sections_and_the_section_pages_do_not(srv): _, _, home = req(srv, "GET", "/") assert "
Comment: gave up on step two
" in body and "- " not in body def test_the_record_file_is_read_only_after_closing_and_tampering_is_called_out(srv): base, _ = start(srv, "rtut.showcase-lighthouse-v2") post(srv, f"{base}/finalize", outcome="abandoned") r = run_of(srv, base) assert r.path.stat().st_mode & 0o222 == 0 and R1.seal_state(r) == "sealed" assert "changed outside the app" not in req(srv, "GET", base)[2] r.path.chmod(0o644) data = json.loads(r.path.read_text()); data["operator"] = "forged"; r.path.write_text(json.dumps(data)) body = req(srv, "GET", base)[2] assert "changed outside the app after it was sealed" in body and "no longer counts towards maturity" in body # ---- evidence export ------------------------------------------------------------------------------------------------------ def raw(s, path): c = http.client.HTTPConnection("127.0.0.1", s.server_address[1]) c.request("GET", path, None, {"Host": "127.0.0.1"}) r = c.getresponse() return r.status, {k.lower(): v for k, v in r.getheaders()}, r.read() @pytest.mark.parametrize("pack", ["rtut.showcase-lighthouse", "rtut.showcase-lighthouse-v2"]) def test_a_closed_run_record_can_be_downloaded_and_its_seal_checked_elsewhere(srv, pack, tmp_path, capsys): from rtut.__main__ import main base, _ = start(srv, pack) st, _, body = raw(srv, f"{base}/record.json") assert st == 409 and b"once the run is closed" in body # an open run has no final record assert "Download the run record" not in req(srv, "GET", base)[2] post(srv, f"{base}/finalize", outcome="abandoned", note="for the record") st, hdr, body = raw(srv, f"{base}/record.json") rid = base.rsplit("/", 1)[1] assert st == 200 and hdr["content-type"] == "application/json" and hdr["x-rtut-seal"] == "sealed" assert hdr["content-disposition"] == f'attachment; filename="run-{rid}.json"' and hdr["x-content-type-options"] == "nosniff" assert "sandbox" in hdr["content-security-policy"] assert body == run_of(srv, base).path.read_bytes() # exactly as stored record = json.loads(body) assert record["run_id"] == rid and record["outcome"] == "abandoned" and R1.record_seal_state(record) == "sealed" assert f"Download the run record (JSON)" in req(srv, "GET", base)[2] f = tmp_path / "exported.json"; f.write_bytes(body) assert main(["seal", str(f)]) == 0 and capsys.readouterr().out.strip() == "sealed" # anyone can verify it record["operator"] = "forged"; f.write_text(json.dumps(record)) assert main(["seal", str(f)]) == 1 and capsys.readouterr().out.strip() == "broken" def test_a_tampered_record_is_still_downloadable_but_flagged_in_the_header(srv): base, _ = start(srv, "rtut.showcase-lighthouse-v2") post(srv, f"{base}/finalize", outcome="abandoned") r = run_of(srv, base); r.path.chmod(0o644) data = json.loads(r.path.read_text()); data["operator"] = "forged"; r.path.write_text(json.dumps(data)) st, hdr, _ = raw(srv, f"{base}/record.json") assert st == 200 and hdr["x-rtut-seal"] == "broken" # evidence, with the warning attached def test_unknown_run_record_is_not_found(srv): assert raw(srv, "/run/0/nope/record.json")[0] == 404