From a8a3a5954468db279b6b175743c03d09cd0305b1 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Thu, 25 Jun 2026 12:02:09 +0200 Subject: [PATCH] block: Test the unaligned O_DIRECT bounce helpers Cover read_unaligned and write_unaligned directly: a scatter read at an unaligned offset, a short read at EOF, a read-modify-write gather that preserves head and tail padding, and error propagation from the scatter closure. Signed-off-by: Anatol Belski --- block/src/aligned_file.rs | 65 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/block/src/aligned_file.rs b/block/src/aligned_file.rs index 78fa9ca62..d9cf2affa 100644 --- a/block/src/aligned_file.rs +++ b/block/src/aligned_file.rs @@ -419,4 +419,69 @@ mod tests { assert_eq!(af.write(&[]).unwrap(), 0); assert_eq!(af.position, 1); } + + #[test] + fn read_unaligned_scatters_in_a_single_copy() { + let file = pattern_file(8192); + let aligned_file = forced(file.as_file().try_clone().unwrap(), 512); + let mut out = vec![0u8; 200]; + let n = aligned_file + .read_unaligned(100, 200, |data| { + out.copy_from_slice(data); + Ok(()) + }) + .unwrap(); + assert_eq!(n, 200); + let want: Vec = (100..300).map(|i| (i % 251) as u8).collect(); + assert_eq!(out, want); + } + + #[test] + fn read_unaligned_closure_short_at_eof() { + let file = pattern_file(100); + let aligned_file = forced(file.as_file().try_clone().unwrap(), 512); + let mut seen = 0usize; + let n = aligned_file + .read_unaligned(10, 200, |data| { + seen = data.len(); + Ok(()) + }) + .unwrap(); + assert_eq!(n, 90); + assert_eq!(seen, 90); + } + + #[test] + fn write_unaligned_gather_is_rmw() { + let file = pattern_file(8192); + let aligned_file = forced(file.as_file().try_clone().unwrap(), 512); + let data: Vec = (0..200).map(|i| ((i + 1) % 239) as u8).collect(); + let n = aligned_file + .write_unaligned(100, 200, |buf| { + buf.copy_from_slice(&data); + Ok(()) + }) + .unwrap(); + assert_eq!(n, 200); + + let mut whole = vec![0u8; 8192]; + file.as_file().read_exact_at(&mut whole, 0).unwrap(); + let before: Vec = (0..100).map(|i| (i % 251) as u8).collect(); + assert_eq!(&whole[..100], &before[..]); + assert_eq!(&whole[100..300], &data[..]); + let after: Vec = (300..8192).map(|i| (i % 251) as u8).collect(); + assert_eq!(&whole[300..], &after[..]); + } + + #[test] + fn read_unaligned_propagates_closure_error() { + let file = pattern_file(8192); + let aligned_file = forced(file.as_file().try_clone().unwrap(), 512); + let err = aligned_file + .read_unaligned(100, 200, |_| { + Err(io::Error::new(io::ErrorKind::InvalidInput, "boom")) + }) + .unwrap_err(); + assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + } }