205 lines
7.2 KiB
Python
205 lines
7.2 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Test específico para demostrar casos donde el hash detecta cambios
|
||
que el método tradicional (tiempo + tamaño) podría perder.
|
||
"""
|
||
|
||
import os
|
||
import json
|
||
import hashlib
|
||
import tempfile
|
||
import time
|
||
|
||
|
||
def calculate_file_hash(filepath):
|
||
"""Calcula el hash SHA256 de un archivo."""
|
||
try:
|
||
sha256_hash = hashlib.sha256()
|
||
with open(filepath, "rb") as f:
|
||
for chunk in iter(lambda: f.read(4096), b""):
|
||
sha256_hash.update(chunk)
|
||
return sha256_hash.hexdigest()
|
||
except Exception as e:
|
||
print(f"Error calculando hash de {filepath}: {e}")
|
||
return None
|
||
|
||
|
||
def test_subtle_changes():
|
||
"""Demuestra detección de cambios sutiles que mantienen el mismo tamaño."""
|
||
print("=== Test: Cambios Sutiles con Mismo Tamaño ===\n")
|
||
|
||
with tempfile.TemporaryDirectory() as temp_dir:
|
||
xml_file = os.path.join(temp_dir, "test.xml")
|
||
|
||
# Crear contenido original de exactamente el mismo tamaño
|
||
original = """<?xml version="1.0"?>
|
||
<Block>
|
||
<Name>MotorControl_01</Name>
|
||
<Status>Active</Status>
|
||
</Block>"""
|
||
|
||
# Crear contenido modificado del mismo tamaño (cambiar solo algunos caracteres)
|
||
modified = """<?xml version="1.0"?>
|
||
<Block>
|
||
<Name>MotorControl_02</Name>
|
||
<Status>Active</Status>
|
||
</Block>"""
|
||
|
||
# Verificar que tienen el mismo tamaño
|
||
assert len(original) == len(
|
||
modified
|
||
), "Los contenidos deben tener el mismo tamaño"
|
||
|
||
# Paso 1: Crear archivo original
|
||
with open(xml_file, "w", encoding="utf-8") as f:
|
||
f.write(original)
|
||
|
||
original_hash = calculate_file_hash(xml_file)
|
||
original_size = os.path.getsize(xml_file)
|
||
original_mtime = os.path.getmtime(xml_file)
|
||
|
||
print(f"1. Archivo original:")
|
||
print(f" Contenido: MotorControl_01")
|
||
print(f" Hash: {original_hash[:16]}...")
|
||
print(f" Tamaño: {original_size} bytes")
|
||
|
||
# Simular JSON con metadatos
|
||
json_data = {
|
||
"source_xml_hash": original_hash,
|
||
"source_xml_size": original_size,
|
||
"source_xml_mod_time": original_mtime,
|
||
}
|
||
|
||
# Paso 2: Esperar un poco y modificar archivo manteniendo tamaño
|
||
time.sleep(0.1) # Pequeña pausa
|
||
|
||
with open(xml_file, "w", encoding="utf-8") as f:
|
||
f.write(modified)
|
||
|
||
# Restaurar tiempo de modificación original
|
||
os.utime(xml_file, (original_mtime, original_mtime))
|
||
|
||
new_hash = calculate_file_hash(xml_file)
|
||
new_size = os.path.getsize(xml_file)
|
||
new_mtime = os.path.getmtime(xml_file)
|
||
|
||
print(f"\n2. Archivo modificado:")
|
||
print(f" Contenido: MotorControl_02")
|
||
print(f" Hash: {new_hash[:16]}...")
|
||
print(f" Tamaño: {new_size} bytes")
|
||
print(
|
||
f" Tiempo: {'Igual' if abs(new_mtime - original_mtime) < 0.001 else 'Diferente'}"
|
||
)
|
||
|
||
# Paso 3: Comparar métodos de detección
|
||
print(f"\n3. Detección de cambios:")
|
||
|
||
# Método tradicional
|
||
time_match = abs(new_mtime - json_data["source_xml_mod_time"]) < 0.001
|
||
size_match = new_size == json_data["source_xml_size"]
|
||
traditional_detects_change = not (time_match and size_match)
|
||
|
||
# Método por hash
|
||
hash_detects_change = new_hash != json_data["source_xml_hash"]
|
||
|
||
print(f" Método tradicional:")
|
||
print(f" Tiempo coincide: {time_match}")
|
||
print(f" Tamaño coincide: {size_match}")
|
||
print(f" Detecta cambio: {traditional_detects_change}")
|
||
|
||
print(f" Método por hash:")
|
||
print(f" Hash coincide: {new_hash == json_data['source_xml_hash']}")
|
||
print(f" Detecta cambio: {hash_detects_change}")
|
||
|
||
# Resultado
|
||
print(f"\n4. Resultado:")
|
||
if not traditional_detects_change and hash_detects_change:
|
||
print(f" 🎯 HASH DETECTÓ CAMBIO que método tradicional PERDIÓ")
|
||
print(f" ✅ Sin hash: archivo NO se regeneraría (ERROR)")
|
||
print(f" ✅ Con hash: archivo SÍ se regenerará (CORRECTO)")
|
||
elif traditional_detects_change and hash_detects_change:
|
||
print(f" ✅ Ambos métodos detectaron el cambio correctamente")
|
||
else:
|
||
print(
|
||
f" ℹ️ Resultado: tradicional={traditional_detects_change}, hash={hash_detects_change}"
|
||
)
|
||
|
||
return not traditional_detects_change and hash_detects_change
|
||
|
||
|
||
def test_same_size_different_content():
|
||
"""Test con contenidos completamente diferentes pero mismo tamaño."""
|
||
print("\n" + "=" * 50)
|
||
print("=== Test: Contenido Diferente, Mismo Tamaño ===\n")
|
||
|
||
with tempfile.TemporaryDirectory() as temp_dir:
|
||
xml_file = os.path.join(temp_dir, "test.xml")
|
||
|
||
# Contenidos de igual longitud pero diferentes
|
||
content1 = "<Root><Item>AAAAAAAAAA</Item></Root>" # 33 chars
|
||
content2 = "<Root><Item>BBBBBBBBBB</Item></Root>" # 33 chars
|
||
|
||
assert len(content1) == len(content2), "Deben tener igual tamaño"
|
||
|
||
# Crear archivo con contenido 1
|
||
with open(xml_file, "w", encoding="utf-8") as f:
|
||
f.write(content1)
|
||
|
||
hash1 = calculate_file_hash(xml_file)
|
||
size1 = os.path.getsize(xml_file)
|
||
mtime1 = os.path.getmtime(xml_file)
|
||
|
||
# Cambiar a contenido 2 manteniendo tiempo
|
||
time.sleep(0.1)
|
||
with open(xml_file, "w", encoding="utf-8") as f:
|
||
f.write(content2)
|
||
os.utime(xml_file, (mtime1, mtime1))
|
||
|
||
hash2 = calculate_file_hash(xml_file)
|
||
size2 = os.path.getsize(xml_file)
|
||
mtime2 = os.path.getmtime(xml_file)
|
||
|
||
print(f"Contenido 1: {content1[:20]}...")
|
||
print(f"Contenido 2: {content2[:20]}...")
|
||
print(f"Tamaños: {size1} = {size2} ({'✓' if size1 == size2 else '✗'})")
|
||
print(f"Tiempos: {'iguales' if abs(mtime2 - mtime1) < 0.001 else 'diferentes'}")
|
||
print(f"Hashes: {'iguales' if hash1 == hash2 else 'diferentes'}")
|
||
|
||
would_skip_traditional = (size1 == size2) and (abs(mtime2 - mtime1) < 0.001)
|
||
would_skip_hash = hash1 == hash2
|
||
|
||
print(
|
||
f"\nSin hash: {'SALTARÍA procesamiento' if would_skip_traditional else 'procesaría'}"
|
||
)
|
||
print(
|
||
f"Con hash: {'saltaría procesamiento' if would_skip_hash else 'PROCESARÍA'}"
|
||
)
|
||
|
||
if would_skip_traditional and not would_skip_hash:
|
||
print("🎯 El hash evita saltar un archivo que SÍ cambió")
|
||
return True
|
||
|
||
return False
|
||
|
||
|
||
if __name__ == "__main__":
|
||
print("Ejecutando tests de detección de cambios por hash...\n")
|
||
|
||
test1_result = test_subtle_changes()
|
||
test2_result = test_same_size_different_content()
|
||
|
||
print("\n" + "=" * 50)
|
||
print("=== RESUMEN ===")
|
||
print(
|
||
f"Test 1 (cambios sutiles): {'HASH ÚTIL' if test1_result else 'ambos métodos iguales'}"
|
||
)
|
||
print(
|
||
f"Test 2 (mismo tamaño): {'HASH ÚTIL' if test2_result else 'ambos métodos iguales'}"
|
||
)
|
||
|
||
if test1_result or test2_result:
|
||
print("\n✅ El hash SHA256 mejora la detección de cambios")
|
||
print("✅ Evita regeneraciones innecesarias Y perdida de cambios reales")
|
||
else:
|
||
print("\n✓ Ambos métodos funcionaron igual en estos tests")
|