use crate::runtime::cache::tiered_cache::{CacheTier, LruPolicy, TieredCache};
use crate::runtime::cache::AccessTracker;
#[test]
fn get_returns_entry_after_insert() {
let mut cache = TieredCache::new(vec![CacheTier::new("L1", 1024)]);
cache.insert(1, 100).unwrap();
let entry = cache.get(1).unwrap();
assert_eq!(entry.key, 1);
assert_eq!(entry.size, 100);
assert_eq!(entry.tier, 0);
}
#[test]
fn get_missing_returns_none() {
let cache = TieredCache::new(vec![CacheTier::new("L1", 1024)]);
assert!(cache.get(99).is_none());
}
#[test]
fn insert_replaces_existing_key() {
let mut cache = TieredCache::new(vec![CacheTier::new("L1", 1024)]);
cache.insert(1, 100).unwrap();
cache.insert(1, 200).unwrap();
let entry = cache.get(1).unwrap();
assert_eq!(entry.size, 200);
}
#[test]
fn promote_moves_to_higher_tier() {
let mut cache = TieredCache::new(vec![CacheTier::new("L1", 1024), CacheTier::new("L2", 1024)]);
cache.insert(1, 100).unwrap();
for _ in 0..LruPolicy::DEFAULT_THRESHOLD {
cache.record_access(1);
}
cache.promote(1).unwrap();
let entry = cache.get(1).unwrap();
assert_eq!(entry.tier, 1);
}
#[test]
fn demote_moves_to_lower_tier() {
let mut cache = TieredCache::new(vec![CacheTier::new("L1", 1024), CacheTier::new("L2", 1024)]);
cache.insert(1, 100).unwrap();
for _ in 0..LruPolicy::DEFAULT_THRESHOLD {
cache.record_access(1);
}
cache.promote(1).unwrap();
cache.demote(1).unwrap();
let entry = cache.get(1).unwrap();
assert_eq!(entry.tier, 0);
}
#[test]
fn insert_replacement_evicts_old_entry() {
let mut cache = TieredCache::new(vec![CacheTier::new("L1", 1024)]);
cache.insert(1, 100).unwrap();
cache.insert(1, 200).unwrap();
assert!(cache.get(1).is_some());
assert_eq!(cache.get(1).unwrap().size, 200);
}
#[test]
fn make_room_evicts_coldest() {
let mut cache = TieredCache::new(vec![CacheTier::new("L1", 200)]);
cache.insert(1, 100).unwrap();
cache.insert(2, 100).unwrap();
cache.record_access(1);
cache.insert(3, 100).unwrap();
assert!(cache.get(1).is_some());
assert!(cache.get(2).is_none());
assert!(cache.get(3).is_some());
}
#[test]
fn stats_returns_last_access_not_rank() {
let mut tracker = AccessTracker::new();
tracker.set_size(1, 100);
tracker.record(1);
tracker.record(2);
tracker.record(1);
let stats1 = tracker.stats(1).unwrap();
let stats2 = tracker.stats(2).unwrap();
assert!(stats1.last_access > stats2.last_access);
assert_eq!(stats1.frequency, 2);
assert_eq!(stats2.frequency, 1);
}
#[test]
fn get_after_evict_from_tier_during_promote() {
let mut cache = TieredCache::new(vec![CacheTier::new("L1", 200), CacheTier::new("L2", 200)]);
cache.insert(1, 100).unwrap();
cache.insert(2, 100).unwrap();
for _ in 0..LruPolicy::DEFAULT_THRESHOLD {
cache.record_access(1);
}
cache.promote(1).unwrap();
assert!(cache.get(1).is_some());
assert!(cache.get(2).is_some());
}
#[test]
fn get_after_tier_full_and_insert_evicts() {
let mut cache = TieredCache::new(vec![CacheTier::new("L1", 250)]);
cache.insert(1, 100).unwrap();
cache.insert(2, 100).unwrap();
cache.record_access(1);
cache.insert(3, 100).unwrap();
assert!(cache.get(1).is_some());
assert!(cache.get(2).is_none());
assert!(cache.get(3).is_some());
}