use super::*;
use std::io::Write;
use tempfile::NamedTempFile;
#[test]
fn test_page_cache_config_basic() {
let config = PageCacheConfig::balanced();
assert!(config.capacity > 0);
assert!(config.num_shards > 0);
assert!(config.page_size == PAGE_SIZE);
}
#[test]
fn test_cache_creation() {
let config = PageCacheConfig::memory_optimized();
let cache = LruPageCache::new(config);
assert!(cache.is_ok());
}
#[test]
fn test_real_file_io_basic() -> Result<()> {
let mut temp_file = NamedTempFile::new()?;
let test_data = b"Hello, LRU Cache!";
temp_file.write_all(test_data)?;
temp_file.flush()?;
let config = PageCacheConfig::balanced();
let cache = LruPageCache::new(config)?;
let file_id = cache.open_file(temp_file.path())?;
let buffer = cache.read(file_id, 0, test_data.len())?;
assert_eq!(buffer.len(), test_data.len());
assert_eq!(buffer.data(), test_data);
let file_size = cache.file_size(file_id)?;
assert_eq!(file_size, test_data.len() as u64);
cache.close_file(file_id)?;
Ok(())
}
#[test]
fn test_cache_statistics() {
let mut stats = CacheStatistics::new();
stats.record_hit(CacheHitType::Hit);
stats.record_miss();
assert_eq!(stats.hit_ratio(), 0.5);
assert_eq!(stats.miss_ratio(), 0.5);
}
#[test]
fn test_buffer_operations() {
let mut buffer = CacheBuffer::new();
assert!(buffer.is_empty());
let test_data = b"Test data";
buffer.copy_from_slice(test_data);
assert!(!buffer.is_empty());
assert_eq!(buffer.data(), test_data);
assert_eq!(buffer.len(), test_data.len());
buffer.clear();
assert!(buffer.is_empty());
}
#[test]
fn test_cache_read_same_page_twice() -> Result<()> {
let mut temp_file = NamedTempFile::new()?;
let test_data = b"Cached page data";
temp_file.write_all(test_data)?;
temp_file.flush()?;
let config = PageCacheConfig::balanced();
let cache = LruPageCache::new(config)?;
let file_id = cache.open_file(temp_file.path())?;
let buffer1 = cache.read(file_id, 0, test_data.len())?;
assert_eq!(buffer1.data(), test_data);
assert_eq!(cache.stats().total_misses, 1);
assert_eq!(cache.stats().total_hits, 1);
let buffer2 = cache.read(file_id, 0, test_data.len())?;
assert_eq!(buffer2.data(), test_data);
assert_eq!(cache.stats().total_misses, 1);
assert_eq!(cache.stats().total_hits, 2);
cache.close_file(file_id)?;
Ok(())
}
#[test]
fn test_cache_read_different_offsets() -> Result<()> {
let mut temp_file = NamedTempFile::new()?;
let test_data = b"0123456789ABCDEF";
temp_file.write_all(test_data)?;
temp_file.flush()?;
let config = PageCacheConfig::balanced();
let cache = LruPageCache::new(config)?;
let file_id = cache.open_file(temp_file.path())?;
let buffer1 = cache.read(file_id, 0, 5)?;
assert_eq!(buffer1.data(), b"01234");
let buffer2 = cache.read(file_id, 5, 5)?;
assert_eq!(buffer2.data(), b"56789");
cache.close_file(file_id)?;
Ok(())
}
#[test]
fn test_cache_miss_then_hit() -> Result<()> {
let mut temp_file = NamedTempFile::new()?;
temp_file.write_all(b"test")?;
temp_file.flush()?;
let config = PageCacheConfig::balanced();
let cache = LruPageCache::new(config)?;
let file_id = cache.open_file(temp_file.path())?;
let _buffer1 = cache.read(file_id, 0, 4)?;
let _buffer2 = cache.read(file_id, 0, 4)?;
let stats = cache.stats();
assert_eq!(stats.total_hits, 2);
assert_eq!(stats.total_misses, 1);
assert!((stats.hit_ratio - 0.666).abs() < 0.01);
assert!((stats.miss_ratio - 0.333).abs() < 0.01);
cache.close_file(file_id)?;
Ok(())
}
#[test]
fn test_cache_file_size_query() -> Result<()> {
let mut temp_file = NamedTempFile::new()?;
let test_data = b"File size test data";
temp_file.write_all(test_data)?;
temp_file.flush()?;
let config = PageCacheConfig::balanced();
let cache = LruPageCache::new(config)?;
let file_id = cache.open_file(temp_file.path())?;
let file_size = cache.file_size(file_id)?;
assert_eq!(file_size, test_data.len() as u64);
cache.close_file(file_id)?;
Ok(())
}
#[test]
fn test_cache_large_file_multipage() -> Result<()> {
let mut temp_file = NamedTempFile::new()?;
let test_data = vec![0x42u8; 8192];
temp_file.write_all(&test_data)?;
temp_file.flush()?;
let config = PageCacheConfig::balanced();
let cache = LruPageCache::new(config)?;
let file_id = cache.open_file(temp_file.path())?;
let buffer = cache.read(file_id, 3000, 3000)?;
assert_eq!(buffer.len(), 3000);
assert!(buffer.data().iter().all(|&b| b == 0x42));
cache.close_file(file_id)?;
Ok(())
}
#[test]
fn test_cache_open_close_file() -> Result<()> {
let mut temp_file = NamedTempFile::new()?;
temp_file.write_all(b"lifecycle test")?;
temp_file.flush()?;
let config = PageCacheConfig::balanced();
let cache = LruPageCache::new(config)?;
let file_id = cache.open_file(temp_file.path())?;
assert!(file_id > 0);
let buffer = cache.read(file_id, 0, 4)?;
assert_eq!(buffer.data(), b"life");
cache.close_file(file_id)?;
Ok(())
}
#[test]
fn test_cache_memory_optimized_config() {
let config = PageCacheConfig::memory_optimized();
assert!(config.capacity > 0);
assert!(config.num_shards > 0);
assert_eq!(config.page_size, PAGE_SIZE);
let balanced_config = PageCacheConfig::balanced();
assert!(config.capacity <= balanced_config.capacity);
}
#[test]
fn test_cache_buffer_extend_and_read() -> Result<()> {
let mut temp_file = NamedTempFile::new()?;
temp_file.write_all(b"part1part2")?;
temp_file.flush()?;
let config = PageCacheConfig::balanced();
let cache = LruPageCache::new(config)?;
let file_id = cache.open_file(temp_file.path())?;
let mut buffer = cache.read(file_id, 0, 5)?;
assert_eq!(buffer.data(), b"part1");
buffer.extend_from_slice(b"part2");
assert_eq!(buffer.data(), b"part1part2");
assert_eq!(buffer.len(), 10);
cache.close_file(file_id)?;
Ok(())
}