use std::{sync::mpsc::channel, thread};
use aok::{OK, Void};
use log::info;
use wbase::{BufferPool, DEFAULT_SECTOR_SIZE, MIN_SECTOR_SIZE};
#[test]
fn cross_thread_return_routes_back_to_origin_and_reuses() -> Void {
info!("对标 CrossThreadReturnRoutesBackToOriginAndReuses:异线程 Return 后属主 Get 复用同指针");
let pool = BufferPool::new(MIN_SECTOR_SIZE)?;
let p1 = pool.get_with_policy(4096, false)?;
let ptr1 = p1.as_allocated_slice().as_ptr() as usize;
thread::spawn(move || drop(p1))
.join()
.expect("跨线程归还执行成功");
let p2 = pool.get_with_policy(4096, false)?;
assert_eq!(
p2.as_allocated_slice().as_ptr() as usize,
ptr1,
"跨线程归还必须路由回属主线程并复用同一分配"
);
OK
}
#[test]
fn cross_thread_dirty_return_is_lazy_cleared_on_owner_reuse() -> Void {
info!("对标 CrossThreadDirtyReturnIsLazyClearedOnOwnerReuse:脏归还惰性清零与反极性验证");
let pool = BufferPool::new(DEFAULT_SECTOR_SIZE)?;
let mut p1 = pool.get_with_policy(4096, false)?;
p1.as_allocated_slice_mut().fill(0xAB);
let ptr1 = p1.as_allocated_slice().as_ptr() as usize;
thread::spawn(move || drop(p1))
.join()
.expect("异线程归还成功");
let p2 = pool.get(4096)?;
assert_eq!(
p2.as_allocated_slice().as_ptr() as usize,
ptr1,
"脏缓冲必须路由回属主复用"
);
assert!(
p2.as_allocated_slice().iter().all(|&b| b == 0),
"跨线程收割路径必须惰性清零脏缓冲"
);
drop(p2);
let mut p3 = pool.get_with_policy(4096, true)?;
p3.as_allocated_slice_mut().fill(0xCD);
thread::spawn(move || drop(p3))
.join()
.expect("异线程归还成功");
let p4 = pool.get_with_policy(4096, false)?;
assert_eq!(p4.as_allocated_slice().as_ptr() as usize, ptr1);
assert!(
p4.as_allocated_slice().iter().all(|&b| b == 0),
"异线程急切清零后的缓冲必须保持全零"
);
OK
}
#[test]
fn large_class_cross_thread_return_shares_via_depot() -> Void {
info!("对标 LargeClassCrossThreadReturnSharesViaDepot:1MB 大缓冲经 Depot 跨线程共享");
let pool = BufferPool::new(DEFAULT_SECTOR_SIZE)?;
let large_size = 1024 * 1024;
let p_clone1 = pool.clone();
let (tx, rx) = channel();
thread::spawn(move || {
let p1 = p_clone1
.get_with_policy(large_size, false)
.expect("大缓冲租借成功");
let ptr1 = p1.as_allocated_slice().as_ptr() as usize;
tx.send((p1, ptr1)).expect("发送成功");
})
.join()
.expect("属主线程执行成功");
let (p1, ptr1) = rx.recv().expect("接收成功");
thread::spawn(move || drop(p1))
.join()
.expect("完成线程执行成功");
let p_clone2 = pool.clone();
let ptr2 = thread::spawn(move || {
p_clone2
.get_with_policy(large_size, false)
.expect("复用租借成功")
.as_allocated_slice()
.as_ptr() as usize
})
.join()
.expect("复用线程执行成功");
assert_eq!(ptr1, ptr2, "第三线程必须从 Depot 复用同一底层物理指针");
OK
}
#[test]
fn large_class_owner_return_shares_via_depot() -> Void {
info!("对标 LargeClassOwnerReturnSharesViaDepot:属主归还的大缓冲不经本地栈,异源线程可命中");
let pool = BufferPool::new(DEFAULT_SECTOR_SIZE)?;
let large_size = 1024 * 1024;
let p_clone1 = pool.clone();
let ptr1 = thread::spawn(move || {
let p1 = p_clone1
.get_with_policy(large_size, false)
.expect("大缓冲租借成功");
let ptr1 = p1.as_allocated_slice().as_ptr() as usize;
drop(p1); ptr1
})
.join()
.expect("属主线程执行成功");
let p_clone2 = pool.clone();
let ptr2 = thread::spawn(move || {
p_clone2
.get_with_policy(large_size, false)
.expect("复用租借成功")
.as_allocated_slice()
.as_ptr() as usize
})
.join()
.expect("复用线程执行成功");
assert_eq!(ptr1, ptr2, "异源线程必须从 Depot 命中属主归还的大缓冲");
OK
}
#[test]
fn sealed_inbox_fallback_zeroing_preserves_free_node_region() -> Void {
info!("验证属主退出后密封回退路径恢复 32B FreeNode 污染区,复用缓冲 100% 全零");
let pool = BufferPool::new(DEFAULT_SECTOR_SIZE)?;
let p1 = {
let p_clone = pool.clone();
let (tx, rx) = channel();
thread::spawn(move || {
let mut buf = p_clone.get_with_policy(4096, true).expect("租借成功");
buf.as_allocated_slice_mut().fill(0x7F);
tx.send(buf).expect("发送成功");
})
.join()
.expect("属主线程退出成功");
rx.recv().expect("接收成功")
};
thread::spawn(move || drop(p1))
.join()
.expect("归还线程执行成功");
let p2 = pool.get(4096)?;
assert!(
p2.as_allocated_slice().iter().all(|&b| b == 0),
"回退进入 Depot 的缓冲区复用时必须 100% 全零(不得残留 FreeNode 非零字节)"
);
OK
}