use std::sync::Arc; use std::time::Duration; use tokio::time::{sleep, timeout}; use crate::adaptive_pool_manager::{AdaptivePoolConfig, AdaptivePoolManager}; use crate::frame_pool::HierarchicalFramePool; use crate::memory_monitor::MemoryMonitor; /// Main adaptive pool system test (entry point for CLI) pub async fn test_adaptive_pool_system() -> anyhow::Result<()> { test_adaptive_pool_integration().await } /// Memory pressure stress test (entry point for CLI) pub async fn stress_test_memory_pressure() -> anyhow::Result<()> { stress_test_adaptive_managers().await } /// Integration test with monitoring (entry point for CLI) pub async fn integration_test_adaptive_with_monitoring() -> anyhow::Result<()> { test_memory_optimization_integration().await } /// Integration test for adaptive pool management system pub async fn test_adaptive_pool_integration() -> anyhow::Result<()> { println!("๐Ÿงช Testing Adaptive Pool Management"); println!("=================================="); // Test 1: Adaptive pool manager creation println!("\n๐Ÿ“‹ Test 1: Adaptive Pool Manager Creation"); test_adaptive_manager_creation().await?; // Test 2: Configuration validation println!("\n๐Ÿ“‹ Test 2: Configuration Validation"); test_configuration_validation().await?; println!("\nโœ… All adaptive pool management tests passed!"); Ok(()) } /// Test adaptive pool manager creation and basic functionality async fn test_adaptive_manager_creation() -> anyhow::Result<()> { let hierarchical_pool = Arc::new(HierarchicalFramePool::new(20)); let config = AdaptivePoolConfig::default(); let _manager = AdaptivePoolManager::new(config.clone(), hierarchical_pool.clone()); println!(" โœ“ Created adaptive pool manager"); println!(" Target memory usage: {:.1}%", config.target_memory_usage * 100.0); println!(" High pressure threshold: {:.1}%", config.high_memory_threshold * 100.0); println!(" Min pool capacity: {}", config.min_pool_capacity); println!(" Max pool capacity: {}", config.max_pool_capacity); assert!(config.target_memory_usage > 0.0 && config.target_memory_usage < 1.0); assert!(config.high_memory_threshold > config.target_memory_usage); assert!(config.min_pool_capacity < config.max_pool_capacity); println!(" โœ“ Configuration validation passed"); Ok(()) } /// Test configuration validation and edge cases async fn test_configuration_validation() -> anyhow::Result<()> { // Test default configuration let default_config = AdaptivePoolConfig::default(); assert!(default_config.target_memory_usage < default_config.high_memory_threshold); assert!(default_config.high_memory_threshold < default_config.critical_memory_threshold); println!(" โœ“ Default configuration hierarchy is valid"); // Test custom configuration let custom_config = AdaptivePoolConfig { target_memory_usage: 0.6, high_memory_threshold: 0.75, critical_memory_threshold: 0.9, min_pool_capacity: 10, max_pool_capacity: 50, evaluation_interval: Duration::from_secs(5), history_samples: 20, min_cache_hit_rate: 0.7, }; // Validate custom config makes sense assert!(custom_config.target_memory_usage < custom_config.high_memory_threshold); assert!(custom_config.min_pool_capacity < custom_config.max_pool_capacity); assert!(custom_config.min_cache_hit_rate >= 0.0 && custom_config.min_cache_hit_rate <= 1.0); println!(" โœ“ Custom configuration validation passed"); // Test with hierarchical pool let hierarchical_pool = Arc::new(HierarchicalFramePool::new(custom_config.min_pool_capacity)); let _manager = AdaptivePoolManager::new(custom_config, hierarchical_pool); println!(" โœ“ Manager created with custom configuration"); Ok(()) } /// Stress test with multiple pools and memory pressure simulation pub async fn stress_test_adaptive_managers() -> anyhow::Result<()> { println!("\n๐Ÿš€ Stress Test: Adaptive Management Under Load"); // Create memory monitor for generating load let memory_monitor = Arc::new(MemoryMonitor::new()); // Create hierarchical pool let hierarchical_pool = Arc::new(HierarchicalFramePool::new(15)); // Create adaptive manager let config = AdaptivePoolConfig { evaluation_interval: Duration::from_millis(100), // Fast evaluation for testing min_pool_capacity: 5, max_pool_capacity: 30, ..AdaptivePoolConfig::default() }; let manager = AdaptivePoolManager::new(config, hierarchical_pool.clone()); println!(" ๐Ÿ“Š Starting stress test configuration:"); println!(" Pool sizes: 64KB, 256KB, 900KB, 2MB"); println!(" Load duration: 2 seconds"); println!(" Frame rate: ~100 FPS"); // Start manager in background (with timeout for testing) let manager_handle = tokio::spawn(async move { // Run adaptive management for limited time in test timeout(Duration::from_secs(2), async { manager.start_adaptive_management().await; }).await }); // Generate high load for different frame sizes let memory_monitor_clone = memory_monitor.clone(); let load_handle = tokio::spawn(async move { let frame_sizes = [64 * 1024, 256 * 1024, 900 * 1024, 2 * 1024 * 1024]; for i in 0..200 { let frame_size = frame_sizes[i % frame_sizes.len()]; memory_monitor_clone.record_frame_processed(frame_size, 4); // 4 subscribers if i % 30 == 0 { sleep(Duration::from_millis(10)).await; } } }); // Wait for both load generation and manager let (_manager_result, _load_result) = tokio::join!(manager_handle, load_handle); // Check final pool state let final_stats = hierarchical_pool.all_stats(); let total_memory = hierarchical_pool.total_memory_usage(); println!(" ๐Ÿ“ˆ Stress test results:"); println!(" Pool configurations: {} different sizes", final_stats.len()); println!(" Total pool memory: {} KB", total_memory / 1024); for (size, stats) in final_stats.iter().take(4) { println!(" {}KB pool: {} allocations, {:.1}% hit rate", size / 1024, stats.total_allocations, stats.cache_hit_rate * 100.0); } let global_stats = memory_monitor.stats(); println!(" Global frames processed: {}", global_stats.frames_processed); println!(" Global memory saved: {:.1} MB", global_stats.bytes_saved_total as f64 / 1_000_000.0); assert!(global_stats.frames_processed > 0, "Should have processed frames"); println!(" โœ… Adaptive management stress test completed"); Ok(()) } /// Test memory optimization integration pub async fn test_memory_optimization_integration() -> anyhow::Result<()> { println!("\n๐Ÿ“ˆ Memory Optimization Integration Test"); let memory_monitor = Arc::new(MemoryMonitor::new()); let hierarchical_pool = Arc::new(HierarchicalFramePool::new(10)); // Generate some usage patterns for frame_count in 0..100 { let frame_size = match frame_count % 4 { 0 => 64 * 1024, // 64KB 1 => 256 * 1024, // 256KB 2 => 900 * 1024, // 900KB _ => 2 * 1024 * 1024, // 2MB }; memory_monitor.record_frame_processed(frame_size, 3); // Get buffer from pool to simulate usage if frame_count % 10 == 0 { let _buffer = hierarchical_pool.acquire(frame_size); // Buffer automatically returns to pool on drop } } // Check optimization results let memory_stats = memory_monitor.stats(); let pool_stats = hierarchical_pool.all_stats(); println!(" ๐Ÿ“Š Integration results:"); println!(" Frames processed: {}", memory_stats.frames_processed); println!(" Memory saved: {:.2} MB", memory_stats.bytes_saved_total as f64 / 1_000_000.0); println!(" Pool configurations: {}", pool_stats.len()); // Verify optimization is working assert!(memory_stats.bytes_saved_total > 0, "Should have saved memory"); assert!(memory_stats.frames_processed == 100, "Should have processed all frames"); // Check pool efficiency for (size, stats) in pool_stats { if stats.total_allocations > 0 { println!(" {}KB pool efficiency: {:.1}% hit rate", size / 1024, stats.cache_hit_rate * 100.0); } } println!(" โœ… Memory optimization integration verified"); Ok(()) } #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn test_integration_suite() { test_adaptive_pool_integration().await.unwrap(); } #[tokio::test] async fn test_stress_test() { stress_test_adaptive_managers().await.unwrap(); } #[tokio::test] async fn test_memory_optimization() { test_memory_optimization_integration().await.unwrap(); } }