face-intel / tests /unit /test_forensic_metadata.py
Marwan
Restructure + add reverse face search (PimEyes-style)
f5eeb1c
Raw
History Blame Contribute Delete
3.15 kB
"""Unit tests for cores.metadata.forensic — ICC, thumbnail, editing history, etc."""
from __future__ import annotations
import io
import pytest
from PIL import Image
from cores.metadata import (
extract_icc_profile,
extract_thumbnail,
extract_embedded_preview,
extract_editing_history,
analyze_compression,
normalize_timestamp,
extract_lens_info,
camera_fingerprint,
)
class TestICCProfile:
def test_no_icc_returns_none(self, sample_image_bytes):
result = extract_icc_profile(sample_image_bytes)
# Synthetic JPEG likely has no ICC
assert result is None or result.get("present") is False
def test_empty_bytes(self):
assert extract_icc_profile(b"") is None
class TestThumbnail:
def test_no_thumbnail_returns_none(self, sample_image_bytes):
result = extract_thumbnail(sample_image_bytes)
assert result is None or result.get("present") is False
def test_empty_bytes(self):
assert extract_thumbnail(b"") is None
class TestEditingHistory:
def test_empty_exif(self):
assert extract_editing_history({}) == []
def test_extracts_software(self):
exif = {"Software": "Adobe Photoshop"}
history = extract_editing_history(exif)
assert any("Software" in h for h in history)
def test_extracts_artist(self):
exif = {"Artist": "John Doe"}
history = extract_editing_history(exif)
assert any("Artist" in h for h in history)
class TestCompressionAnalysis:
def test_returns_format(self, sample_image_bytes):
result = analyze_compression(sample_image_bytes)
assert result is not None
assert result["format"] == "JPEG"
assert result["size_bytes"] > 0
assert result["compression_ratio"] > 0
def test_empty_bytes(self):
assert analyze_compression(b"") is None
class TestTimestampNormalization:
def test_exif_format(self):
result = normalize_timestamp("2023:01:15 14:30:45")
assert result is not None
assert result["iso"].startswith("2023-01-15T14:30:45")
assert result["timezone"] == "unknown"
def test_iso_format(self):
result = normalize_timestamp("2023-01-15 14:30:45")
assert result is not None
assert result["iso"].startswith("2023-01-15")
def test_empty(self):
assert normalize_timestamp("") is None
def test_invalid(self):
result = normalize_timestamp("not a date")
assert result is not None
assert result["iso"] is None
class TestLensInfo:
def test_extracts_lens_model(self):
exif = {"LensModel": "24-70mm f/2.8"}
assert extract_lens_info(exif) == "24-70mm f/2.8"
def test_empty_exif(self):
assert extract_lens_info({}) is None
class TestCameraFingerprint:
def test_returns_hash(self, sample_image_bytes):
fp = camera_fingerprint(sample_image_bytes, (200, 200))
# Should return a 32-char hash or None
if fp is not None:
assert len(fp) == 32
def test_empty_bytes(self):
assert camera_fingerprint(b"", (200, 200)) is None