#[cfg(test)]
mod tests {
use crate::{
IntelligentCacheManager, L1CacheConfig, MonitoringConfig, PreheatingConfig, TuningConfig,
UnifiedCache, UnifiedCacheConfig, CACHE_VERSION, DEFAULT_L1_CAPACITY, DEFAULT_L2_CAPACITY,
DEFAULT_MEMORY_LIMIT_MB, DEFAULT_TTL_SECONDS,
};
use std::time::Duration;
use tokio::time::sleep;
#[test]
fn test_version_info() {
assert!(!CACHE_VERSION.is_empty());
}
#[test]
fn test_default_constants() {
assert!(DEFAULT_L1_CAPACITY > 0);
assert!(DEFAULT_L2_CAPACITY > DEFAULT_L1_CAPACITY);
assert!(DEFAULT_TTL_SECONDS > 0);
assert!(DEFAULT_MEMORY_LIMIT_MB > 0);
}
#[tokio::test]
async fn test_basic_cache_operations() {
let config = UnifiedCacheConfig::default();
let cache = IntelligentCacheManager::<String, String>::new(config);
cache
.put("key1".to_string(), "value1".to_string())
.await
.unwrap();
let result = cache.get(&"key1".to_string()).await;
assert_eq!(result, Some("value1".to_string()));
let result = cache.get(&"nonexistent".to_string()).await;
assert_eq!(result, None);
assert!(cache.contains_key(&"key1".to_string()).await);
assert!(!cache.contains_key(&"nonexistent".to_string()).await);
assert!(cache.remove(&"key1".to_string()).await);
assert!(!cache.contains_key(&"key1".to_string()).await);
}
#[tokio::test]
async fn test_multilevel_caching() {
let config = UnifiedCacheConfig {
l1_config: L1CacheConfig {
max_entries: 3, promotion_threshold: 2,
..Default::default()
},
..Default::default()
};
let cache = IntelligentCacheManager::<String, String>::new(config);
for i in 0..5 {
let key = format!("key_{}", i);
let value = format!("value_{}", i);
cache.put(key, value).await.unwrap();
}
let stats = cache.get_stats().await;
assert!(stats.l1_stats.entries <= 3);
for _ in 0..3 {
let _ = cache.get(&"key_1".to_string()).await;
}
let _stats_after = cache.get_stats().await;
}
#[tokio::test]
async fn test_predictive_preheating() {
let config = UnifiedCacheConfig {
preheating_config: PreheatingConfig {
enable_predictive_preheating: true,
enable_pattern_learning: true,
min_confidence_threshold: 0.3,
..Default::default()
},
..Default::default()
};
let cache = IntelligentCacheManager::<String, String>::new(config);
for cycle in 0..3 {
for i in 0..5 {
if i % 2 == cycle % 2 {
let key = format!("pattern_key_{}", i);
cache.preheater().record_access(&key).await;
}
}
sleep(Duration::from_millis(10)).await;
}
let stats = cache.preheater().get_stats();
assert!(stats.patterns_learned > 0);
let _recommendations = cache.preheater().get_preheat_recommendations().await;
}
#[tokio::test]
async fn test_adaptive_tuning() {
let config = UnifiedCacheConfig {
tuning_config: TuningConfig {
enable_adaptive_tuning: true,
min_samples_for_tuning: 3,
target_hit_rate: 0.9,
..Default::default()
},
..Default::default()
};
let cache = IntelligentCacheManager::<String, String>::new(config);
for i in 0..10 {
let key = format!("key_{}", i);
let value = format!("value_{}", i);
let _ = cache.get(&key).await; cache.put(key, value).await.unwrap(); }
let stats = cache.get_stats().await;
cache.tuner().record_performance(&stats).await;
let _recommendations = cache.tuner().analyze_and_tune().await;
let _tuning_stats = cache.tuner().get_stats();
}
#[tokio::test]
async fn test_performance_monitoring() {
let config = UnifiedCacheConfig {
monitoring_config: MonitoringConfig {
enable_detailed_stats: true,
enable_performance_metrics: true,
enable_event_logging: true,
..Default::default()
},
..Default::default()
};
let cache = IntelligentCacheManager::<String, Vec<u8>>::new(config);
let monitor = cache.monitor();
for i in 0..10 {
let key = format!("key_{}", i);
let value = vec![i as u8; 100];
cache.put(key.clone(), value).await.unwrap();
let _ = cache.get(&key).await;
}
let metrics = monitor.get_performance_metrics().await;
assert!(metrics.avg_get_latency_us >= 0.0);
assert!(metrics.avg_put_latency_us >= 0.0);
let events = monitor.get_recent_events(5).await;
assert!(events.len() > 0);
}
#[tokio::test]
async fn test_cache_statistics() {
let config = UnifiedCacheConfig::default();
let cache = IntelligentCacheManager::<String, String>::new(config);
let stats = cache.get_stats().await;
assert_eq!(stats.l1_stats.entries, 0);
assert_eq!(stats.l2_stats.entries, 0);
assert_eq!(stats.overall_stats.total_entries, 0);
for i in 0..5 {
let key = format!("key_{}", i);
let value = format!("value_{}", i);
cache.put(key, value).await.unwrap();
}
let stats = cache.get_stats().await;
assert_eq!(stats.overall_stats.total_entries, 5);
for i in 0..5 {
let key = format!("key_{}", i);
let _ = cache.get(&key).await;
}
let stats = cache.get_stats().await;
assert!(stats.l1_stats.hits > 0);
}
#[tokio::test]
async fn test_cache_capacity_limits() {
let config = UnifiedCacheConfig {
l1_config: L1CacheConfig {
max_entries: 2,
..Default::default()
},
..Default::default()
};
let cache = IntelligentCacheManager::<String, String>::new(config);
for i in 0..5 {
let key = format!("key_{}", i);
let value = format!("value_{}", i);
cache.put(key, value).await.unwrap();
}
let stats = cache.get_stats().await;
assert!(stats.l1_stats.entries <= 2);
assert!(stats.overall_stats.total_entries <= 5);
}
#[tokio::test]
async fn test_cache_clear() {
let config = UnifiedCacheConfig::default();
let cache = IntelligentCacheManager::<String, String>::new(config);
for i in 0..3 {
let key = format!("key_{}", i);
let value = format!("value_{}", i);
cache.put(key, value).await.unwrap();
}
assert!(!cache.is_empty().await);
cache.clear().await.unwrap();
assert!(cache.is_empty().await);
let stats = cache.get_stats().await;
assert_eq!(stats.overall_stats.total_entries, 0);
}
#[tokio::test]
async fn test_concurrent_access() {
let config = UnifiedCacheConfig::default();
let cache = std::sync::Arc::new(IntelligentCacheManager::<String, String>::new(config));
let mut handles = Vec::new();
for worker_id in 0..4 {
let cache = std::sync::Arc::clone(&cache);
let handle = tokio::spawn(async move {
for i in 0..10 {
let key = format!("worker_{}_key_{}", worker_id, i);
let value = format!("worker_{}_value_{}", worker_id, i);
cache.put(key.clone(), value.clone()).await.unwrap();
let result = cache.get(&key).await;
assert_eq!(result, Some(value));
}
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
let stats = cache.get_stats().await;
assert_eq!(stats.overall_stats.total_entries, 40);
}
#[tokio::test]
async fn test_configuration_validation() {
let config = UnifiedCacheConfig::default();
assert!(config.validate().is_ok());
let mut config = UnifiedCacheConfig::default();
config.l1_config.max_entries = 0;
assert!(config.validate().is_err());
let mut config = UnifiedCacheConfig::default();
config.preheating_config.min_confidence_threshold = 1.5;
assert!(config.validate().is_err());
}
}