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

172 lines
6.1 KiB
Python

#!/usr/bin/env python3
"""
Test script para verificar la detección de cambios basada en hash.
Este script demuestra cómo el sistema detecta cambios en archivos XML
utilizando hash SHA256 en lugar de solo tiempo/tamaño de archivo.
"""
import os
import json
import hashlib
import tempfile
import shutil
from datetime import datetime
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 create_test_xml(content, filepath):
"""Crea un archivo XML de prueba con el contenido especificado."""
with open(filepath, "w", encoding="utf-8") as f:
f.write(content)
def create_test_json(xml_filepath, json_filepath):
"""Crea un archivo JSON de prueba con metadatos del XML."""
xml_hash = calculate_file_hash(xml_filepath)
xml_mtime = os.path.getmtime(xml_filepath)
xml_size = os.path.getsize(xml_filepath)
json_data = {
"block_name": "Test_Block",
"block_type": "FC",
"language": "LAD",
"source_xml_mod_time": xml_mtime,
"source_xml_size": xml_size,
"source_xml_hash": xml_hash,
"interface": {},
"networks": [],
}
with open(json_filepath, "w", encoding="utf-8") as f:
json.dump(json_data, f, indent=4)
return json_data
def test_hash_detection():
"""Prueba la detección de cambios basada en hash."""
print("=== Test de Detección de Cambios por Hash ===\n")
# Crear directorio temporal
with tempfile.TemporaryDirectory() as temp_dir:
xml_file = os.path.join(temp_dir, "test_block.xml")
json_file = os.path.join(temp_dir, "test_block_processed.json")
# Paso 1: Crear XML original
original_content = """<?xml version="1.0" encoding="UTF-8"?>
<Document>
<SW.Blocks.FC ID="A">
<AttributeList>
<Name>Test_Block</Name>
<Number>100</Number>
<ProgrammingLanguage>LAD</ProgrammingLanguage>
</AttributeList>
<ObjectList>
<NetworkSource />
</ObjectList>
</SW.Blocks.FC>
</Document>"""
create_test_xml(original_content, xml_file)
original_hash = calculate_file_hash(xml_file)
print(f"1. XML original creado")
print(f" Hash: {original_hash[:16]}...")
print(f" Tamaño: {os.path.getsize(xml_file)} bytes")
# Paso 2: Crear JSON con metadatos
json_data = create_test_json(xml_file, json_file)
print(f"\n2. JSON con metadatos creado")
print(f" Hash almacenado: {json_data['source_xml_hash'][:16]}...")
# Paso 3: Simular verificación - archivo sin cambios
current_hash = calculate_file_hash(xml_file)
hash_match = json_data["source_xml_hash"] == current_hash
print(f"\n3. Verificación sin cambios:")
print(f" Hash actual: {current_hash[:16]}...")
print(f" ¿Hash coincide?: {hash_match}")
print(f"{'SALTAR procesamiento' if hash_match else 'PROCESAR archivo'}")
# Paso 4: Modificar archivo manteniendo mismo tamaño y tiempo
print(f"\n4. Modificando XML (cambio sutil)...")
modified_content = original_content.replace(
"Test_Block", "Test_Blck"
) # Cambio sutil
# Guardar tiempo original
original_mtime = os.path.getmtime(xml_file)
create_test_xml(modified_content, xml_file)
# Restaurar tiempo original (simular que el timestamp no cambió)
os.utime(xml_file, (original_mtime, original_mtime))
new_size = os.path.getsize(xml_file)
new_mtime = os.path.getmtime(xml_file)
new_hash = calculate_file_hash(xml_file)
print(f" Nuevo hash: {new_hash[:16]}...")
print(f" Nuevo tamaño: {new_size} bytes")
print(
f" Tiempo modificación: {abs(new_mtime - json_data['source_xml_mod_time']) < 0.001}"
)
# Paso 5: Verificar detección por diferentes métodos
print(f"\n5. Comparación de métodos de detección:")
# Método tradicional (tiempo + tamaño)
time_match = abs(new_mtime - json_data["source_xml_mod_time"]) < 0.001
size_match = new_size == json_data["source_xml_size"]
traditional_would_skip = time_match and size_match
# Método por hash
hash_would_skip = new_hash == json_data["source_xml_hash"]
print(f" Método tradicional (tiempo+tamaño):")
print(f" ¿Tiempo coincide?: {time_match}")
print(f" ¿Tamaño coincide?: {size_match}")
print(f"{'SALTAR' if traditional_would_skip else 'PROCESAR'}")
print(f" Método por hash:")
print(f" ¿Hash coincide?: {hash_would_skip}")
print(f"{'SALTAR' if hash_would_skip else 'PROCESAR'}")
print(f"\n6. Resultado:")
if traditional_would_skip and not hash_would_skip:
print(f" ✅ HASH DETECTÓ CAMBIO que el método tradicional PERDIÓ")
print(f" 🔄 El archivo será regenerado correctamente")
elif not traditional_would_skip and not hash_would_skip:
print(f" ✅ Ambos métodos detectaron el cambio")
elif traditional_would_skip and hash_would_skip:
print(f" ✅ Ambos métodos indican que no hay cambios")
else:
print(f" ⚠️ Situación inesperada")
# Paso 6: Mostrar contenidos para verificación
print(f"\n7. Verificación de contenido:")
print(f" Contenido original tenía: 'Test_Block'")
print(f" Contenido nuevo tiene: 'Test_Blck'")
with open(xml_file, "r", encoding="utf-8") as f:
content = f.read()
has_original = "Test_Block" in content
has_modified = "Test_Blck" in content
print(f" ¿Contiene 'Test_Block'?: {has_original}")
print(f" ¿Contiene 'Test_Blck'?: {has_modified}")
if __name__ == "__main__":
test_hash_detection()