71 lines
2.5 KiB
Python
71 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
SCRIPT = Path(__file__).resolve().parents[2] / "scripts" / "run_accuracy_phase3_full_data_scan.py"
|
|
|
|
|
|
def run_scan(repo: Path, output: Path, *, resume: bool = False) -> dict:
|
|
command = [
|
|
sys.executable,
|
|
str(SCRIPT),
|
|
"--repo-root",
|
|
str(repo),
|
|
"--output-dir",
|
|
str(output),
|
|
"--roots",
|
|
"data",
|
|
"--batch-size",
|
|
"2",
|
|
]
|
|
if resume:
|
|
command.append("--resume")
|
|
completed = subprocess.run(command, check=True, capture_output=True, text=True)
|
|
return json.loads(completed.stdout)
|
|
|
|
|
|
def test_phase3_scan_reconciles_and_resumes_deterministically(tmp_path: Path) -> None:
|
|
data = tmp_path / "data"
|
|
data.mkdir()
|
|
(data / "valid.geojson").write_text(
|
|
json.dumps(
|
|
{
|
|
"type": "FeatureCollection",
|
|
"features": [
|
|
{
|
|
"type": "Feature",
|
|
"properties": {"source": "GRB"},
|
|
"geometry": {"type": "Point", "coordinates": [4.4, 50.8]},
|
|
}
|
|
],
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
invalid = data / "invalid.geojson"
|
|
invalid.write_text(
|
|
'{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[0,0],[1,1],[1,0],[0,1],[0,0]]]}}]}',
|
|
encoding="utf-8",
|
|
)
|
|
duplicate_payload = '{"schema_version":1,"value":"same"}'
|
|
(data / "one.json").write_text(duplicate_payload, encoding="utf-8")
|
|
(data / "two.json").write_text(duplicate_payload, encoding="utf-8")
|
|
(data / "broken.tif").write_bytes(b"not a geotiff")
|
|
|
|
output = tmp_path / "evidence"
|
|
first = run_scan(tmp_path, output)
|
|
second = run_scan(tmp_path, output, resume=True)
|
|
manifest = json.loads((output / "full-scan-manifest.json").read_text(encoding="utf-8"))
|
|
quarantine = json.loads((output / "quarantine-manifest.json").read_text(encoding="utf-8"))
|
|
|
|
assert first["reconciliation"] == {"examined": 5, "skipped": 0, "unreachable": 3, "inventory_total": 8, "reconciles": True}
|
|
assert second["content_hash"] == first["content_hash"]
|
|
assert manifest["determinism"]["content_hash"] == first["content_hash"]
|
|
assert any(item["path"] == "data/broken.tif" for item in quarantine["items"])
|
|
assert any(item["path"] == "data/invalid.geojson" for item in quarantine["items"])
|
|
assert len(manifest["duplicates"]["exact_duplicate_groups"]) == 1
|