feat(infra): auto-commit con 88 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
"""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.")
|
||||
Reference in New Issue
Block a user