"""Tests for the library-validation sweep. Covers: scanning a fake library, ignoring the _quarantine subtree, counting suspect files by format, and capping suspect_paths. """ from pathlib import Path import pytest from app.services.file_validator import ( GIF_HEAD_89A, JPEG_HEAD, JPEG_TAIL, PNG_HEAD, PNG_TAIL, ) from app.tasks.maintenance import scan_library_for_corruption def _good_jpeg(p: Path) -> None: p.parent.mkdir(parents=True, exist_ok=True) p.write_bytes(JPEG_HEAD + b"\x00" * 32 + JPEG_TAIL) def _bad_jpeg(p: Path) -> None: p.parent.mkdir(parents=True, exist_ok=True) p.write_bytes(JPEG_HEAD + b"\x00" * 32) # no EOI def _bad_png(p: Path) -> None: p.parent.mkdir(parents=True, exist_ok=True) p.write_bytes(PNG_HEAD + b"\x00" * 32) # no IEND def test_scan_finds_truncated_files(tmp_path): _good_jpeg(tmp_path / "Artist" / "patreon" / "01.jpg") _bad_jpeg(tmp_path / "Artist" / "patreon" / "02.jpg") _bad_png(tmp_path / "Artist" / "patreon" / "03.png") # JSON sidecars must not be scanned (tmp_path / "Artist" / "patreon" / "01.json").write_bytes(b"{}") report = scan_library_for_corruption(tmp_path) assert report["scanned"] == 3 assert report["suspect_count"] == 2 assert report["by_format"] == {"jpeg": 1, "png": 1} paths = {entry["path"] for entry in report["suspect_paths"]} assert any("02.jpg" in p for p in paths) assert any("03.png" in p for p in paths) assert not report["truncated"] def test_scan_skips_quarantine_subtree(tmp_path): """Files already moved to _quarantine are known-bad; don't re-scan them.""" _bad_jpeg(tmp_path / "_quarantine" / "Artist" / "patreon" / "01.jpg") _good_jpeg(tmp_path / "Artist" / "patreon" / "02.jpg") report = scan_library_for_corruption(tmp_path) assert report["scanned"] == 1 assert report["suspect_count"] == 0 def test_scan_caps_suspect_paths(tmp_path): """suspect_count is the true total; suspect_paths is capped + truncated flag set.""" for i in range(7): _bad_jpeg(tmp_path / "Artist" / "patreon" / f"{i:02d}.jpg") report = scan_library_for_corruption(tmp_path, max_suspect_paths=3) assert report["scanned"] == 7 assert report["suspect_count"] == 7 assert len(report["suspect_paths"]) == 3 assert report["truncated"] is True def test_scan_missing_root_returns_empty_report(tmp_path): report = scan_library_for_corruption(tmp_path / "does_not_exist") assert report["scanned"] == 0 assert report["suspect_count"] == 0 assert report["suspect_paths"] == []