manage-your-printer/utils/test_database_cleanup.py
2025-06-04 10:03:22 +02:00

275 lines
9.9 KiB
Python
Raw Permalink 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-Script für den DatabaseCleanupManager
Validiert die robuste Datenbank-Cleanup-Funktionalität
"""
import os
import sys
import time
import sqlite3
import threading
from datetime import datetime
# Pfad zur App hinzufügen
app_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, app_dir)
from utils.database_cleanup import DatabaseCleanupManager, safe_database_cleanup
from config.settings import DATABASE_PATH
from utils.logging_config import get_logger
logger = get_logger("database_cleanup_test")
def test_basic_cleanup():
"""Test der grundlegenden Cleanup-Funktionalität"""
print("🧪 Test 1: Grundlegende Cleanup-Funktionalität")
try:
# Erstelle Test-DatabaseCleanupManager
cleanup_manager = DatabaseCleanupManager()
# Teste WAL-Checkpoint
checkpoint_success, checkpoint_error = cleanup_manager.safe_wal_checkpoint(retry_attempts=3)
if checkpoint_success:
print("✅ WAL-Checkpoint erfolgreich")
else:
print(f"❌ WAL-Checkpoint fehlgeschlagen: {checkpoint_error}")
# Teste umfassendes Cleanup
cleanup_result = cleanup_manager.comprehensive_cleanup(force_mode_switch=False) # Kein Mode-Switch für Test
if cleanup_result["success"]:
print(f"✅ Umfassendes Cleanup erfolgreich: {', '.join(cleanup_result['operations'])}")
else:
print(f"❌ Umfassendes Cleanup fehlgeschlagen: {', '.join(cleanup_result['errors'])}")
return cleanup_result["success"]
except Exception as e:
print(f"❌ Test 1 fehlgeschlagen: {e}")
return False
def test_concurrent_access():
"""Test des Cleanup-Verhaltens bei gleichzeitigen Datenbankzugriffen"""
print("\n🧪 Test 2: Cleanup bei gleichzeitigen Datenbankzugriffen")
try:
# Worker-Thread der Datenbankoperationen ausführt
def database_worker():
try:
for i in range(5):
conn = sqlite3.connect(DATABASE_PATH, timeout=2)
conn.execute("SELECT COUNT(*) FROM users")
time.sleep(0.5)
conn.close()
print(f" Worker: Datenbankoperation {i+1} abgeschlossen")
except Exception as e:
print(f" Worker-Fehler: {e}")
# Starte Worker-Thread
worker_thread = threading.Thread(target=database_worker, daemon=True)
worker_thread.start()
# Kurz warten damit Worker startet
time.sleep(1)
# Teste Cleanup während Worker läuft
cleanup_manager = DatabaseCleanupManager()
cleanup_result = cleanup_manager.comprehensive_cleanup(force_mode_switch=False)
if cleanup_result["success"]:
print("✅ Cleanup erfolgreich trotz gleichzeitiger Datenbankzugriffe")
else:
print(f"❌ Cleanup fehlgeschlagen: {', '.join(cleanup_result['errors'])}")
# Warte auf Worker
worker_thread.join(timeout=10)
return cleanup_result["success"]
except Exception as e:
print(f"❌ Test 2 fehlgeschlagen: {e}")
return False
def test_error_recovery():
"""Test der Fehlerbehandlung und Recovery-Mechanismen"""
print("\n🧪 Test 3: Fehlerbehandlung und Recovery")
try:
cleanup_manager = DatabaseCleanupManager()
# Teste mit verschiedenen Retry-Parametern
for retry_attempts in [1, 3, 5]:
print(f" Teste mit {retry_attempts} Retry-Versuchen...")
checkpoint_success, checkpoint_error = cleanup_manager.safe_wal_checkpoint(retry_attempts=retry_attempts)
if checkpoint_success:
print(f" ✅ WAL-Checkpoint mit {retry_attempts} Versuchen erfolgreich")
else:
print(f" ⚠️ WAL-Checkpoint mit {retry_attempts} Versuchen: {checkpoint_error}")
return True
except Exception as e:
print(f"❌ Test 3 fehlgeschlagen: {e}")
return False
def test_journal_mode_operations():
"""Test der Journal-Mode-Operationen"""
print("\n🧪 Test 4: Journal-Mode-Operationen")
try:
cleanup_manager = DatabaseCleanupManager()
# Teste aktuellen Journal-Mode
conn = sqlite3.connect(DATABASE_PATH, timeout=5)
current_mode = conn.execute("PRAGMA journal_mode").fetchone()[0]
print(f" Aktueller Journal-Mode: {current_mode}")
conn.close()
# Teste Journal-Mode-Switch (nur wenn bereits WAL-Mode)
if current_mode.upper() == "WAL":
print(" Teste Journal-Mode-Switch...")
# Teste Switch zu WAL (sollte bereits WAL sein)
mode_success, mode_error = cleanup_manager.safe_journal_mode_switch("WAL", retry_attempts=2)
if mode_success:
print(" ✅ Journal-Mode-Switch zu WAL erfolgreich")
else:
print(f" ❌ Journal-Mode-Switch fehlgeschlagen: {mode_error}")
return mode_success
else:
print(f" Database bereits im {current_mode}-Mode, kein Switch-Test nötig")
return True
except Exception as e:
print(f"❌ Test 4 fehlgeschlagen: {e}")
return False
def test_convenience_function():
"""Test der Convenience-Funktion safe_database_cleanup"""
print("\n🧪 Test 5: Convenience-Funktion safe_database_cleanup")
try:
# Teste die einfache Convenience-Funktion
cleanup_result = safe_database_cleanup(force_mode_switch=False)
if cleanup_result["success"]:
print(f"✅ safe_database_cleanup erfolgreich: {', '.join(cleanup_result['operations'])}")
# Prüfe Cleanup-Details
if "timestamp" in cleanup_result:
print(f" Zeitstempel: {cleanup_result['timestamp']}")
if "wal_files_removed" in cleanup_result:
print(f" WAL-Dateien entfernt: {cleanup_result['wal_files_removed']}")
else:
print(f"❌ safe_database_cleanup fehlgeschlagen: {', '.join(cleanup_result['errors'])}")
return cleanup_result["success"]
except Exception as e:
print(f"❌ Test 5 fehlgeschlagen: {e}")
return False
def test_performance():
"""Test der Performance von Cleanup-Operationen"""
print("\n🧪 Test 6: Performance-Test")
try:
cleanup_manager = DatabaseCleanupManager()
# Messe Zeit für verschiedene Operationen
operations = [
("WAL-Checkpoint", lambda: cleanup_manager.safe_wal_checkpoint(retry_attempts=1)),
("Verbindungsschließung", lambda: cleanup_manager.force_close_all_connections(max_wait_seconds=5)),
("Umfassendes Cleanup", lambda: cleanup_manager.comprehensive_cleanup(force_mode_switch=False))
]
for operation_name, operation_func in operations:
start_time = time.time()
try:
result = operation_func()
duration = time.time() - start_time
success = result if isinstance(result, bool) else result[0] if isinstance(result, tuple) else result.get("success", False)
if success:
print(f"{operation_name}: {duration:.3f}s")
else:
print(f" ⚠️ {operation_name}: {duration:.3f}s (mit Problemen)")
except Exception as e:
duration = time.time() - start_time
print(f"{operation_name}: {duration:.3f}s (Fehler: {e})")
return True
except Exception as e:
print(f"❌ Test 6 fehlgeschlagen: {e}")
return False
def main():
"""Hauptfunktion für alle Tests"""
print("🚀 Starte DatabaseCleanupManager Tests")
print(f"Database-Pfad: {DATABASE_PATH}")
print(f"Zeitstempel: {datetime.now().isoformat()}")
print("=" * 60)
# Prüfe ob Datenbankdatei existiert
if not os.path.exists(DATABASE_PATH):
print(f"❌ Datenbankdatei nicht gefunden: {DATABASE_PATH}")
return False
# Führe alle Tests aus
tests = [
("Grundlegende Cleanup-Funktionalität", test_basic_cleanup),
("Cleanup bei gleichzeitigen Zugriffen", test_concurrent_access),
("Fehlerbehandlung und Recovery", test_error_recovery),
("Journal-Mode-Operationen", test_journal_mode_operations),
("Convenience-Funktion", test_convenience_function),
("Performance-Test", test_performance)
]
passed_tests = 0
failed_tests = 0
for test_name, test_func in tests:
try:
if test_func():
passed_tests += 1
print(f"{test_name}: BESTANDEN")
else:
failed_tests += 1
print(f"{test_name}: FEHLGESCHLAGEN")
except Exception as e:
failed_tests += 1
print(f"{test_name}: EXCEPTION - {e}")
print("\n" + "=" * 60)
print(f"📊 Test-Ergebnis: {passed_tests} bestanden, {failed_tests} fehlgeschlagen")
if failed_tests == 0:
print("🎉 Alle Tests bestanden! DatabaseCleanupManager funktioniert korrekt.")
return True
else:
print(f"⚠️ {failed_tests} Test(s) fehlgeschlagen. Überprüfung erforderlich.")
return False
if __name__ == "__main__":
try:
success = main()
sys.exit(0 if success else 1)
except KeyboardInterrupt:
print("\n🔄 Test durch Benutzer unterbrochen")
sys.exit(130)
except Exception as e:
print(f"💥 Kritischer Fehler beim Testen: {e}")
sys.exit(1)