Files
rpa_vision_v3/test_system_cleanup.py
Dom a27b74cf22 v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- Frontend v4 accessible sur réseau local (192.168.1.40)
- Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard)
- Ollama GPU fonctionnel
- Self-healing interactif
- Dashboard confiance

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:23:51 +01:00

374 lines
14 KiB
Python

#!/usr/bin/env python3
"""
Test du système de cleanup complet
Valide que tous les composants sont correctement nettoyés à l'arrêt.
Tests avec de vraies ressources système plutôt que des mocks.
"""
import logging
import sys
import tempfile
import time
from pathlib import Path
import numpy as np
# Add current directory to path for imports
sys.path.insert(0, str(Path(__file__).parent))
from core.system import initialize_system_cleanup, get_cleanup_manager, shutdown_system, register_cleanup_function
def test_real_memory_manager_cleanup():
"""Test cleanup avec le vrai MemoryManager."""
print("🧪 Testing Real Memory Manager Cleanup...")
# 1. Créer et utiliser le vrai MemoryManager
try:
from core.execution.memory_cache import get_memory_manager, EffectiveLRUCache
print("1. Creating real MemoryManager...")
memory_manager = get_memory_manager(enable_monitoring=False, enable_gpu_management=False)
# 2. Créer des ressources réelles à nettoyer
print("2. Creating real resources...")
# Créer un cache réel avec des données
test_cache = EffectiveLRUCache(max_size=10, max_memory_mb=1.0, enable_monitoring=False)
# Ajouter des données réelles au cache
for i in range(5):
test_data = np.random.randn(100).astype(np.float32) # Vraies données numpy
test_cache.put(f"test_key_{i}", test_data)
print(f" ✓ Cache created with {len(test_cache)} items")
# Enregistrer le cache pour cleanup
memory_manager.register_resource(
"test_cache",
test_cache,
lambda cache: cache.clear(),
{"type": "test_cache", "created_by": "test"}
)
# 3. Créer des fichiers temporaires réels
temp_files = []
for i in range(3):
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.write(b"test data for cleanup")
temp_file.close()
temp_files.append(temp_file.name)
def cleanup_temp_files():
for file_path in temp_files:
try:
Path(file_path).unlink(missing_ok=True)
print(f" ✓ Cleaned up temp file: {Path(file_path).name}")
except Exception as e:
print(f" ⚠ Error cleaning temp file: {e}")
memory_manager.register_resource(
"temp_files",
temp_files,
lambda files: cleanup_temp_files(),
{"type": "temp_files", "count": len(temp_files)}
)
print(f" ✓ Registered {len(temp_files)} temp files for cleanup")
# 4. Vérifier l'état avant cleanup
stats_before = memory_manager.get_stats()
print(f" ✓ Resources registered: {stats_before['registered_resources']}")
print(f" ✓ Memory usage: {stats_before['current_memory_mb']:.1f}MB")
# 5. Tester le cleanup
print("3. Testing cleanup...")
memory_manager.shutdown()
# 6. Vérifier que les ressources ont été nettoyées
print("4. Verifying cleanup...")
# Vérifier que le cache est vide
assert len(test_cache) == 0, f"Cache not cleared: {len(test_cache)} items remain"
print(" ✓ Cache cleared successfully")
# Vérifier que les fichiers temporaires ont été supprimés
remaining_files = [f for f in temp_files if Path(f).exists()]
assert len(remaining_files) == 0, f"Temp files not cleaned: {remaining_files}"
print(" ✓ Temp files cleaned successfully")
# Vérifier l'état du memory manager
stats_after = memory_manager.get_stats()
assert stats_after['registered_resources'] == 0, "Resources not unregistered"
print(" ✓ All resources unregistered")
print("✅ Real Memory Manager cleanup test completed successfully!")
return True
except ImportError as e:
print(f"⚠️ Memory Manager not available: {e}")
return True # Skip test if not available
except Exception as e:
print(f"❌ Memory Manager test failed: {e}")
raise
def test_real_system_integration():
"""Test avec l'intégration système complète."""
print("🧪 Testing Real System Integration...")
# Reset cleanup manager for clean test
from core.system.cleanup_manager import CleanupManager
CleanupManager._instance = None
# 1. Initialiser le système complet
print("1. Initializing complete system...")
initialize_system_cleanup()
manager = get_cleanup_manager()
initial_functions = len(manager._cleanup_functions)
initial_objects = len(manager._cleanup_objects)
print(f" ✓ Initial cleanup functions: {initial_functions}")
print(f" ✓ Initial cleanup objects: {initial_objects}")
# 2. Créer des ressources réelles supplémentaires
print("2. Creating additional real resources...")
# Créer un fichier de log réel
log_file = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.log')
log_file.write("Test log entry\n")
log_file.write("Another log entry\n")
log_file.close()
cleanup_executed = []
def cleanup_log_file():
try:
Path(log_file.name).unlink(missing_ok=True)
cleanup_executed.append("log_file_cleaned")
print(f" ✓ Log file cleaned: {Path(log_file.name).name}")
except Exception as e:
print(f" ⚠ Error cleaning log file: {e}")
register_cleanup_function(cleanup_log_file, "Test Log File Cleanup")
# Créer un objet avec méthode shutdown réelle
class TestResource:
def __init__(self):
self.active = True
self.data = list(range(1000)) # Vraies données
def shutdown(self):
self.active = False
self.data.clear()
cleanup_executed.append("test_resource_shutdown")
print(" ✓ Test resource shutdown completed")
test_resource = TestResource()
manager.register_cleanup_object(test_resource, "shutdown")
print(f" ✓ Added cleanup function, total: {len(manager._cleanup_functions)}")
print(f" ✓ Added cleanup object, total: {len(manager._cleanup_objects)}")
# 3. Vérifier l'état avant shutdown
assert test_resource.active, "Test resource should be active"
assert len(test_resource.data) == 1000, "Test resource should have data"
assert Path(log_file.name).exists(), "Log file should exist"
# 4. Effectuer le shutdown
print("3. Performing system shutdown...")
shutdown_system()
# 5. Vérifier les résultats
print("4. Verifying shutdown results...")
# Vérifier que les fonctions de cleanup ont été exécutées
assert "log_file_cleaned" in cleanup_executed, "Log file cleanup not executed"
assert "test_resource_shutdown" in cleanup_executed, "Test resource shutdown not executed"
print(" ✓ All cleanup functions executed")
# Vérifier que les ressources ont été nettoyées
assert not test_resource.active, "Test resource should be inactive"
assert len(test_resource.data) == 0, "Test resource data should be cleared"
assert not Path(log_file.name).exists(), "Log file should be deleted"
print(" ✓ All resources properly cleaned")
# Vérifier l'état du manager
assert manager.is_shutdown_in_progress(), "Shutdown should be in progress"
print(" ✓ Shutdown state correctly set")
print("✅ Real system integration test completed successfully!")
return True
def test_real_cache_cleanup():
"""Test cleanup avec un vrai cache LRU."""
print("🧪 Testing Real Cache Cleanup...")
try:
from core.execution.memory_cache import EffectiveLRUCache
# 1. Créer un cache réel avec monitoring désactivé pour le test
print("1. Creating real LRU cache...")
cache = EffectiveLRUCache(
max_size=50,
max_memory_mb=5.0,
enable_monitoring=False # Désactiver pour test propre
)
# 2. Remplir le cache avec des données réelles
print("2. Filling cache with real data...")
for i in range(30):
# Créer des vecteurs numpy réels (simule des embeddings)
vector = np.random.randn(512).astype(np.float32)
cache.put(f"embedding_{i}", vector)
initial_size = len(cache)
initial_memory = cache.get_memory_usage()
print(f" ✓ Cache filled: {initial_size} items")
print(f" ✓ Memory usage: {initial_memory['current_mb']:.2f}MB")
# 3. Vérifier les statistiques
stats = cache.get_stats()
assert stats['size'] == initial_size, "Cache size mismatch"
assert stats['hits'] == 0, "Should have no hits yet"
# 4. Tester les opérations du cache
print("3. Testing cache operations...")
# Test hit
value = cache.get("embedding_0")
assert value is not None, "Should retrieve existing value"
assert isinstance(value, np.ndarray), "Should return numpy array"
# Test miss
value = cache.get("nonexistent")
assert value is None, "Should return None for missing key"
stats_after = cache.get_stats()
assert stats_after['hits'] == 1, "Should have 1 hit"
assert stats_after['misses'] == 1, "Should have 1 miss"
print(" ✓ Cache operations working correctly")
# 5. Tester le cleanup
print("4. Testing cache cleanup...")
cache.stop_monitoring() # Arrêter le monitoring
cache.clear()
# 6. Vérifier que le cache est vide
assert len(cache) == 0, "Cache should be empty after clear"
final_memory = cache.get_memory_usage()
assert final_memory['current_bytes'] == 0, "Memory should be freed"
print(" ✓ Cache cleared successfully")
print(f" ✓ Memory freed: {initial_memory['current_mb']:.2f}MB → 0MB")
print("✅ Real cache cleanup test completed successfully!")
return True
except ImportError as e:
print(f"⚠️ Cache not available: {e}")
return True # Skip test if not available
def test_weakref_cleanup():
"""Test cleanup avec weak references (vraie fonctionnalité du CleanupManager)."""
print("🧪 Testing Weak Reference Cleanup...")
from core.system.cleanup_manager import CleanupManager
import gc
# Reset pour test propre - forcer une nouvelle instance
CleanupManager._instance = None
# 1. Créer un manager frais
print("1. Creating fresh cleanup manager...")
manager = CleanupManager() # Créer directement pour éviter l'état shutdown
# 2. Créer un objet réel avec méthode shutdown
print("2. Creating real object with shutdown method...")
class RealResource:
def __init__(self, name):
self.name = name
self.active = True
self.shutdown_called = False
def shutdown(self):
self.active = False
self.shutdown_called = True
print(f"{self.name} shutdown called")
# Créer et enregistrer une ressource
resource = RealResource("TestResource1")
manager.register_cleanup_object(resource, "shutdown")
initial_objects = len(manager._cleanup_objects)
print(f" ✓ Registered {initial_objects} cleanup object(s)")
# 3. Vérifier que la weak reference fonctionne
assert initial_objects > 0, "Should have registered objects"
# 4. Supprimer la référence forte et forcer GC
print("3. Testing weak reference behavior...")
resource_id = id(resource)
del resource
gc.collect() # Force garbage collection
# La weak reference devrait avoir été nettoyée automatiquement
# (le callback devrait avoir été appelé)
time.sleep(0.1) # Petit délai pour le callback
print(" ✓ Weak reference cleanup mechanism working")
# 5. Créer une nouvelle ressource et tester le shutdown
print("4. Testing shutdown with active resource...")
resource2 = RealResource("TestResource2")
manager.register_cleanup_object(resource2, "shutdown")
# Shutdown devrait appeler la méthode shutdown
manager.shutdown()
assert resource2.shutdown_called, "Shutdown method should have been called"
assert not resource2.active, "Resource should be inactive"
print(" ✓ Resource shutdown executed correctly")
print("✅ Weak reference cleanup test completed successfully!")
return True
def main():
"""Fonction principale de test."""
print("🎯 RPA Vision V3 - System Cleanup Test")
print("=" * 50)
# Configuration du logging pour voir les vraies opérations
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
try:
# Test 1: Memory Manager avec vraies ressources (test isolé)
test_real_memory_manager_cleanup()
print()
# Test 2: Cache LRU réel (test isolé)
test_real_cache_cleanup()
print()
# Test 3: Weak references (test isolé)
test_weakref_cleanup()
print()
# Test 4: Intégration système complète (test final car fait shutdown)
test_real_system_integration()
print()
print("🎉 All real functionality tests passed!")
return 0
except Exception as e:
print(f"❌ Test failed: {e}")
import traceback
traceback.print_exc()
return 1
if __name__ == "__main__":
sys.exit(main())