face-intel / tests /unit /test_normalization.py
Marwan
Restructure + add reverse face search (PimEyes-style)
f5eeb1c
Raw
History Blame Contribute Delete
5.57 kB
"""Unit tests for normalization/merger.py."""
from __future__ import annotations
from confidence.engine import ConfidenceEngine
from confidence.conflicts import ConflictDetector
from models.providers import ProviderCapability
from normalization.merger import ReportMerger
from providers.base import ProviderResult
def _make_result(provider: str, capability: ProviderCapability,
normalized: dict, success: bool = True) -> ProviderResult:
return ProviderResult(
provider=provider,
capability=capability,
success=success,
elapsed_ms=10.0,
normalized=normalized,
)
class TestReportMerger:
def test_merge_empty_results(self):
engine = ConfidenceEngine()
cd = ConflictDetector()
merger = ReportMerger(engine, cd)
report = merger.merge({}, "hash", "job-id", 100.0, "detection")
assert report.metadata.image_hash == "hash"
assert report.metadata.job_id == "job-id"
assert report.metadata.total_elapsed_ms == 100.0
assert report.detections == []
assert report.matches == []
assert report.evidence == []
assert report.conflicts == []
def test_merge_detection_results(self):
engine = ConfidenceEngine()
cd = ConflictDetector()
merger = ReportMerger(engine, cd)
results = {
"haar": _make_result(
"haar", ProviderCapability.DETECTION,
{"boxes": [{"x": 10, "y": 20, "w": 100, "h": 120}],
"confidences": [0.95], "landmarks": None, "num_faces": 1},
),
}
report = merger.merge(results, "hash", "job-id", 50.0, "detection")
assert len(report.detections) == 1
assert report.detections[0].box == {"x": 10, "y": 20, "w": 100, "h": 120}
assert "haar" in report.detections[0].detected_by
assert report.detections[0].confidence.overall > 0.0
assert len(report.evidence) == 1
assert report.evidence[0].provider == "haar"
def test_merge_preserves_failed_results_as_evidence(self):
engine = ConfidenceEngine()
cd = ConflictDetector()
merger = ReportMerger(engine, cd)
results = {
"dnn": ProviderResult(
provider="dnn", capability=ProviderCapability.DETECTION,
success=False, elapsed_ms=5.0, error="model not loaded",
error_type="RuntimeError",
),
}
report = merger.merge(results, "hash", "job-id", 5.0, "detection")
# Failed provider shouldn't contribute detections
assert report.detections == []
# But should be preserved as evidence
assert len(report.evidence) == 1
assert report.evidence[0].success is False
assert report.evidence[0].error == "model not loaded"
assert "dnn" in report.metadata.providers_failed
def test_merge_image_analysis_results(self):
engine = ConfidenceEngine()
cd = ConflictDetector()
merger = ReportMerger(engine, cd)
results = {
"image_quality": _make_result(
"image_quality", ProviderCapability.IMAGE_ANALYSIS,
{"quality_score": 0.85, "brightness": 128.0, "contrast": 50.0,
"sharpness": 200.0, "noise_level": 5.0, "width": 200, "height": 200,
"channels": 3, "color_profile": "BGR", "dominant_colors": ["#ff0000"]},
),
}
report = merger.merge(results, "hash", "job-id", 30.0, "image_analysis")
assert len(report.image_analyses) == 1
assert report.image_analyses[0].provider == "image_quality"
assert report.image_analyses[0].quality_score == 0.85
assert report.image_analyses[0].confidence is not None
def test_merge_metadata_results(self):
engine = ConfidenceEngine()
cd = ConflictDetector()
merger = ReportMerger(engine, cd)
results = {
"exif": _make_result(
"exif", ProviderCapability.METADATA,
{"format": "JPEG", "exif": {"Make": "Canon"}, "camera_make": "Canon"},
),
}
report = merger.merge(results, "hash", "job-id", 20.0, "metadata")
assert len(report.metadata_extractions) == 1
assert report.metadata_extractions[0].format == "JPEG"
assert report.metadata_extractions[0].camera_make == "Canon"
def test_merge_forensics_results(self):
engine = ConfidenceEngine()
cd = ConflictDetector()
merger = ReportMerger(engine, cd)
results = {
"image_integrity": _make_result(
"image_integrity", ProviderCapability.FORENSICS,
{"integrity_score": 0.95, "manipulation_indicators": [],
"details": {"sha256": "abc123"}},
),
}
report = merger.merge(results, "hash", "job-id", 15.0, "forensics")
assert len(report.forensics) == 1
assert report.forensics[0].integrity_score == 0.95
def test_merge_collects_limitations(self):
engine = ConfidenceEngine()
cd = ConflictDetector()
merger = ReportMerger(engine, cd)
results = {
"dnn": ProviderResult(
provider="dnn", capability=ProviderCapability.DETECTION,
success=False, elapsed_ms=5.0, error="model not loaded",
),
}
report = merger.merge(results, "hash", "job-id", 5.0, "detection")
assert any("dnn" in lim for lim in report.metadata.limitations)