"""Layer-3 subprocess-isolated probe tests. The bomb-guard cap is exercised against `_archive_probe_target` directly (in-process, where a monkeypatch on the module constant takes effect) — spawn re-imports the module in the child, so a parent-process monkeypatch wouldn't reach the spawned worker. """ import multiprocessing as mp 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, ".zip") assert total == 150 assert bad is None def test_archive_probe_target_bomb_guard(tmp_path, monkeypatch): """In-process call to the child target so the monkeypatched cap takes effect. A normal zip whose uncompressed size exceeds the (lowered) cap is rejected with the bomb-guard reason.""" 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 q = mp.get_context("spawn").Queue() safe_probe._archive_probe_target(str(z), q) status, detail = q.get(timeout=5) 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