2025-08-12 07:21:41 +08:00

243 lines
9.0 KiB
Rust

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();
}
}