block: Add unit tests for DISCARD zero flag

Add comprehensive tests for DISCARD and WRITE_ZEROES operations:

QCOW2 zero flag test validates the complete workflow: allocate
cluster, DISCARD it, verify reads return zeros, write new data,
verify cluster reallocated.

QcowSync tests verify punch_hole and write_zeroes with Arc<Mutex<>>
sharing, including tests for cache consistency with multiple async
I/O operations.

RawFileSync tests verify punch_hole and write_zeroes using
fallocate.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-01-29 15:02:43 +01:00
committed by Rob Bradford
parent 45b115aeb0
commit 4676fdb494
3 changed files with 478 additions and 0 deletions
+42
View File
@@ -3686,6 +3686,48 @@ mod unit_tests {
});
}
#[test]
fn discard_sets_zero_flag() {
with_basic_file(&valid_header_v3(), |disk_file: RawFile| {
let mut q = QcowFile::from(disk_file).unwrap();
// Write some test data to allocate a cluster
let test_data = [0x42u8; 4096];
q.seek(SeekFrom::Start(0x10000)).expect("Failed to seek.");
q.write_all(&test_data).expect("Failed to write test data.");
// Verify data was written
let mut buf = [0u8; 4096];
q.seek(SeekFrom::Start(0x10000)).expect("Failed to seek.");
q.read_exact(&mut buf).expect("Failed to read.");
assert_eq!(buf[0], 0x42);
assert_eq!(buf[4095], 0x42);
// DISCARD the full cluster (via write_zeroes which calls punch_hole)
q.seek(SeekFrom::Start(0x10000)).expect("Failed to seek.");
let nwritten = q.write_zeroes(4096).expect("Failed to discard cluster.");
assert_eq!(nwritten, 4096);
// Verify reads now return zeros (due to zero flag)
q.seek(SeekFrom::Start(0x10000)).expect("Failed to seek.");
q.read_exact(&mut buf).expect("Failed to read.");
assert_eq!(buf[0], 0);
assert_eq!(buf[4095], 0);
// Write new data to the trimmed cluster
let new_data = [0x99u8; 4096];
q.seek(SeekFrom::Start(0x10000)).expect("Failed to seek.");
q.write_all(&new_data)
.expect("Failed to write to trimmed cluster.");
// Verify new data can be read (cluster was reallocated)
q.seek(SeekFrom::Start(0x10000)).expect("Failed to seek.");
q.read_exact(&mut buf).expect("Failed to read.");
assert_eq!(buf[0], 0x99);
assert_eq!(buf[4095], 0x99);
});
}
#[test]
fn test_header() {
with_basic_file(&valid_header_v2(), |disk_file: RawFile| {