Cybersecurity-Projects/tests/unit/test_image_handler.py

154 lines
4.4 KiB
Python

import shutil
from pathlib import Path
import pytest
from src.services.image_handler import ImageHandler
from src.utils.exceptions import MetadataNotFoundError, UnsupportedFormatError
# Import path helpers from conftest
from tests.conftest import get_jpg_test_file, get_png_test_file
# Test file paths (cross-platform)
JPG_TEST_FILE = get_jpg_test_file()
PNG_TEST_FILE = get_png_test_file()
# ============== Success Case Tests ==============
@pytest.mark.parametrize("x", [JPG_TEST_FILE, PNG_TEST_FILE])
def test_read_image_metadata(x):
"""
test for reading image metadata
"""
# checks if file exists
assert Path(x).exists(), f"Test file not found: {x}"
processor = ImageHandler(x)
metadata = processor.read()
# checks if metadata is not empty
assert processor.metadata == metadata
# checks if tags_to_delete or text_keys_to_delete is not empty
assert (
processor.tags_to_delete is not None or processor.text_keys_to_delete is not None
)
# checks if metadata is a dictionary
assert isinstance(metadata, dict)
@pytest.mark.parametrize("x", [JPG_TEST_FILE, PNG_TEST_FILE])
def test_wipe_image_metadata(x):
"""
test for wiping image metadata
"""
# checks if file exists
assert Path(x).exists(), f"Test file not found: {x}"
processor = ImageHandler(x)
metadata = processor.read()
processor.wipe()
# checks if processed_metadata is not equal to metadata
assert processor.processed_metadata != metadata
@pytest.mark.parametrize("x", [JPG_TEST_FILE, PNG_TEST_FILE])
def test_save_processed_image_metadata(x):
"""
test for saving image processed metadata to a copy of the file
"""
# creates output directory
output_dir = Path("./tests/assets/output")
output_dir.mkdir(parents = True, exist_ok = True)
processor = ImageHandler(x)
metadata = processor.read()
processor.wipe()
# checks if processed_metadata is not equal to metadata
assert processor.processed_metadata != metadata
# Pass full file path
output_file = output_dir / Path(x).name
processor.save(str(output_file))
# checks if output file exists and then deletes it
assert output_file.exists()
shutil.rmtree(output_dir)
# ============== Error Case Tests ==============
def test_unsupported_format_raises_error(tmp_path):
"""
Test that unsupported file formats raise an error (PIL or custom)
"""
from PIL import UnidentifiedImageError
# Create a fake text file
fake_file = tmp_path / "test.txt"
fake_file.write_text("not an image")
handler = ImageHandler(str(fake_file))
# Either our UnsupportedFormatError or PIL's UnidentifiedImageError is acceptable
with pytest.raises((UnsupportedFormatError, UnidentifiedImageError)):
handler.read()
def test_save_without_output_path_raises_error():
"""
Test that save() raises ValueError when output_path is None
"""
handler = ImageHandler(JPG_TEST_FILE)
handler.read()
handler.wipe()
with pytest.raises(ValueError):
handler.save(None)
@pytest.mark.parametrize("x", [JPG_TEST_FILE, PNG_TEST_FILE])
def test_output_file_has_less_metadata(x):
"""
Test that the output file has metadata stripped
"""
output_dir = Path("./tests/assets/output")
output_dir.mkdir(parents = True, exist_ok = True)
# Process original file
processor = ImageHandler(x)
original_metadata = processor.read()
original_count = len(original_metadata)
processor.wipe()
# Save processed file
output_file = output_dir / Path(x).name
processor.save(str(output_file))
# Read output file and verify metadata is reduced or gone
try:
output_processor = ImageHandler(str(output_file))
output_metadata = output_processor.read()
# Output should have fewer metadata entries
assert len(output_metadata) < original_count
except MetadataNotFoundError:
# If no metadata found, that's expected for fully stripped files
pass
# clean up
shutil.rmtree(output_dir)
def test_format_detection_works():
"""
Test that format detection uses Pillow, not file extension
"""
handler = ImageHandler(JPG_TEST_FILE)
detected = handler._detect_format()
assert detected == "jpeg"
handler_png = ImageHandler(PNG_TEST_FILE)
detected_png = handler_png._detect_format()
assert detected_png == "png"