- 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>
374 lines
14 KiB
Python
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()) |