Spaces:
Sleeping
Sleeping
File size: 9,749 Bytes
b610d23 |
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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
"""Tests for validation service."""
import pytest
import tempfile
import shutil
from pathlib import Path
from PIL import Image
import io
from src.storage.validation_service import ValidationService
class TestValidationService:
"""Test cases for ValidationService class."""
def setup_method(self):
"""Set up test fixtures."""
self.temp_dir = Path(tempfile.mkdtemp())
self.validator = ValidationService()
def teardown_method(self):
"""Clean up temporary directory."""
shutil.rmtree(self.temp_dir)
def create_test_image(self, filename: str, width: int = 512, height: int = 512, format: str = 'JPEG') -> Path:
"""Create a test image file."""
file_path = self.temp_dir / filename
# Create a simple test image
img = Image.new('RGB', (width, height), color='red')
img.save(file_path, format)
return file_path
def create_corrupted_file(self, filename: str, content: bytes = b"not an image") -> Path:
"""Create a corrupted file."""
file_path = self.temp_dir / filename
file_path.write_bytes(content)
return file_path
def test_validate_image_format_valid_jpeg(self):
"""Test validation of valid JPEG image."""
image_path = self.create_test_image("test.jpg", format='JPEG')
is_valid, error = self.validator.validate_image_format(image_path)
assert is_valid is True
assert error is None
def test_validate_image_format_invalid_format(self):
"""Test validation of non-JPEG image."""
image_path = self.create_test_image("test.png", format='PNG')
is_valid, error = self.validator.validate_image_format(image_path)
assert is_valid is False
assert "Expected JPEG format, got PNG" in error
def test_validate_image_format_corrupted_file(self):
"""Test validation of corrupted file."""
corrupted_path = self.create_corrupted_file("corrupted.jpg")
is_valid, error = self.validator.validate_image_format(corrupted_path)
assert is_valid is False
assert error is not None
def test_calculate_file_hash(self):
"""Test file hash calculation."""
image_path = self.create_test_image("test.jpg")
hash1 = self.validator.calculate_file_hash(image_path, 'md5')
hash2 = self.validator.calculate_file_hash(image_path, 'md5')
assert hash1 is not None
assert hash1 == hash2 # Same file should have same hash
assert len(hash1) == 32 # MD5 hash length
def test_calculate_file_hash_different_algorithms(self):
"""Test different hash algorithms."""
image_path = self.create_test_image("test.jpg")
md5_hash = self.validator.calculate_file_hash(image_path, 'md5')
sha256_hash = self.validator.calculate_file_hash(image_path, 'sha256')
assert md5_hash is not None
assert sha256_hash is not None
assert len(md5_hash) == 32 # MD5
assert len(sha256_hash) == 64 # SHA256
assert md5_hash != sha256_hash
def test_validate_file_size_exact_match(self):
"""Test file size validation with exact match."""
image_path = self.create_test_image("test.jpg")
actual_size = image_path.stat().st_size
is_valid, error = self.validator.validate_file_size(image_path, actual_size)
assert is_valid is True
assert error is None
def test_validate_file_size_within_tolerance(self):
"""Test file size validation within tolerance."""
image_path = self.create_test_image("test.jpg")
actual_size = image_path.stat().st_size
is_valid, error = self.validator.validate_file_size(image_path, actual_size + 5, tolerance=10)
assert is_valid is True
assert error is None
def test_validate_file_size_outside_tolerance(self):
"""Test file size validation outside tolerance."""
image_path = self.create_test_image("test.jpg")
actual_size = image_path.stat().st_size
is_valid, error = self.validator.validate_file_size(image_path, actual_size + 100, tolerance=10)
assert is_valid is False
assert "Size mismatch" in error
def test_validate_image_content_valid(self):
"""Test validation of valid image content."""
image_path = self.create_test_image("test.jpg", width=1024, height=768)
is_valid, error = self.validator.validate_image_content(image_path)
assert is_valid is True
assert error is None
def test_validate_image_content_too_small(self):
"""Test validation of image that's too small."""
image_path = self.create_test_image("small.jpg", width=50, height=50)
is_valid, error = self.validator.validate_image_content(image_path)
assert is_valid is False
assert "Image too small" in error
def test_validate_image_content_too_large(self):
"""Test validation of image that's too large."""
# Note: We won't actually create a 15000x15000 image for performance reasons
# Instead, we'll mock the Image.open to return large dimensions
from unittest.mock import patch, MagicMock
image_path = self.create_test_image("test.jpg")
with patch('PIL.Image.open') as mock_open:
mock_img = MagicMock()
mock_img.size = (15000, 15000)
mock_img.mode = 'RGB'
mock_open.return_value.__enter__.return_value = mock_img
is_valid, error = self.validator.validate_image_content(image_path)
assert is_valid is False
assert "Image too large" in error
def test_comprehensive_validation_success(self):
"""Test comprehensive validation of valid image."""
image_path = self.create_test_image("test.jpg")
expected_size = image_path.stat().st_size
all_valid, errors = self.validator.comprehensive_validation(image_path, expected_size)
assert all_valid is True
assert len(errors) == 0
def test_comprehensive_validation_missing_file(self):
"""Test comprehensive validation of missing file."""
missing_path = self.temp_dir / "missing.jpg"
all_valid, errors = self.validator.comprehensive_validation(missing_path)
assert all_valid is False
assert len(errors) == 1
assert "File does not exist" in errors[0]
def test_comprehensive_validation_empty_file(self):
"""Test comprehensive validation of empty file."""
empty_path = self.temp_dir / "empty.jpg"
empty_path.write_bytes(b"")
all_valid, errors = self.validator.comprehensive_validation(empty_path)
assert all_valid is False
assert any("File is empty" in error for error in errors)
def test_comprehensive_validation_multiple_errors(self):
"""Test comprehensive validation with multiple errors."""
corrupted_path = self.create_corrupted_file("corrupted.jpg")
all_valid, errors = self.validator.comprehensive_validation(corrupted_path, expected_size=1000000)
assert all_valid is False
assert len(errors) >= 2 # Size mismatch + format error
def test_get_image_info_success(self):
"""Test getting image information."""
image_path = self.create_test_image("test.jpg", width=800, height=600)
info = self.validator.get_image_info(image_path)
assert info is not None
assert info['filename'] == 'test.jpg'
assert info['format'] == 'JPEG'
assert info['width'] == 800
assert info['height'] == 600
assert info['size'] == (800, 600)
assert info['file_size'] > 0
assert 'has_transparency' in info
assert 'has_exif' in info
def test_get_image_info_corrupted_file(self):
"""Test getting image information from corrupted file."""
corrupted_path = self.create_corrupted_file("corrupted.jpg")
info = self.validator.get_image_info(corrupted_path)
assert info is None
def test_repair_corrupted_image_success(self):
"""Test successful image repair."""
# Skip this test on Windows due to file locking issues
import platform
if platform.system() == "Windows":
pytest.skip("Skipping repair test on Windows due to file locking")
# Create a valid image first
image_path = self.create_test_image("test.jpg")
# For this test, we'll assume the image can be "repaired"
# In reality, this would work on images with minor corruption
success = self.validator.repair_corrupted_image(image_path)
# The repair should succeed for a valid image
assert success is True
assert image_path.exists()
def test_repair_corrupted_image_failure(self):
"""Test failed image repair."""
corrupted_path = self.create_corrupted_file("corrupted.jpg")
success = self.validator.repair_corrupted_image(corrupted_path)
assert success is False |