From c21d6bb85635b0799ec53e69de16bc11d2302fe5 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Thu, 26 Mar 2026 09:27:38 +0100 Subject: [PATCH] block: Add unit tests for query_device_size() Test regular file with odd size (not page/sector aligned), sparse file with punch hole verifying physical < logical, and char device rejection, etc. Signed-off-by: Anatol Belski --- block/src/lib.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/block/src/lib.rs b/block/src/lib.rs index 2c07276e2..d62e2717b 100644 --- a/block/src/lib.rs +++ b/block/src/lib.rs @@ -1473,4 +1473,68 @@ mod unit_tests { // SAFETY: buf was allocated with this layout via alloc_zeroed. unsafe { dealloc(buf, layout) }; } + + #[test] + fn test_query_device_size_regular_file() { + let temp_file = TempFile::new().unwrap(); + let mut f = temp_file.into_file(); + // 5 sectors + 13 extra bytes - not page aligned, not sectoraligned + f.write_all(&[0xAB; 5 * 512 + 13]).unwrap(); + f.sync_all().unwrap(); + + let (logical, physical) = query_device_size(&f).unwrap(); + assert_eq!(logical, 5 * 512 + 13); + assert!(physical > 0); + } + + #[test] + fn test_query_device_size_sparse_file_punch_hole() { + let temp_file = TempFile::new().unwrap(); + let f = temp_file.as_file(); + // Allocate 1 MiB + let size: i64 = 1 << 20; + f.set_len(size as u64).unwrap(); + // SAFETY: fd is valid, range is within file size. + let ret = unsafe { + libc::fallocate( + f.as_raw_fd(), + 0, // allocate + 0, + size, + ) + }; + assert_eq!(ret, 0, "fallocate failed: {}", io::Error::last_os_error()); + f.sync_all().unwrap(); + + let (log_before, phys_before) = query_device_size(f).unwrap(); + assert_eq!(log_before, size as u64); + assert_eq!(phys_before, size as u64); + + // Punch a hole in the middle 512 KiB + // SAFETY: fd is valid, range is within file size. + let ret = unsafe { + libc::fallocate( + f.as_raw_fd(), + libc::FALLOC_FL_PUNCH_HOLE | libc::FALLOC_FL_KEEP_SIZE, + size / 4, + size / 2, + ) + }; + assert_eq!(ret, 0, "punch hole failed: {}", io::Error::last_os_error()); + f.sync_all().unwrap(); + + let (logical, physical) = query_device_size(f).unwrap(); + assert_eq!(logical, size as u64, "logical size must not change"); + assert!( + physical < logical, + "physical ({physical}) should be less than logical ({logical}) after punch hole" + ); + } + + #[test] + fn test_query_device_size_rejects_char_device() { + let f = std::fs::File::open("/dev/zero").unwrap(); + let err = query_device_size(&f).unwrap_err(); + assert_eq!(err.kind(), io::ErrorKind::InvalidInput); + } }