use aok::{OK, Void};
use log::info;
use wbase::{BufferPool, DEFAULT_SECTOR_SIZE, MIN_SECTOR_SIZE, NUM_CLASSES};
#[test]
fn get_capacity_covers_request_across_sizes() -> Void {
info!("对标 GetCapacityCoversRequestAcrossSizes:512 扇区池跨尺寸租借并触达首尾字节");
let pool = BufferPool::new(MIN_SECTOR_SIZE)?;
for bytes in [
1, 100, 511, 512, 513, 4096, 4097, 60_000, 200_000, 2_000_000,
] {
let mut page = pool.get_with_policy(bytes, false)?;
assert_eq!(
page.as_allocated_slice().as_ptr() as usize % MIN_SECTOR_SIZE,
0,
"{bytes} 字节请求的指针必须扇区对齐"
);
assert!(page.capacity() >= bytes, "容量必须覆盖 {bytes} 字节请求");
let slice = page.as_allocated_slice_mut();
slice[0] = 1;
slice[bytes - 1] = 1;
}
OK
}
#[test]
fn get_returns_zeroed_buffer_and_reuses() -> Void {
info!("对标 GetReturnsZeroedBufferAndReuses:默认 Get 全零、归还后同指针复用且重新清零");
let pool = BufferPool::new(DEFAULT_SECTOR_SIZE)?;
let ptr_val: usize;
{
let mut p1 = pool.get(4096)?;
assert!(
p1.as_allocated_slice().iter().all(|&b| b == 0),
"默认 Get 必须返回全零缓冲区"
);
p1.as_allocated_slice_mut().fill(0xAB);
ptr_val = p1.as_allocated_slice().as_ptr() as usize;
}
let p2 = pool.get(4096)?;
assert_eq!(
p2.as_allocated_slice().as_ptr() as usize,
ptr_val,
"同线程归还后必须复用本地缓存缓冲区"
);
assert!(
p2.as_allocated_slice().iter().all(|&b| b == 0),
"复用缓冲区必须重新清零"
);
OK
}
#[test]
fn opt_out_clear_then_default_get_is_zeroed() -> Void {
info!(
"对标 OptOutClearThenDefaultGetIsZeroed:clearOnReturn=false 归还脏位,下次默认 Get 惰性清零"
);
let pool = BufferPool::new(DEFAULT_SECTOR_SIZE)?;
let ptr_val: usize;
{
let mut p1 = pool.get_with_policy(4096, false)?;
p1.as_allocated_slice_mut().fill(0xCD);
ptr_val = p1.as_allocated_slice().as_ptr() as usize;
}
let p2 = pool.get(4096)?;
assert_eq!(
p2.as_allocated_slice().as_ptr() as usize,
ptr_val,
"必须复用同一脏槽位"
);
assert!(
p2.as_allocated_slice().iter().all(|&b| b == 0),
"默认 Get 必须惰性清零脏槽位"
);
OK
}
#[test]
fn ensure_size_reuses_capacity_in_place() -> Void {
info!("对标 EnsureSize:容量充足时指针不变且 required_bytes 同步为原始请求字节数");
let pool = BufferPool::new(DEFAULT_SECTOR_SIZE)?;
let mut buf = pool.get(8192)?;
assert_eq!(buf.capacity(), 8192);
assert_eq!(buf.required_len(), 8192);
buf.as_allocated_slice_mut().fill(0x33);
let old_ptr = buf.as_allocated_slice().as_ptr() as usize;
pool.ensure_size(&mut buf, 4096)?;
assert_eq!(
buf.as_allocated_slice().as_ptr() as usize,
old_ptr,
"容量充足必须就地复用"
);
assert_eq!(
buf.required_len(),
4096,
"required_bytes 必须同步为原始请求"
);
assert_eq!(buf.capacity(), 8192);
pool.ensure_size(&mut buf, 2048)?;
assert_eq!(buf.as_allocated_slice().as_ptr() as usize, old_ptr);
assert_eq!(buf.required_len(), 2048);
pool.ensure_size(&mut buf, 16384)?;
assert!(buf.capacity() >= 16384);
assert_eq!(buf.required_len(), 16384);
OK
}
#[test]
fn get_from_slice_copies_data_and_reuses_memory() -> Void {
info!("验证 get_from_slice 数据拷贝与归还后的内存复用、清零语义");
let pool = BufferPool::new(DEFAULT_SECTOR_SIZE)?;
let empty = pool.get_from_slice(&[])?;
assert_eq!(empty.len(), 0);
let data = b"embedded storage wutil zero-copy test";
let ptr_val: usize;
{
let buf = pool.get_from_slice(data)?;
assert_eq!(buf.len(), data.len());
assert_eq!(&buf[..], data);
assert!(buf.capacity() >= DEFAULT_SECTOR_SIZE);
ptr_val = buf.as_allocated_slice().as_ptr() as usize;
}
let next = pool.get(DEFAULT_SECTOR_SIZE)?;
assert_eq!(
next.as_allocated_slice().as_ptr() as usize,
ptr_val,
"归还缓冲必须入池复用"
);
assert!(
next.as_allocated_slice().iter().all(|&b| b == 0),
"复用缓冲必须全零"
);
OK
}
#[test]
fn zero_byte_request_and_unknown_class_queries_are_safe() -> Void {
info!("验证 get(0) 空缓冲语义与 cached_len 越界 class 的防御性返回");
let pool = BufferPool::new(DEFAULT_SECTOR_SIZE)?;
assert_eq!(pool.cached_len(NUM_CLASSES), 0);
assert_eq!(pool.cached_len(NUM_CLASSES + 42), 0);
assert_eq!(pool.cached_len(usize::MAX), 0);
let empty = pool.get(0)?;
assert_eq!(empty.capacity(), 0);
assert_eq!(empty.len(), 0);
assert!(empty.is_empty());
assert!(empty.is_ptr_aligned());
assert_eq!(pool.reserved_bytes(), 0, "空缓冲不占预算许可");
let cloned = empty.clone();
assert_eq!(cloned.capacity(), 0);
assert!(cloned.is_ptr_aligned());
drop((empty, cloned));
assert_eq!(pool.reserved_bytes(), 0);
OK
}