"""Tests para extract_exif_metadata.""" import os import sys from PIL import Image from PIL.ExifTags import Base, GPS, IFD from PIL.TiffImagePlugin import IFDRational sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) from cybersecurity.extract_exif_metadata import extract_exif_metadata def _make_png_without_exif(path: str) -> None: """Crea un PNG pequeño sin EXIF.""" Image.new("RGB", (4, 4), (10, 20, 30)).save(path, format="PNG") def _make_jpeg_with_exif(path: str) -> None: """Crea un JPEG pequeño con EXIF de camara/software/fecha.""" img = Image.new("RGB", (4, 4), (200, 100, 50)) exif = img.getexif() exif[Base.Make.value] = "TestCam" exif[Base.Model.value] = "Model X" exif[Base.Software.value] = "PyTestRig 1.0" exif[Base.DateTime.value] = "2024:08:12 19:43:07" # DateTimeOriginal vive en el sub-IFD EXIF. exif_ifd = exif.get_ifd(IFD.Exif) exif_ifd[Base.DateTimeOriginal.value] = "2024:08:12 19:43:07" img.save(path, format="JPEG", exif=exif) def _make_jpeg_with_gps(path: str) -> None: """Crea un JPEG con GPSInfo en DMS, hemisferio sur y oeste.""" img = Image.new("RGB", (4, 4), (0, 128, 64)) exif = img.getexif() gps_ifd = exif.get_ifd(IFD.GPSInfo) # 40 deg, 25 min, 0.48 seg => 40.41680 grados. gps_ifd[GPS.GPSLatitude.value] = ( IFDRational(40, 1), IFDRational(25, 1), IFDRational(48, 100), ) gps_ifd[GPS.GPSLatitudeRef.value] = "S" # hemisferio sur => negativo # 3 deg, 42 min, 13.68 seg => 3.7038 grados. gps_ifd[GPS.GPSLongitude.value] = ( IFDRational(3, 1), IFDRational(42, 1), IFDRational(1368, 100), ) gps_ifd[GPS.GPSLongitudeRef.value] = "W" # oeste => negativo img.save(path, format="JPEG", exif=exif) def test_imagen_sin_exif_png_devuelve_none(tmp_path): """imagen sin EXIF (PNG) devuelve campos None y raw vacio.""" p = str(tmp_path / "plain.png") _make_png_without_exif(p) meta = extract_exif_metadata(p) assert meta["datetime"] is None assert meta["camera_make"] is None assert meta["camera_model"] is None assert meta["software"] is None assert meta["gps_lat"] is None assert meta["gps_lon"] is None assert meta["raw"] == {} def test_imagen_con_exif_devuelve_camara_software_fecha(tmp_path): """imagen con EXIF devuelve camara, software y fecha.""" p = str(tmp_path / "withexif.jpg") _make_jpeg_with_exif(p) meta = extract_exif_metadata(p) assert meta["camera_make"] == "TestCam" assert meta["camera_model"] == "Model X" assert meta["software"] == "PyTestRig 1.0" assert meta["datetime"] == "2024:08:12 19:43:07" assert meta["raw"] # no vacio def test_gps_dms_a_grados_decimales_con_signo(tmp_path): """GPSInfo DMS se convierte a grados decimales con signo por hemisferio.""" p = str(tmp_path / "withgps.jpg") _make_jpeg_with_gps(p) meta = extract_exif_metadata(p) assert meta["gps_lat"] is not None assert meta["gps_lon"] is not None # Sur y Oeste => ambos negativos. assert meta["gps_lat"] < 0 assert meta["gps_lon"] < 0 assert abs(meta["gps_lat"] - (-40.41680)) < 1e-4 assert abs(meta["gps_lon"] - (-3.7038)) < 1e-4 if __name__ == "__main__": import tempfile from pathlib import Path with tempfile.TemporaryDirectory() as d: test_imagen_sin_exif_png_devuelve_none(Path(d)) test_imagen_con_exif_devuelve_camara_software_fecha(Path(d)) test_gps_dms_a_grados_decimales_con_signo(Path(d)) print("Todos los tests pasaron.")