use aok::{OK, Void};
use compio::runtime::Runtime;
use log::info;
use tempfile::tempdir;
use wdev::{Device, Error, SegmentedDevice};
use wram::AlignedBuf;
#[test]
fn unaligned_offset_read_async_throws() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
let device = SegmentedDevice::new(dir.path().join("unaligned_read.log"), None, 4096)?;
let rbuf = AlignedBuf::new(4 * 4096, 4096)?;
let (res, rbuf) = device.read_aligned(4095, rbuf).await;
drop(rbuf);
match res {
Err(Error::UnalignedOffset { offset, align }) => {
assert_eq!(offset, 4095);
assert_eq!(align, 4096);
}
other => panic!("预期 UnalignedOffset,实际为: {other:?}"),
}
info!("未对齐偏移读取拒绝校验通过 (UnalignedOffset_ReadAsync_Throws)");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn unaligned_offset_write_async_throws() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
let device = SegmentedDevice::new(dir.path().join("unaligned_write.log"), None, 4096)?;
let valid = vec![0xAAu8; 4096];
for bad_offset in [1u64, 511, 4095, 4097, 7000] {
let wbuf = AlignedBuf::from_slice(&valid, 4096)?;
let (res, _) = device.write_aligned(bad_offset, wbuf).await;
match res {
Err(Error::UnalignedOffset { offset, align }) => {
assert_eq!(offset, bad_offset);
assert_eq!(align, 4096);
}
other => panic!("偏移 {bad_offset} 预期 UnalignedOffset,实际为: {other:?}"),
}
}
info!("未对齐偏移写入拒绝校验通过 (ThrowIfMisaligned 写路径)");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn unaligned_length_write_async_throws() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
let device = SegmentedDevice::new(dir.path().join("unaligned_len.log"), None, 4096)?;
let bad_len = vec![0xBBu8; 4096 + 1];
let wbuf = AlignedBuf::from_slice(&bad_len, 4096)?;
let (res, _) = device.write_aligned(0, wbuf).await;
match res {
Err(Error::UnalignedLen { len, align }) => {
assert_eq!(len, 4097);
assert_eq!(align, 4096);
}
other => panic!("预期 UnalignedLen,实际为: {other:?}"),
}
info!("未对齐长度写入拒绝校验通过 (UnalignedLength_WriteAsync_Throws)");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn unaligned_buffer_write_async_throws() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
let device = SegmentedDevice::new(dir.path().join("unaligned_buf.log"), None, 4096)?;
for _ in 0..100 {
let candidate = AlignedBuf::new(4096, 512)?;
if !candidate.is_aligned_to(4096) {
let ptr_val = candidate.as_ptr() as usize;
let (res, _) = device.write_aligned(0, candidate.clone()).await;
match res {
Err(Error::UnalignedBuffer { ptr, align }) => {
assert_eq!(ptr, ptr_val);
assert_eq!(align, 4096);
}
other => panic!("预期 UnalignedBuffer 写拒绝,实际为: {other:?}"),
}
let (res, _) = device.read_aligned(0, candidate).await;
match res {
Err(Error::UnalignedBuffer { ptr, align }) => {
assert_eq!(ptr, ptr_val);
assert_eq!(align, 4096);
}
other => panic!("预期 UnalignedBuffer 读拒绝,实际为: {other:?}"),
}
info!("未对齐缓冲区地址读写拒绝校验通过 (UnalignedBuffer_WriteAsync_Throws)");
return aok::Result::<()>::Ok(());
}
}
info!("100 次分配均为 4096 对齐,环境天然满足对齐,跳过未对齐缓冲区断言");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn non_power_of_two_segment_size_throws() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
assert!(matches!(
SegmentedDevice::new(dir.path().join("seg_3mib.log"), Some(3 * 1024 * 1024), 4096),
Err(Error::InvalidSegmentSize(_))
));
info!("非 2 的幂段尺寸拒绝校验通过 (NonPowerOfTwoSegmentSize_Throws)");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn segment_size_smaller_than_sector_throws() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
assert!(matches!(
SegmentedDevice::new(dir.path().join("seg_small1.log"), Some(512), 4096),
Err(Error::InvalidSegmentSize(512))
));
assert!(matches!(
SegmentedDevice::new(dir.path().join("seg_small2.log"), Some(256), 512),
Err(Error::InvalidSegmentSize(256))
));
info!("小于扇区尺寸的段尺寸拒绝校验通过 (SegmentSizeSmallerThanSector_Throws)");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn zero_segment_size_throws() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
assert!(matches!(
SegmentedDevice::new(dir.path().join("seg_zero.log"), Some(0), 4096),
Err(Error::InvalidSegmentSize(0))
));
info!("0 段尺寸拒绝校验通过 (ZeroSegmentSize_Throws)");
aok::Result::<()>::Ok(())
})?;
OK
}
#[test]
fn sector_size_is_power_of_two_at_least_512() -> Void {
let rt = Runtime::new()?;
rt.block_on(async {
let dir = tempdir()?;
for sector in [512usize, 4096] {
let device =
SegmentedDevice::new(dir.path().join(format!("sec_{sector}.log")), None, sector)?;
let s = device.sector_size();
assert!(s >= 512, "扇区尺寸必须不小于 512");
assert!(s.is_power_of_two(), "扇区尺寸必须为 2 的幂,实际为 {s}");
}
for bad in [256usize, 500, 3000] {
assert!(
matches!(
SegmentedDevice::new(dir.path().join(format!("sec_bad_{bad}.log")), None, bad),
Err(Error::InvalidSectorSize { .. })
),
"扇区尺寸 {bad} 必须被拒绝"
);
}
info!("扇区尺寸 2 的幂与 512 下界校验通过 (SectorSize_IsPowerOfTwoAtLeast512)");
aok::Result::<()>::Ok(())
})?;
OK
}