"""Layer-3 subprocess-isolated probe tests. The bomb-guard cap is exercised against `_run_probe` directly (in-process, where a monkeypatch on the module constant takes effect) — the real probe runs in a subprocess that re-imports the module, so a parent-process monkeypatch wouldn't reach the spawned interpreter. """ import zipfile from pathlib import Path from backend.app.utils import safe_probe def _zip(path, entries): with zipfile.ZipFile(path, "w") as zf: for name, data in entries.items(): zf.writestr(name, data) def test_probe_archive_valid_zip(tmp_path): z = tmp_path / "ok.zip" _zip(z, {"a.jpg": b"hello", "b.png": b"world"}) res = safe_probe.probe_archive(z) assert res.ok is True assert res.crashed is False def test_probe_archive_corrupt_zip_clean_rejection(tmp_path): z = tmp_path / "broken.zip" z.write_bytes(b"PK\x03\x04 not really a zip past here") res = safe_probe.probe_archive(z) assert res.ok is False # Corrupt-but-handled (zipfile raises BadZipFile in the child) — a # clean rejection, not a hard crash. assert res.crashed is False assert res.reason def test_inspect_archive_reports_size_and_clean_integrity(tmp_path): z = tmp_path / "sized.zip" _zip(z, {"a.txt": b"x" * 100, "b.txt": b"y" * 50}) total, bad = safe_probe._inspect_archive(z) assert total == 150 assert bad is None def test_inspect_archive_detects_misnamed_zip(tmp_path): """A zip with a mangled / extension-less name (Patreon URL-blob attachment) is still bomb-guarded + integrity-tested via magic-byte detection.""" z = tmp_path / "01_https___www.patreon.com_media-u_v3_131083093" _zip(z, {"a.txt": b"x" * 100}) total, bad = safe_probe._inspect_archive(z) assert total == 100 assert bad is None def test_run_probe_bomb_guard(tmp_path, monkeypatch): """In-process call to _run_probe so the monkeypatched cap takes effect. The public probe_archive runs in a subprocess which re-imports the module and wouldn't see the patched constant.""" monkeypatch.setattr(safe_probe, "MAX_ARCHIVE_UNCOMPRESSED_BYTES", 10) z = tmp_path / "bomb.zip" _zip(z, {"big.txt": b"x" * 5000}) # 5000 uncompressed > 10-byte cap status, detail = safe_probe._run_probe(str(z)) assert status == "error" assert "bomb-guard cap" in detail def test_probe_video_non_video_is_not_ok(tmp_path): """A text file is not a decodable video. Whether ffprobe is present (returncode != 0) or absent (OSError → 'unavailable'), the result is ok=False. We don't assert on crashed/reason so the test is robust to ffprobe presence in CI.""" f = tmp_path / "nope.txt" f.write_text("definitely not a video container") res = safe_probe.probe_video(f) assert res.ok is False