ParamManagerScripts/backend/script_groups/XML Parser to SCL/test_hash_edge_cases.py

205 lines
7.2 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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")