use aok::{OK, Void};
use compio::runtime::Runtime;
use log::info;
use tempfile::tempdir;
use wdev::{
Device, Error, MAX_SEGMENT_SIZE, SegmentedDevice, detect_cpu_cores, detect_system_memory,
};
use wram::AlignedBuf;
#[test]
fn set_capacity_rejects_non_multiple_of_segment_size() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
let seg_size: u64 = 64 * 1024;
let mut device = SegmentedDevice::segmented(dir.path().join("cap_invalid.log"), seg_size)?;
assert!(
matches!(
device.set_capacity(Some(0)),
Err(Error::InvalidCapacity { .. })
),
"0 容量必须被拒绝"
);
assert!(
matches!(
device.set_capacity(Some(seg_size * 2 + 123)),
Err(Error::InvalidCapacity { .. })
),
"非段尺寸整数倍的容量必须被拒绝"
);
assert_eq!(device.capacity(), None, "校验失败后容量应保持未设置");
device.set_capacity(Some(seg_size * 2))?;
assert_eq!(device.capacity(), Some(seg_size * 2));
assert_eq!(Device::capacity(&device), Some(seg_size * 2));
info!("容量上限整数倍校验通过 (Initialize capacity validation)");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn handle_capacity_evicts_oldest_segments_when_bounded() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
let seg_size: u64 = 64 * 1024;
let mut device = SegmentedDevice::segmented(dir.path().join("cap_evict.log"), seg_size)?;
device.set_capacity(Some(seg_size * 2))?;
assert_eq!(
device.end_segment(),
None,
"初始 end_segment 应为 None (C# -1)"
);
for seg_id in 0..4u32 {
let buf = AlignedBuf::from_slice(&[(seg_id * 17 + 1) as u8; 4096], 4096)?;
let (res, _) = device.write_aligned((seg_id as u64) * seg_size, buf).await;
assert_eq!(res?, 4096);
}
assert_eq!(
device.start_segment(),
1,
"段 0 被逐出后 start_segment 应为 1"
);
assert_eq!(device.end_segment(), Some(3));
assert!(
!device.segment_path(0).exists(),
"超容量的最老段必须被 HandleCapacity 自动物理删除"
);
assert_eq!(device.get_file_size(0)?, 0);
for seg_id in 1..4u32 {
assert!(device.segment_path(seg_id).exists(), "段 {seg_id} 应保留");
let expected = (seg_id * 17 + 1) as u8;
let check = AlignedBuf::new(4096, 4096)?;
let (res, check) = device.read_aligned((seg_id as u64) * seg_size, check).await;
assert_eq!(res?, 4096);
assert!(check.as_slice().iter().all(|&b| b == expected));
}
info!("有界容量自动逐出最老段校验通过 (HandleCapacity)");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn segment_size_above_max_is_rejected() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
assert!(matches!(
SegmentedDevice::new(dir.path().join("seg_max1.log"), Some(1u64 << 63), 4096),
Err(Error::InvalidSegmentSize(_))
));
assert!(matches!(
SegmentedDevice::new(
dir.path().join("seg_max2.log"),
Some(MAX_SEGMENT_SIZE + 1),
4096
),
Err(Error::InvalidSegmentSize(_))
));
let device = SegmentedDevice::new(
dir.path().join("seg_max_ok.log"),
Some(MAX_SEGMENT_SIZE),
4096,
)?;
assert_eq!(device.segment_size(), Some(MAX_SEGMENT_SIZE));
info!("段尺寸上界防御校验通过 (MAX_SEGMENT_SIZE)");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn system_probes_return_usable_values() -> Void {
let sys_mem = detect_system_memory();
assert!(sys_mem > 0, "系统内存探测值必须大于 0");
let cores = detect_cpu_cores();
assert!(cores >= 1, "可用 CPU 核心数必须至少为 1");
info!("系统内存/核心数探测校验通过");
OK
}