File size: 2,769 Bytes
23d337e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | """Provider tests for EXIFProvider."""
from __future__ import annotations
import cv2
import io
import numpy as np
import pytest
from PIL import Image
from config.settings import Settings
from pipeline.feature_extraction import PipelineOutput
from providers.metadata.exif import EXIFProvider
@pytest.fixture
def exif_provider():
return EXIFProvider(settings=Settings(environment="test", db_path=":memory:"))
@pytest.fixture
def pipeline_with_bytes(sample_image_bytes):
img = cv2.imdecode(np.frombuffer(sample_image_bytes, np.uint8), cv2.IMREAD_COLOR)
return PipelineOutput(
image=img, image_hash="h", width=img.shape[1], height=img.shape[0], source="bytes",
original_bytes=sample_image_bytes, original_format=".jpg",
)
@pytest.fixture
def pipeline_without_bytes(sample_image_bytes):
"""A pipeline output WITHOUT original_bytes — EXIF should gracefully return empty."""
img = cv2.imdecode(np.frombuffer(sample_image_bytes, np.uint8), cv2.IMREAD_COLOR)
return PipelineOutput(
image=img, image_hash="h", width=img.shape[1], height=img.shape[0], source="bytes",
original_bytes=None, original_format=None,
)
class TestEXIFProvider:
def test_name(self, exif_provider):
assert exif_provider.name == "exif"
def test_capability(self, exif_provider):
from models.providers import ProviderCapability
assert exif_provider.capability == ProviderCapability.METADATA
def test_is_available(self, exif_provider):
# Should be available if Pillow is installed (it is, in requirements)
assert exif_provider.is_available() is True
def test_execute_with_bytes(self, exif_provider, pipeline_with_bytes):
result = exif_provider.execute(pipeline_with_bytes)
assert result.success is True
assert "format" in result.normalized
assert "exif" in result.normalized
assert isinstance(result.normalized["exif"], dict)
def test_execute_without_bytes_returns_empty(self, exif_provider, pipeline_without_bytes):
result = exif_provider.execute(pipeline_without_bytes)
assert result.success is True
assert result.normalized["exif"] == {}
def test_synthetic_jpeg_has_no_exif(self, exif_provider, pipeline_with_bytes):
"""A synthetic JPEG (no camera) should have no EXIF tags."""
result = exif_provider.execute(pipeline_with_bytes)
assert len(result.normalized["exif"]) == 0
assert result.normalized["camera_make"] is None
assert result.normalized["capture_time"] is None
def test_format_extracted(self, exif_provider, pipeline_with_bytes):
result = exif_provider.execute(pipeline_with_bytes)
assert result.normalized["format"] == "JPEG"
|