"""Basic tests for image hashing.""" from io import BytesIO import pytest from PIL import Image from fieldwitness.attest.hashing import hash_image, perceptual_distance, is_same_image def create_test_image(width: int = 100, height: int = 100, color: tuple = (255, 0, 0)) -> bytes: """Create a simple test image.""" img = Image.new("RGB", (width, height), color) buffer = BytesIO() img.save(buffer, format="PNG") return buffer.getvalue() class TestHashImage: """Tests for hash_image function.""" def test_hash_returns_all_components(self): """Hash should return sha256, phash, and dhash.""" image_data = create_test_image() hashes = hash_image(image_data) assert hashes.sha256 assert hashes.phash assert hashes.dhash assert len(hashes.sha256) == 64 # SHA-256 hex def test_identical_images_same_hash(self): """Identical bytes should produce identical hashes.""" image_data = create_test_image() hash1 = hash_image(image_data) hash2 = hash_image(image_data) assert hash1.sha256 == hash2.sha256 assert hash1.phash == hash2.phash assert hash1.dhash == hash2.dhash def test_different_images_different_hash(self): """Different images should produce different SHA-256.""" red = create_test_image(color=(255, 0, 0)) blue = create_test_image(color=(0, 0, 255)) hash_red = hash_image(red) hash_blue = hash_image(blue) assert hash_red.sha256 != hash_blue.sha256 class TestPerceptualDistance: """Tests for perceptual distance calculation.""" def test_identical_hashes_zero_distance(self): """Identical hashes should have zero distance.""" h = "0123456789abcdef" assert perceptual_distance(h, h) == 0 def test_different_hashes_nonzero_distance(self): """Different hashes should have positive distance.""" h1 = "0000000000000000" h2 = "0000000000000001" assert perceptual_distance(h1, h2) == 1 def test_completely_different_max_distance(self): """Completely different hashes should have max distance.""" h1 = "0000000000000000" h2 = "ffffffffffffffff" assert perceptual_distance(h1, h2) == 64 # 16 hex chars = 64 bits class TestIsSameImage: """Tests for image comparison.""" def test_exact_match(self): """Identical bytes should be exact match.""" image_data = create_test_image() hash1 = hash_image(image_data) hash2 = hash_image(image_data) is_same, reason = is_same_image(hash1, hash2) assert is_same assert reason == "exact"