2025-12-07 20:15:38 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
"""
|
|
|
|
|
Test-Skript für die erweiterte XML-Hash-Duplikatserkennung.
|
|
|
|
|
Testet die neuen Funktionalitäten in MainWindow.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import hashlib
|
|
|
|
|
import tempfile
|
|
|
|
|
import shutil
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
import sys
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
# Füge src-Verzeichnis zum Python-Pfad hinzu
|
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
|
|
|
|
|
|
|
|
|
|
from conf import XmlFile, XslFile, TreeNode, ProjectData
|
|
|
|
|
|
|
|
|
|
def create_test_xml_file(content: str, filename: str) -> Path:
|
|
|
|
|
"""Erstellt eine temporäre XML-Testdatei."""
|
|
|
|
|
temp_dir = Path(tempfile.mkdtemp())
|
|
|
|
|
xml_file = temp_dir / filename
|
|
|
|
|
|
|
|
|
|
with open(xml_file, 'w', encoding='utf-8') as f:
|
|
|
|
|
f.write(content)
|
|
|
|
|
|
|
|
|
|
return xml_file
|
|
|
|
|
|
|
|
|
|
def calculate_test_hash(file_path: Path) -> str:
|
|
|
|
|
"""Berechnet den blake2b-Hash für eine Testdatei."""
|
|
|
|
|
with open(file_path, 'rb') as f:
|
|
|
|
|
file_content = f.read()
|
|
|
|
|
hash_obj = hashlib.blake2b(file_content)
|
|
|
|
|
return f"blake2b:{hash_obj.hexdigest()}"
|
|
|
|
|
|
|
|
|
|
def test_hash_calculation():
|
|
|
|
|
"""Testet die Hash-Berechnung."""
|
|
|
|
|
print("=== Test: Hash-Berechnung ===")
|
|
|
|
|
|
|
|
|
|
# Erstelle Testdatei
|
|
|
|
|
test_content = """<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<root>
|
|
|
|
|
<test>Hash-Berechnung Test</test>
|
|
|
|
|
</root>"""
|
|
|
|
|
|
|
|
|
|
xml_file = create_test_xml_file(test_content, "test_hash.xml")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Berechne Hash
|
|
|
|
|
calculated_hash = calculate_test_hash(xml_file)
|
|
|
|
|
print(f"Berechneter Hash: {calculated_hash}")
|
|
|
|
|
|
|
|
|
|
# Verifikation
|
|
|
|
|
assert calculated_hash.startswith("blake2b:"), "Hash-Präfix fehlt!"
|
|
|
|
|
# blake2b erzeugt 128-stellige Hex-Strings + 8 Zeichen für "blake2b:" = 136 Zeichen
|
|
|
|
|
assert len(calculated_hash) == 136, f"Hash-Länge falsch: {len(calculated_hash)} (erwartet: 136)"
|
|
|
|
|
|
|
|
|
|
print("[OK] Hash-Berechnung funktioniert korrekt")
|
|
|
|
|
return calculated_hash
|
|
|
|
|
|
|
|
|
|
finally:
|
|
|
|
|
# Aufräumen
|
|
|
|
|
shutil.rmtree(xml_file.parent)
|
|
|
|
|
|
|
|
|
|
def test_xml_file_model_with_hash():
|
|
|
|
|
"""Testet das erweiterte XmlFile-Modell mit Hash."""
|
|
|
|
|
print("\n=== Test: XmlFile-Modell mit Hash ===")
|
|
|
|
|
|
|
|
|
|
# Test 1: XmlFile ohne Hash
|
|
|
|
|
xml_file1 = XmlFile(xml=Path("test1.xml"))
|
|
|
|
|
print(f"XmlFile ohne Hash: {xml_file1}")
|
|
|
|
|
assert xml_file1.hashsum is None, "Initiale hashsum sollte None sein"
|
|
|
|
|
|
|
|
|
|
# Test 2: XmlFile mit Hash
|
|
|
|
|
test_hash = "blake2b:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
|
|
|
|
|
xml_file2 = XmlFile(xml=Path("test2.xml"), hashsum=test_hash)
|
|
|
|
|
print(f"XmlFile mit Hash: {xml_file2}")
|
|
|
|
|
assert xml_file2.hashsum == test_hash, "Hash stimmt nicht überein"
|
|
|
|
|
|
|
|
|
|
print("[OK] XmlFile-Modell mit Hash funktioniert korrekt")
|
|
|
|
|
|
|
|
|
|
def test_duplicate_detection_logic():
|
|
|
|
|
"""Testet die Duplikatserkennung-Logik."""
|
|
|
|
|
print("\n=== Test: Duplikatserkennung-Logik ===")
|
|
|
|
|
|
|
|
|
|
# Erstelle Test-Projektstruktur
|
|
|
|
|
hash1 = "blake2b:1111111111111111111111111111111111111111111111111111111111111111"
|
|
|
|
|
hash2 = "blake2b:2222222222222222222222222222222222222222222222222222222222222222"
|
|
|
|
|
|
|
|
|
|
# XML-Dateien mit verschiedenen Hashes
|
|
|
|
|
xml1 = XmlFile(xml=Path("xml/file1.xml"), hashsum=hash1)
|
|
|
|
|
xml2 = XmlFile(xml=Path("xml/file2.xml"), hashsum=hash2)
|
|
|
|
|
xml3 = XmlFile(xml=Path("xml/file3.xml"), hashsum=hash1) # Duplikat von xml1
|
|
|
|
|
|
|
|
|
|
# XSL-Dateien
|
|
|
|
|
xsl1 = XslFile(id=(1,), bez="XSL 1", xsl_file=Path("xsl1.xsl"), xmls=[xml1, xml2])
|
|
|
|
|
xsl2 = XslFile(id=(2,), bez="XSL 2", xsl_file=Path("xsl2.xsl"), xmls=[xml3])
|
|
|
|
|
|
|
|
|
|
# TreeNode
|
|
|
|
|
tree_node = TreeNode(id=(1,), bez="Test Node", children=[xsl1, xsl2])
|
|
|
|
|
|
|
|
|
|
# Projekt
|
|
|
|
|
project = ProjectData(nodes=[tree_node])
|
|
|
|
|
|
|
|
|
|
# Sammle alle XML-Dateien
|
|
|
|
|
all_xml_files = []
|
|
|
|
|
|
|
|
|
|
def collect_xml_files(nodes):
|
|
|
|
|
for node in nodes:
|
|
|
|
|
if isinstance(node, XslFile) and node.xmls:
|
|
|
|
|
for xml_file in node.xmls:
|
|
|
|
|
if not any(existing.xml == xml_file.xml for existing in all_xml_files):
|
|
|
|
|
all_xml_files.append(xml_file)
|
|
|
|
|
elif isinstance(node, TreeNode) and node.children:
|
|
|
|
|
collect_xml_files(node.children)
|
|
|
|
|
|
|
|
|
|
collect_xml_files(project.nodes)
|
|
|
|
|
|
|
|
|
|
print(f"Gesammelte XML-Dateien: {len(all_xml_files)}")
|
|
|
|
|
for xml in all_xml_files:
|
|
|
|
|
print(f" - {xml.xml}: {xml.hashsum}")
|
|
|
|
|
|
|
|
|
|
# Test Hash-Suche
|
|
|
|
|
def find_xml_by_hash(target_hash):
|
|
|
|
|
for xml_file in all_xml_files:
|
|
|
|
|
if xml_file.hashsum == target_hash:
|
|
|
|
|
return xml_file
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
# Test 1: Existierenden Hash finden
|
|
|
|
|
found_xml = find_xml_by_hash(hash1)
|
|
|
|
|
assert found_xml is not None, "Hash1 sollte gefunden werden"
|
|
|
|
|
assert found_xml.xml == Path("xml/file1.xml"), "Falsches XML-File gefunden"
|
|
|
|
|
print(f"Hash-Suche erfolgreich: {found_xml.xml}")
|
|
|
|
|
|
|
|
|
|
# Test 2: Nicht existierenden Hash suchen
|
|
|
|
|
non_existent_hash = "blake2b:9999999999999999999999999999999999999999999999999999999999999999"
|
|
|
|
|
not_found = find_xml_by_hash(non_existent_hash)
|
|
|
|
|
assert not_found is None, "Nicht existierender Hash sollte None zurückgeben"
|
|
|
|
|
print("Nicht existierender Hash korrekt behandelt")
|
|
|
|
|
|
|
|
|
|
print("[OK] Duplikatserkennung-Logik funktioniert korrekt")
|
|
|
|
|
|
|
|
|
|
def test_alternative_filename_generation():
|
|
|
|
|
"""Testet die Generierung alternativer Dateinamen."""
|
|
|
|
|
print("\n=== Test: Alternative Dateinamen-Generierung ===")
|
|
|
|
|
|
|
|
|
|
# Simuliere existierende Dateien
|
|
|
|
|
existing_files = {
|
|
|
|
|
"test.xml",
|
|
|
|
|
"test_1.xml",
|
|
|
|
|
"test_2.xml",
|
|
|
|
|
"document.xml"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def generate_alternative_name(original_name: str) -> str:
|
|
|
|
|
"""Simuliert die Generierung alternativer Namen."""
|
|
|
|
|
base_name = Path(original_name).stem
|
|
|
|
|
extension = Path(original_name).suffix
|
|
|
|
|
|
|
|
|
|
counter = 1
|
|
|
|
|
while True:
|
|
|
|
|
new_name = f"{base_name}_{counter}{extension}"
|
|
|
|
|
if new_name not in existing_files:
|
|
|
|
|
return new_name
|
|
|
|
|
counter += 1
|
|
|
|
|
|
|
|
|
|
if counter > 100: # Sicherheitsgrenze
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
return f"{base_name}_fallback{extension}"
|
|
|
|
|
|
|
|
|
|
# Test 1: Datei existiert bereits
|
|
|
|
|
alt_name1 = generate_alternative_name("test.xml")
|
|
|
|
|
expected1 = "test_3.xml" # test.xml, test_1.xml, test_2.xml existieren bereits
|
|
|
|
|
assert alt_name1 == expected1, f"Erwarteter Name: {expected1}, erhalten: {alt_name1}"
|
|
|
|
|
print(f"Alternative für 'test.xml': {alt_name1}")
|
|
|
|
|
|
|
|
|
|
# Test 2: Datei existiert nicht
|
|
|
|
|
alt_name2 = generate_alternative_name("new_file.xml")
|
|
|
|
|
expected2 = "new_file_1.xml"
|
|
|
|
|
assert alt_name2 == expected2, f"Erwarteter Name: {expected2}, erhalten: {alt_name2}"
|
|
|
|
|
print(f"Alternative für 'new_file.xml': {alt_name2}")
|
|
|
|
|
|
|
|
|
|
# Test 3: Datei ohne Konflikte
|
|
|
|
|
alt_name3 = generate_alternative_name("unique.xml")
|
|
|
|
|
expected3 = "unique_1.xml"
|
|
|
|
|
assert alt_name3 == expected3, f"Erwarteter Name: {expected3}, erhalten: {alt_name3}"
|
|
|
|
|
print(f"Alternative für 'unique.xml': {alt_name3}")
|
|
|
|
|
|
|
|
|
|
print("[OK] Alternative Dateinamen-Generierung funktioniert korrekt")
|
|
|
|
|
|
|
|
|
|
def test_integration_workflow():
|
|
|
|
|
"""Testet den kompletten Workflow der Integration."""
|
|
|
|
|
print("\n=== Test: Integration Workflow ===")
|
|
|
|
|
|
|
|
|
|
# Simuliere den kompletten Workflow
|
|
|
|
|
|
|
|
|
|
# 1. Neue XML-Datei
|
|
|
|
|
new_xml_content = """<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<document>
|
|
|
|
|
<title>Integration Test</title>
|
|
|
|
|
<content>Test-Inhalt für Integration</content>
|
|
|
|
|
</document>"""
|
|
|
|
|
|
|
|
|
|
new_xml_file = create_test_xml_file(new_xml_content, "integration_test.xml")
|
|
|
|
|
new_hash = calculate_test_hash(new_xml_file)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# 2. Bestehende Projekt-XML-Dateien simulieren
|
|
|
|
|
existing_xml1 = XmlFile(xml=Path("xml/existing1.xml"), hashsum="blake2b:aaaa")
|
|
|
|
|
existing_xml2 = XmlFile(xml=Path("xml/existing2.xml"), hashsum="blake2b:bbbb")
|
|
|
|
|
existing_xml3 = XmlFile(xml=Path("xml/existing3.xml"), hashsum=new_hash) # Duplikat!
|
|
|
|
|
|
|
|
|
|
existing_xmls = [existing_xml1, existing_xml2, existing_xml3]
|
|
|
|
|
|
|
|
|
|
# 3. Hash-Vergleich
|
|
|
|
|
duplicate_found = None
|
|
|
|
|
for existing_xml in existing_xmls:
|
|
|
|
|
if existing_xml.hashsum == new_hash:
|
|
|
|
|
duplicate_found = existing_xml
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
# 4. Verifikation
|
|
|
|
|
assert duplicate_found is not None, "Duplikat sollte gefunden werden"
|
|
|
|
|
assert duplicate_found.xml == Path("xml/existing3.xml"), "Falsches Duplikat gefunden"
|
|
|
|
|
|
2025-12-14 15:16:57 +01:00
|
|
|
print("Workflow-Test erfolgreich:")
|
2025-12-07 20:15:38 +01:00
|
|
|
print(f" - Neue Datei: {new_xml_file.name}")
|
|
|
|
|
print(f" - Berechneter Hash: {new_hash}")
|
|
|
|
|
print(f" - Duplikat gefunden: {duplicate_found.xml}")
|
2025-12-14 15:16:57 +01:00
|
|
|
print(" - Automatische Zuordnung würde erfolgen")
|
2025-12-07 20:15:38 +01:00
|
|
|
|
|
|
|
|
print("[OK] Integration Workflow funktioniert korrekt")
|
|
|
|
|
|
|
|
|
|
finally:
|
|
|
|
|
# Aufräumen
|
|
|
|
|
shutil.rmtree(new_xml_file.parent)
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
print("Starte Tests für XML-Hash-Duplikatserkennung...\n")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
test_hash_calculation()
|
|
|
|
|
test_xml_file_model_with_hash()
|
|
|
|
|
test_duplicate_detection_logic()
|
|
|
|
|
test_alternative_filename_generation()
|
|
|
|
|
test_integration_workflow()
|
|
|
|
|
|
|
|
|
|
print("\n" + "="*60)
|
|
|
|
|
print("[SUCCESS] Alle Tests erfolgreich abgeschlossen!")
|
|
|
|
|
print("\nDie erweiterte XML-Hash-Duplikatserkennung ist bereit für den Einsatz.")
|
|
|
|
|
print("\nNeue Funktionalitäten:")
|
|
|
|
|
print("+ Hash-basierte Duplikatserkennung im gesamten Projekt")
|
|
|
|
|
print("+ Automatische Zuordnung bei Hash-Match")
|
|
|
|
|
print("+ Intelligente Dateinamen-Generierung (datei_1.xml Format)")
|
|
|
|
|
print("+ Integration in Drag&Drop und Kontextmenü")
|
|
|
|
|
print("+ Benutzerfreundliche Dateiname-Auswahl-Dialoge")
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"\n[ERROR] Test fehlgeschlagen: {e}")
|
|
|
|
|
import traceback
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
sys.exit(1)
|