File size: 2,373 Bytes
9bd3ee0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Provider tests for ELA (Error Level Analysis)."""

from __future__ import annotations

import cv2
import numpy as np
import pytest

from config.settings import Settings
from pipeline.feature_extraction import PipelineOutput
from providers.forensics.ela import ELAProvider


@pytest.fixture
def ela_provider():
    return ELAProvider(settings=Settings(environment="test", db_path=":memory:"))


@pytest.fixture
def pipeline_output(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",
    )


class TestELAProvider:
    def test_name(self, ela_provider):
        assert ela_provider.name == "ela"

    def test_capability(self, ela_provider):
        from models.providers import ProviderCapability
        assert ela_provider.capability == ProviderCapability.FORENSICS

    def test_is_available(self, ela_provider):
        assert ela_provider.is_available() is True

    def test_execute_returns_metrics(self, ela_provider, pipeline_output):
        result = ela_provider.execute(pipeline_output)
        assert result.success is True
        n = result.normalized
        assert "ela_score" in n
        assert "manipulation_indicators" in n
        assert "details" in n
        assert 0.0 <= n["ela_score"] <= 1.0
        assert "mean_diff" in n["details"]
        assert "max_diff" in n["details"]

    def test_ela_score_in_range(self, ela_provider, pipeline_output):
        result = ela_provider.execute(pipeline_output)
        assert 0.0 <= result.normalized["ela_score"] <= 1.0

    def test_synthetic_image_low_ela(self, ela_provider, sample_image_bytes):
        # A synthetic JPEG re-encoded at quality 90 should have low ELA
        # (it was never manipulated)
        img = cv2.imdecode(np.frombuffer(sample_image_bytes, np.uint8), cv2.IMREAD_COLOR)
        po = PipelineOutput(
            image=img, image_hash="h", width=img.shape[1], height=img.shape[0],
            source="bytes", original_bytes=sample_image_bytes, original_format=".jpg",
        )
        result = ela_provider.execute(po)
        # ELA score should be relatively low for a clean image
        assert result.normalized["ela_score"] < 0.8