Files
fn_registry/python/functions/cybersecurity/extract_exif_metadata_test.py
T
egutierrez eb8dbf66a1 feat(infra): auto-commit con 88 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-11 00:16:46 +02:00

111 lines
3.5 KiB
Python

"""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.")