use ruchy::performance_optimizations::{CompilationCache, ParserPool, StringInterner};
#[test]
fn test_compilation_cache_basic() {
let mut cache = CompilationCache::new(100);
assert_eq!(cache.len(), 0);
assert!(cache.is_empty());
cache.insert(
"test1".to_string(),
"output1".to_string(),
std::time::Duration::from_millis(100),
512,
);
assert_eq!(cache.len(), 1);
assert!(!cache.is_empty());
let result = cache.get("test1");
assert_eq!(result, Some("output1".to_string()));
let miss = cache.get("nonexistent");
assert_eq!(miss, None);
let stats = cache.stats();
assert_eq!(stats.hits, 1);
assert_eq!(stats.misses, 1);
assert_eq!(stats.hit_rate(), 0.5);
}
#[test]
fn test_cache_lru_eviction() {
let mut cache = CompilationCache::new(2);
cache.insert(
"a".to_string(),
"val_a".to_string(),
std::time::Duration::from_millis(10),
100,
);
cache.insert(
"b".to_string(),
"val_b".to_string(),
std::time::Duration::from_millis(10),
100,
);
assert_eq!(cache.len(), 2);
let _ = cache.get("a");
cache.insert(
"c".to_string(),
"val_c".to_string(),
std::time::Duration::from_millis(10),
100,
);
assert_eq!(cache.len(), 2);
assert!(cache.get("a").is_some());
assert!(cache.get("b").is_none()); assert!(cache.get("c").is_some());
let stats = cache.stats();
assert_eq!(stats.evictions, 1);
}
#[test]
fn test_string_interner_basic() {
let mut interner = StringInterner::new();
assert_eq!(interner.len(), 0);
assert!(interner.is_empty());
let id1 = interner.intern("hello");
let id2 = interner.intern("world");
let id3 = interner.intern("hello");
assert_eq!(id1, id3); assert_ne!(id1, id2);
assert_eq!(interner.get(id1), Some("hello"));
assert_eq!(interner.get(id2), Some("world"));
assert_eq!(interner.get(9999), None);
assert_eq!(interner.len(), 2); assert!(!interner.is_empty());
}
#[test]
fn test_string_interner_clear() {
let mut interner = StringInterner::new();
interner.intern("test1");
interner.intern("test2");
assert_eq!(interner.len(), 2);
interner.clear();
assert_eq!(interner.len(), 0);
assert!(interner.is_empty());
let id = interner.intern("new");
assert_eq!(interner.get(id), Some("new"));
}
#[test]
fn test_parser_pool_basic() {
let pool = ParserPool::new(10);
assert_eq!(pool.capacity(), 10);
assert_eq!(pool.size(), 0);
let _parser1 = pool.create_parser("let x = 42");
let _parser2 = pool.create_parser("let y = 100");
let stats = pool.stats();
assert_eq!(stats.created, 2);
assert_eq!(stats.borrowed, 2);
}
#[test]
fn test_cache_memory_tracking() {
let mut cache = CompilationCache::new(10);
cache.insert(
"small".to_string(),
"x".to_string(),
std::time::Duration::from_millis(5),
100,
);
cache.insert(
"medium".to_string(),
"y".repeat(10),
std::time::Duration::from_millis(10),
1000,
);
cache.insert(
"large".to_string(),
"z".repeat(100),
std::time::Duration::from_millis(15),
10000,
);
let memory = cache.memory_usage();
assert_eq!(memory, 11100);
cache.clear();
assert_eq!(cache.memory_usage(), 0);
}
#[test]
fn test_cache_utilization() {
let cache = CompilationCache::new(10);
let stats = cache.stats();
assert_eq!(stats.utilization(), 0.0); assert_eq!(stats.capacity, 10);
assert_eq!(stats.size, 0);
}
#[cfg(test)]
mod property_tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn prop_cache_consistency(
key in "[a-z]{1,10}",
value in "[a-z]{1,20}",
millis in 1u64..1000,
bytes in 1usize..10000
) {
let mut cache = CompilationCache::new(5);
cache.insert(
key.clone(),
value.clone(),
std::time::Duration::from_millis(millis),
bytes
);
let retrieved = cache.get(&key);
prop_assert_eq!(retrieved, Some(value));
}
#[test]
fn prop_interner_deduplication(s1 in ".*", s2 in ".*") {
let mut interner = StringInterner::new();
let id1a = interner.intern(&s1);
let id1b = interner.intern(&s1);
let id2a = interner.intern(&s2);
let id2b = interner.intern(&s2);
prop_assert_eq!(id1a, id1b);
prop_assert_eq!(id2a, id2b);
if s1 == s2 {
prop_assert_eq!(id1a, id2a);
} else {
prop_assert_ne!(id1a, id2a);
}
}
#[test]
fn prop_cache_capacity_respected(capacity in 1usize..20) {
let mut cache = CompilationCache::new(capacity);
for i in 0..capacity + 5 {
cache.insert(
format!("key{i}"),
format!("val{i}"),
std::time::Duration::from_millis(10),
100
);
}
prop_assert!(cache.len() <= capacity);
}
#[test]
fn prop_interner_retrieval(strings in prop::collection::vec(".*", 1..20)) {
let mut interner = StringInterner::new();
let mut ids = Vec::new();
for s in &strings {
ids.push(interner.intern(s));
}
for (i, id) in ids.iter().enumerate() {
prop_assert_eq!(interner.get(*id), Some(strings[i].as_str()));
}
}
}
}