Files
geointel/backend/tests/test_accuracy_phase3_full_data_scan.py
T
Jens faeb58ef6d
GeoIntel release gates / Compile, test, contracts and builds (push) Successful in 1m49s
GeoIntel release gates / Python and npm vulnerability policy (push) Successful in 21s
GeoIntel release gates / Production AI image, SBOM and container scan (push) Successful in 5m39s
GeoIntel release gates / Deploy exact gated revision to Unraid (push) Failing after 58m43s
Initial public release
2026-08-31 21:56:53 +02:00

132 lines
4.2 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,
unreachable_scopes: tuple[str, ...] = (),
) -> dict:
command = [
sys.executable,
str(SCRIPT),
"--repo-root",
str(repo),
"--output-dir",
str(output),
"--roots",
"data",
"--batch-size",
"2",
]
if resume:
command.append("--resume")
for scope in unreachable_scopes:
command.extend(("--unreachable-scope", scope))
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"
unreachable_scopes = (
"external://tower-corpora=Tower corpora are not mounted in this fixture",
"external://mounted-model-volumes=Model volumes are not mounted in this fixture",
"external://production-postgis-or-api=Production database is not configured in this fixture",
)
first = run_scan(tmp_path, output, unreachable_scopes=unreachable_scopes)
second = run_scan(
tmp_path,
output,
resume=True,
unreachable_scopes=unreachable_scopes,
)
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
def test_phase3_scan_does_not_invent_unreachable_production_boundaries(
tmp_path: Path,
) -> None:
data = tmp_path / "data"
data.mkdir()
(data / "present.json").write_text("{}", encoding="utf-8")
output = tmp_path / "evidence"
result = run_scan(tmp_path, output)
assert result["reconciliation"] == {
"examined": 1,
"skipped": 0,
"unreachable": 0,
"inventory_total": 1,
"reconciles": True,
}
def test_phase3_scan_records_a_missing_requested_root(tmp_path: Path) -> None:
output = tmp_path / "evidence"
completed = subprocess.run(
[
sys.executable,
str(SCRIPT),
"--repo-root",
str(tmp_path),
"--output-dir",
str(output),
"--roots",
"missing-data",
],
check=True,
capture_output=True,
text=True,
)
result = json.loads(completed.stdout)
manifest = json.loads((output / "full-scan-manifest.json").read_text(encoding="utf-8"))
assert result["reconciliation"]["unreachable"] == 1
assert manifest["items"][0]["path"] == "root://missing-data"