From d883b54fb7cf6fff2ea53645b16fb6f51f727f82 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Sat, 14 Mar 2026 12:07:57 +0100 Subject: [PATCH] block: Deduplicate raw_sync and raw_async_aio tests Replace duplicated test bodies with thin wrappers that construct the backend-specific AsyncIo instance and delegate to the shared raw_async_io_tests helpers. Signed-off-by: Anatol Belski --- block/src/raw_async_aio.rs | 150 ++----------------------------------- block/src/raw_sync.rs | 150 ++----------------------------------- 2 files changed, 10 insertions(+), 290 deletions(-) diff --git a/block/src/raw_async_aio.rs b/block/src/raw_async_aio.rs index 20fb26c2c..7f66ce411 100644 --- a/block/src/raw_async_aio.rs +++ b/block/src/raw_async_aio.rs @@ -242,174 +242,34 @@ impl AsyncIo for RawFileAsyncAio { #[cfg(test)] mod unit_tests { - use std::io::{Read, Seek, SeekFrom, Write}; + use std::os::unix::io::AsRawFd; use vmm_sys_util::tempfile::TempFile; use super::*; + use crate::raw_async_io_tests; #[test] fn test_punch_hole() { let temp_file = TempFile::new().unwrap(); let mut file = temp_file.into_file(); - - // Write 4MB of data - let data = vec![0xAA; 4 * 1024 * 1024]; - file.write_all(&data).unwrap(); - file.sync_all().unwrap(); - - // Create async IO instance let mut async_io = RawFileAsyncAio::new(file.as_raw_fd(), 128).unwrap(); - - // Punch hole in the middle (1MB at offset 1MB) - let offset = 1024 * 1024; - let length = 1024 * 1024; - async_io.punch_hole(offset, length, 1).unwrap(); - - // Check completion - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 1); - assert_eq!(result, 0); - - // Verify the hole reads as zeros - file.seek(SeekFrom::Start(offset)).unwrap(); - let mut read_buf = vec![0; length as usize]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0), - "Punched hole should read as zeros" - ); - - // Verify data before hole is intact - file.seek(SeekFrom::Start(0)).unwrap(); - let mut read_buf = vec![0; 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0xAA), - "Data before hole should be intact" - ); - - // Verify data after hole is intact - file.seek(SeekFrom::Start(offset + length)).unwrap(); - let mut read_buf = vec![0; 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0xAA), - "Data after hole should be intact" - ); + raw_async_io_tests::test_punch_hole(&mut async_io, &mut file); } #[test] fn test_write_zeroes() { let temp_file = TempFile::new().unwrap(); let mut file = temp_file.into_file(); - - // Write 4MB of data - let data = vec![0xBB; 4 * 1024 * 1024]; - file.write_all(&data).unwrap(); - file.sync_all().unwrap(); - - // Create async IO instance let mut async_io = RawFileAsyncAio::new(file.as_raw_fd(), 128).unwrap(); - - // Write zeros in the middle (512KB at offset 2MB) - let offset = 2 * 1024 * 1024; - let length = 512 * 1024; - let write_zeroes_result = async_io.write_zeroes(offset, length, 2); - - // FALLOC_FL_ZERO_RANGE might not be supported on all filesystems (e.g., tmpfs) - // If it fails with ENOTSUP, skip the test - if let Err(AsyncIoError::WriteZeroes(ref e)) = write_zeroes_result - && (e.raw_os_error() == Some(libc::EOPNOTSUPP) - || e.raw_os_error() == Some(libc::ENOTSUP)) - { - eprintln!( - "Skipping test_write_zeroes: filesystem doesn't support FALLOC_FL_ZERO_RANGE" - ); - return; - } - write_zeroes_result.unwrap(); - - // Check completion - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 2); - assert_eq!(result, 0); - - // Verify the zeroed region reads as zeros - file.seek(SeekFrom::Start(offset)).unwrap(); - let mut read_buf = vec![0; length as usize]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0), - "Zeroed region should read as zeros" - ); - - // Verify data before zeroed region is intact - file.seek(SeekFrom::Start(offset - 1024)).unwrap(); - let mut read_buf = vec![0; 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0xBB), - "Data before zeroed region should be intact" - ); - - // Verify data after zeroed region is intact - file.seek(SeekFrom::Start(offset + length)).unwrap(); - let mut read_buf = vec![0; 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0xBB), - "Data after zeroed region should be intact" - ); + raw_async_io_tests::test_write_zeroes(&mut async_io, &mut file); } #[test] fn test_punch_hole_multiple_operations() { let temp_file = TempFile::new().unwrap(); let mut file = temp_file.into_file(); - - // Write 8MB of data - let data = vec![0xCC; 8 * 1024 * 1024]; - file.write_all(&data).unwrap(); - file.sync_all().unwrap(); - - // Create async IO instance let mut async_io = RawFileAsyncAio::new(file.as_raw_fd(), 128).unwrap(); - - // Punch multiple holes - async_io.punch_hole(1024 * 1024, 512 * 1024, 10).unwrap(); - async_io - .punch_hole(3 * 1024 * 1024, 512 * 1024, 11) - .unwrap(); - async_io - .punch_hole(5 * 1024 * 1024, 512 * 1024, 12) - .unwrap(); - - // Check all completions - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 10); - assert_eq!(result, 0); - - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 11); - assert_eq!(result, 0); - - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 12); - assert_eq!(result, 0); - - // Verify all holes read as zeros - file.seek(SeekFrom::Start(1024 * 1024)).unwrap(); - let mut read_buf = vec![0; 512 * 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!(read_buf.iter().all(|&b| b == 0)); - - file.seek(SeekFrom::Start(3 * 1024 * 1024)).unwrap(); - file.read_exact(&mut read_buf).unwrap(); - assert!(read_buf.iter().all(|&b| b == 0)); - - file.seek(SeekFrom::Start(5 * 1024 * 1024)).unwrap(); - file.read_exact(&mut read_buf).unwrap(); - assert!(read_buf.iter().all(|&b| b == 0)); + raw_async_io_tests::test_punch_hole_multiple_operations(&mut async_io, &mut file); } } diff --git a/block/src/raw_sync.rs b/block/src/raw_sync.rs index 9c2d6b789..0e60a48a7 100644 --- a/block/src/raw_sync.rs +++ b/block/src/raw_sync.rs @@ -211,174 +211,34 @@ impl AsyncIo for RawFileSync { #[cfg(test)] mod unit_tests { - use std::io::{Read, Seek, SeekFrom, Write}; + use std::os::unix::io::AsRawFd; use vmm_sys_util::tempfile::TempFile; use super::*; + use crate::raw_async_io_tests; #[test] fn test_punch_hole() { let temp_file = TempFile::new().unwrap(); let mut file = temp_file.into_file(); - - // Write 4MB of data - let data = vec![0xAA; 4 * 1024 * 1024]; - file.write_all(&data).unwrap(); - file.sync_all().unwrap(); - - // Create async IO instance let mut async_io = RawFileSync::new(file.as_raw_fd()); - - // Punch hole in the middle (1MB at offset 1MB) - let offset = 1024 * 1024; - let length = 1024 * 1024; - async_io.punch_hole(offset, length, 1).unwrap(); - - // Check completion - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 1); - assert_eq!(result, 0); - - // Verify the hole reads as zeros - file.seek(SeekFrom::Start(offset)).unwrap(); - let mut read_buf = vec![0; length as usize]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0), - "Punched hole should read as zeros" - ); - - // Verify data before hole is intact - file.seek(SeekFrom::Start(0)).unwrap(); - let mut read_buf = vec![0; 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0xAA), - "Data before hole should be intact" - ); - - // Verify data after hole is intact - file.seek(SeekFrom::Start(offset + length)).unwrap(); - let mut read_buf = vec![0; 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0xAA), - "Data after hole should be intact" - ); + raw_async_io_tests::test_punch_hole(&mut async_io, &mut file); } #[test] fn test_write_zeroes() { let temp_file = TempFile::new().unwrap(); let mut file = temp_file.into_file(); - - // Write 4MB of data - let data = vec![0xBB; 4 * 1024 * 1024]; - file.write_all(&data).unwrap(); - file.sync_all().unwrap(); - - // Create async IO instance let mut async_io = RawFileSync::new(file.as_raw_fd()); - - // Write zeros in the middle (512KB at offset 2MB) - let offset = 2 * 1024 * 1024; - let length = 512 * 1024; - let write_zeroes_result = async_io.write_zeroes(offset, length, 2); - - // FALLOC_FL_ZERO_RANGE might not be supported on all filesystems (e.g., tmpfs) - // If it fails with ENOTSUP, skip the test - if let Err(AsyncIoError::WriteZeroes(ref e)) = write_zeroes_result - && (e.raw_os_error() == Some(libc::EOPNOTSUPP) - || e.raw_os_error() == Some(libc::ENOTSUP)) - { - eprintln!( - "Skipping test_write_zeroes: filesystem doesn't support FALLOC_FL_ZERO_RANGE" - ); - return; - } - write_zeroes_result.unwrap(); - - // Check completion - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 2); - assert_eq!(result, 0); - - // Verify the zeroed region reads as zeros - file.seek(SeekFrom::Start(offset)).unwrap(); - let mut read_buf = vec![0; length as usize]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0), - "Zeroed region should read as zeros" - ); - - // Verify data before zeroed region is intact - file.seek(SeekFrom::Start(offset - 1024)).unwrap(); - let mut read_buf = vec![0; 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0xBB), - "Data before zeroed region should be intact" - ); - - // Verify data after zeroed region is intact - file.seek(SeekFrom::Start(offset + length)).unwrap(); - let mut read_buf = vec![0; 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!( - read_buf.iter().all(|&b| b == 0xBB), - "Data after zeroed region should be intact" - ); + raw_async_io_tests::test_write_zeroes(&mut async_io, &mut file); } #[test] fn test_punch_hole_multiple_operations() { let temp_file = TempFile::new().unwrap(); let mut file = temp_file.into_file(); - - // Write 8MB of data - let data = vec![0xCC; 8 * 1024 * 1024]; - file.write_all(&data).unwrap(); - file.sync_all().unwrap(); - - // Create async IO instance let mut async_io = RawFileSync::new(file.as_raw_fd()); - - // Punch multiple holes - async_io.punch_hole(1024 * 1024, 512 * 1024, 10).unwrap(); - async_io - .punch_hole(3 * 1024 * 1024, 512 * 1024, 11) - .unwrap(); - async_io - .punch_hole(5 * 1024 * 1024, 512 * 1024, 12) - .unwrap(); - - // Check all completions - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 10); - assert_eq!(result, 0); - - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 11); - assert_eq!(result, 0); - - let (user_data, result) = async_io.next_completed_request().unwrap(); - assert_eq!(user_data, 12); - assert_eq!(result, 0); - - // Verify all holes read as zeros - file.seek(SeekFrom::Start(1024 * 1024)).unwrap(); - let mut read_buf = vec![0; 512 * 1024]; - file.read_exact(&mut read_buf).unwrap(); - assert!(read_buf.iter().all(|&b| b == 0)); - - file.seek(SeekFrom::Start(3 * 1024 * 1024)).unwrap(); - file.read_exact(&mut read_buf).unwrap(); - assert!(read_buf.iter().all(|&b| b == 0)); - - file.seek(SeekFrom::Start(5 * 1024 * 1024)).unwrap(); - file.read_exact(&mut read_buf).unwrap(); - assert!(read_buf.iter().all(|&b| b == 0)); + raw_async_io_tests::test_punch_hole_multiple_operations(&mut async_io, &mut file); } }