mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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 <anbelski@linux.microsoft.com>
This commit is contained in:
committed by
Rob Bradford
parent
5aa68ddf9e
commit
d883b54fb7
@@ -242,174 +242,34 @@ impl AsyncIo for RawFileAsyncAio {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod unit_tests {
|
mod unit_tests {
|
||||||
use std::io::{Read, Seek, SeekFrom, Write};
|
use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
use vmm_sys_util::tempfile::TempFile;
|
use vmm_sys_util::tempfile::TempFile;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::raw_async_io_tests;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_punch_hole() {
|
fn test_punch_hole() {
|
||||||
let temp_file = TempFile::new().unwrap();
|
let temp_file = TempFile::new().unwrap();
|
||||||
let mut file = temp_file.into_file();
|
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();
|
let mut async_io = RawFileAsyncAio::new(file.as_raw_fd(), 128).unwrap();
|
||||||
|
raw_async_io_tests::test_punch_hole(&mut async_io, &mut file);
|
||||||
// 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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write_zeroes() {
|
fn test_write_zeroes() {
|
||||||
let temp_file = TempFile::new().unwrap();
|
let temp_file = TempFile::new().unwrap();
|
||||||
let mut file = temp_file.into_file();
|
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();
|
let mut async_io = RawFileAsyncAio::new(file.as_raw_fd(), 128).unwrap();
|
||||||
|
raw_async_io_tests::test_write_zeroes(&mut async_io, &mut file);
|
||||||
// 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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_punch_hole_multiple_operations() {
|
fn test_punch_hole_multiple_operations() {
|
||||||
let temp_file = TempFile::new().unwrap();
|
let temp_file = TempFile::new().unwrap();
|
||||||
let mut file = temp_file.into_file();
|
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();
|
let mut async_io = RawFileAsyncAio::new(file.as_raw_fd(), 128).unwrap();
|
||||||
|
raw_async_io_tests::test_punch_hole_multiple_operations(&mut async_io, &mut file);
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,174 +211,34 @@ impl AsyncIo for RawFileSync {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod unit_tests {
|
mod unit_tests {
|
||||||
use std::io::{Read, Seek, SeekFrom, Write};
|
use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
use vmm_sys_util::tempfile::TempFile;
|
use vmm_sys_util::tempfile::TempFile;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::raw_async_io_tests;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_punch_hole() {
|
fn test_punch_hole() {
|
||||||
let temp_file = TempFile::new().unwrap();
|
let temp_file = TempFile::new().unwrap();
|
||||||
let mut file = temp_file.into_file();
|
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());
|
let mut async_io = RawFileSync::new(file.as_raw_fd());
|
||||||
|
raw_async_io_tests::test_punch_hole(&mut async_io, &mut file);
|
||||||
// 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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_write_zeroes() {
|
fn test_write_zeroes() {
|
||||||
let temp_file = TempFile::new().unwrap();
|
let temp_file = TempFile::new().unwrap();
|
||||||
let mut file = temp_file.into_file();
|
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());
|
let mut async_io = RawFileSync::new(file.as_raw_fd());
|
||||||
|
raw_async_io_tests::test_write_zeroes(&mut async_io, &mut file);
|
||||||
// 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"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_punch_hole_multiple_operations() {
|
fn test_punch_hole_multiple_operations() {
|
||||||
let temp_file = TempFile::new().unwrap();
|
let temp_file = TempFile::new().unwrap();
|
||||||
let mut file = temp_file.into_file();
|
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());
|
let mut async_io = RawFileSync::new(file.as_raw_fd());
|
||||||
|
raw_async_io_tests::test_punch_hole_multiple_operations(&mut async_io, &mut file);
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user