#[test]
fn test_cov_fragmentation_stats_trailing_free_region() {
let mut cache = PagedKvCache::new(100, 16, 8, 64);
let seq = cache.allocate_sequence(16).expect("alloc");
cache.update_tokens(seq, 16).expect("update");
let stats = cache.fragmentation_stats();
assert_eq!(stats.largest_free_region, 99);
}
#[test]
fn test_cov_should_defragment_waste_ratio_trigger() {
let mut cache = PagedKvCache::new(100, 16, 8, 64);
for _ in 0..10 {
let seq = cache.allocate_sequence(32).expect("alloc"); cache.update_tokens(seq, 1).expect("update");
}
let stats = cache.fragmentation_stats();
let _ = stats; }
#[test]
fn test_cov_should_defragment_low_free_with_holes() {
let mut cache = PagedKvCache::new(10, 16, 8, 64);
let mut seqs = Vec::new();
for _ in 0..9 {
seqs.push(cache.allocate_sequence(16).expect("alloc"));
}
cache.free_sequence(seqs[4]);
let should = cache.should_defragment();
let _ = should;
}
#[test]
fn test_cov_quantized_kv_data_write_beyond_capacity() {
let mut data = QuantizedKvData::new(KvQuantType::FP32, 4, 2, 4);
let large_data: Vec<f32> = (0..100).map(|i| i as f32).collect();
data.write_keys(0, &large_data);
let read = data.read_keys(0, 100);
assert!(read.len() <= 32);
}
#[test]
fn test_cov_quantized_kv_data_read_beyond_capacity() {
let data = QuantizedKvData::new(KvQuantType::FP32, 4, 2, 4);
let read = data.read_keys(0, 1000);
assert!(read.len() <= 32);
}
#[test]
fn test_cov_q8_write_spanning_multiple_blocks() {
let mut data = QuantizedKvData::new(KvQuantType::Q8, 16, 8, 64);
let test_data: Vec<f32> = (0..200).map(|i| (i as f32 - 100.0) * 0.01).collect();
data.write_keys(50, &test_data);
let read = data.read_keys(50, 200);
assert_eq!(read.len(), 200);
}
#[test]
fn test_cov_q4_write_spanning_multiple_blocks() {
let mut data = QuantizedKvData::new(KvQuantType::Q4, 16, 8, 64);
let test_data: Vec<f32> = (0..100).map(|i| (i as f32 - 50.0) * 0.05).collect();
data.write_values(30, &test_data);
let read = data.read_values(30, 100);
assert_eq!(read.len(), 100);
}
#[test]
fn test_cov_quantized_page_write_at_different_positions() {
let mut page = QuantizedKvPage::new(PageId::new(0), KvQuantType::Q8, 16, 8, 64);
for pos in 0..4 {
let keys: Vec<f32> = (0..512).map(|i| (i + pos * 100) as f32 * 0.001).collect();
page.write_keys(pos, &keys);
page.num_tokens = pos + 1;
}
for pos in 0..4 {
let read = page.read_keys(pos);
assert_eq!(read.len(), 512);
}
}
#[test]
fn test_cov_quantized_cache_get_page_mut_not_found() {
let mut cache = QuantizedPagedKvCache::new(100, 16, 8, 64, KvQuantType::Q8);
let fake_seq = SeqId::new();
let result = cache.get_page_mut(fake_seq, 0);
assert!(matches!(result, Err(PagedCacheError::SequenceNotFound(_))));
}
#[test]
fn test_cov_quantized_cache_fp32_operations() {
let mut cache = QuantizedPagedKvCache::new(100, 16, 8, 64, KvQuantType::FP32);
let seq_id = cache.allocate_sequence(32).expect("alloc");
{
let page = cache.get_page_mut(seq_id, 0).expect("get");
let keys: Vec<f32> = (0..512).map(|i| i as f32).collect();
page.write_keys(0, &keys);
page.num_tokens = 1;
}
let page = cache.get_page(seq_id, 0).expect("get_read");
let read_keys = page.read_keys(0);
assert_eq!(read_keys[0], 0.0);
assert_eq!(read_keys[1], 1.0);
}
#[test]
fn test_cov_quantized_cache_q4_operations() {
let mut cache = QuantizedPagedKvCache::new(100, 16, 8, 64, KvQuantType::Q4);
let seq_id = cache.allocate_sequence(16).expect("alloc");
{
let page = cache.get_page_mut(seq_id, 0).expect("get");
let values: Vec<f32> = (0..512).map(|i| (i as f32 - 256.0) * 0.01).collect();
page.write_values(0, &values);
}
let page = cache.get_page(seq_id, 0).expect("read");
let read = page.read_values(0);
assert_eq!(read.len(), 512);
}
#[test]
fn test_cov_prefix_cache_evict_lru_all_referenced() {
let mut cache = PrefixCache::new(2);
cache.insert(CachedPrefix::new(1, 1, vec![]));
cache.insert(CachedPrefix::new(2, 2, vec![]));
assert_eq!(cache.len(), 2);
let inserted = cache.insert(CachedPrefix::new(3, 3, vec![]));
assert!(!inserted);
assert_eq!(cache.len(), 2);
}
#[test]
fn test_cov_prefix_cache_insert_existing_hash() {
let mut cache = PrefixCache::new(10);
cache.insert(CachedPrefix::new(42, 5, vec![]));
assert_eq!(cache.len(), 1);
cache.insert(CachedPrefix::new(42, 10, vec![PageId::new(0)]));
assert_eq!(cache.len(), 1);
let lookup = cache.lookup(42);
assert!(lookup.is_some());
assert_eq!(lookup.unwrap().num_tokens, 10);
}
#[test]
fn test_cov_memory_usage_multiple_sequences() {
let mut cache = PagedKvCache::new(100, 16, 8, 64);
for _ in 0..5 {
let _ = cache.allocate_sequence(32).expect("alloc");
}
let usage = cache.memory_usage();
let capacity = cache.total_capacity();
assert_eq!(usage * 10, capacity);
}
#[test]
fn test_cov_quantized_memory_usage_after_free() {
let mut cache = QuantizedPagedKvCache::new(100, 16, 8, 64, KvQuantType::Q8);
let seq1 = cache.allocate_sequence(16).expect("alloc1");
let seq2 = cache.allocate_sequence(16).expect("alloc2");
let usage_before = cache.memory_usage();
cache.free_sequence(seq1);
let usage_after = cache.memory_usage();
assert!(usage_after < usage_before);
cache.free_sequence(seq2);
let usage_final = cache.memory_usage();
assert_eq!(usage_final, 0);
}
#[test]
fn test_cov_cached_prefix_serialization() {
let prefix = CachedPrefix::new(12345, 10, vec![PageId::new(0), PageId::new(1)]);
let json = serde_json::to_string(&prefix).expect("serialize");
let parsed: CachedPrefix = serde_json::from_str(&json).expect("deserialize");
assert_eq!(parsed.hash, 12345);
assert_eq!(parsed.num_tokens, 10);
assert_eq!(parsed.page_ids.len(), 2);
}
#[test]
fn test_cov_tokens_to_pages_various_sizes() {
let cache = PagedKvCache::new(100, 16, 8, 64);
assert!(cache.free_page_count() == 100);
let mut cache2 = PagedKvCache::new(100, 16, 8, 64);
let _ = cache2.allocate_sequence(1); assert_eq!(cache2.free_page_count(), 99);
let _ = cache2.allocate_sequence(16); assert_eq!(cache2.free_page_count(), 98);
let _ = cache2.allocate_sequence(17); assert_eq!(cache2.free_page_count(), 96);
let _ = cache2.allocate_sequence(32); assert_eq!(cache2.free_page_count(), 94);
let _ = cache2.allocate_sequence(33); assert_eq!(cache2.free_page_count(), 91);
}
#[test]
fn test_cov_is_page_free_verification() {
let mut cache = PagedKvCache::new(10, 16, 8, 64);
let seq = cache.allocate_sequence(16).expect("alloc");
cache.free_sequence(seq);
assert_eq!(cache.free_page_count(), 10);
}
#[test]
fn test_cov_fragmentation_ratio_max_one() {
let mut cache = PagedKvCache::new(5, 16, 8, 64);
let seq1 = cache.allocate_sequence(16).expect("s1");
let seq2 = cache.allocate_sequence(16).expect("s2");
let seq3 = cache.allocate_sequence(16).expect("s3");
cache.free_sequence(seq2);
let stats = cache.fragmentation_stats();
assert!(stats.fragmentation_ratio <= 1.0);
cache.free_sequence(seq1);
cache.free_sequence(seq3);
}
#[test]
fn test_cov_compact_single_page_sequence() {
let mut cache = PagedKvCache::new(100, 16, 8, 64);
let seq = cache.allocate_sequence(10).expect("alloc");
let moved = cache.compact_sequence(seq);
assert_eq!(moved, 0);
}
#[test]
fn test_cov_update_tokens_exact_block_boundary() {
let mut cache = PagedKvCache::new(100, 16, 8, 64);
let seq = cache.allocate_sequence(32).expect("alloc");
cache.update_tokens(seq, 16).expect("update");
assert_eq!(cache.get_sequence_tokens(seq).expect("get"), 16);
cache.update_tokens(seq, 32).expect("update2");
assert_eq!(cache.get_sequence_tokens(seq).expect("get2"), 32);
}
#[test]
fn test_cov_quantized_kv_page_shared_state() {
let mut page = QuantizedKvPage::new(PageId::new(0), KvQuantType::Q8, 16, 8, 64);
assert!(!page.is_shared());
page.ref_count = 1;
assert!(!page.is_shared());
page.ref_count = 2;
assert!(page.is_shared()); }
#[test]
fn test_cov_kv_quant_type_serialization() {
for quant in [KvQuantType::FP32, KvQuantType::Q8, KvQuantType::Q4] {
let json = serde_json::to_string(&quant).expect("serialize");
let parsed: KvQuantType = serde_json::from_str(&json).expect("deserialize");
assert_eq!(parsed, quant);
}
}
#[test]
fn test_cov_compute_prefix_hash_collision_resistance() {
let hashes: Vec<u64> = (0..100)
.map(|i| {
let tokens: Vec<u32> = (0..=i).map(|j| j as u32).collect();
compute_prefix_hash(&tokens)
})
.collect();
let mut unique = hashes.clone();
unique.sort_unstable();
unique.dedup();
assert_eq!(unique.len(), hashes.len(), "All hashes should be unique");
}
#[test]
fn test_cov_find_longest_prefix_empty_tokens() {
let mut cache = PrefixCache::new(100);
let result = find_longest_prefix(&mut cache, &[]);
assert!(result.is_none());
}
#[test]
fn test_cov_find_longest_prefix_single_token() {
let mut cache = PrefixCache::new(100);
let hash = compute_prefix_hash(&[42]);
cache.insert(CachedPrefix::new(hash, 1, vec![]));
let result = find_longest_prefix(&mut cache, &[42, 43, 44]);
assert!(result.is_some());
let (found_hash, len) = result.unwrap();
assert_eq!(found_hash, hash);
assert_eq!(len, 1);
}
#[test]
fn test_cov_error_out_of_memory_fields() {
let err = PagedCacheError::OutOfMemory {
needed: 100,
available: 5,
};
let msg = err.to_string();
assert!(msg.contains("100"));
assert!(msg.contains("5"));
}
#[test]
fn test_cov_error_invalid_page_access_fields() {
let err = PagedCacheError::InvalidPageAccess {
page_id: 42,
offset: 999,
};
let msg = err.to_string();
assert!(msg.contains("42"));
assert!(msg.contains("999"));
}
#[test]
fn test_cov_error_page_table_corruption_field() {
let err = PagedCacheError::PageTableCorruption { seq_id: 123 };
let msg = err.to_string();
assert!(msg.contains("123"));
}