use std::io;
use super::{DiskOptions, DiskPath, OpenedDisk};
use crate::dioring::tests::{TempFile, wtf};
use crate::windows_backend::{
Cached, FileOptions, OpenedFile, ReadOnly, ReadWrite, ShareMode, Unbuffered, Win32FileTarget,
WriteOnly, disk_flush_domain,
};
use durable_ioring::{Access, Capabilities, Geometry, IoTarget, WarrantyClass};
fn assembled<B: crate::windows_backend::Buffering>(
disk_number: u32,
sector: u32,
) -> (OpenedDisk<B>, TempFile) {
let temp = TempFile::new("od-assembled");
let file = OpenedFile::<Cached>::open(wtf(&temp.0), FileOptions::new().read().write())
.expect("open a file");
(
OpenedDisk::assembled(file.handle().clone(), disk_number, sector),
temp,
)
}
#[test]
fn a_disk_is_opened_sharing_every_member_unless_told_otherwise() {
assert_eq!(DiskOptions::new().share, ShareMode::ALL);
assert_eq!(DiskOptions::default().share, ShareMode::ALL);
assert_eq!(
DiskOptions::new().share(ShareMode::NONE).share,
ShareMode::NONE
);
assert_eq!(
DiskOptions::new()
.share(ShareMode::NONE)
.share(ShareMode::READ)
.share,
ShareMode::READ,
"the last call replaces the mode"
);
}
#[test]
fn a_disks_target_states_the_access_the_disk_was_opened_with() {
let temp = TempFile::new("od-access");
let file = OpenedFile::<Cached>::open(wtf(&temp.0), FileOptions::new().read().write())
.expect("open a file");
let handle = file.handle().clone();
let disk = OpenedDisk::<Unbuffered, ReadOnly>::assembled(handle.clone(), 1, 512);
assert_eq!(Win32FileTarget::from_disk(disk).access(), Access::ReadOnly);
let disk = OpenedDisk::<Unbuffered, WriteOnly>::assembled(handle.clone(), 1, 512);
assert_eq!(Win32FileTarget::from_disk(disk).access(), Access::WriteOnly);
let disk = OpenedDisk::<Unbuffered, ReadWrite>::assembled(handle, 1, 512);
assert_eq!(Win32FileTarget::from_disk(disk).access(), Access::ReadWrite);
}
#[test]
fn a_disk_is_named_by_its_number_in_the_one_form_that_names_a_disk() {
for (number, path) in [
(0, r"\\.\PhysicalDrive0"),
(1, r"\\.\PhysicalDrive1"),
(17, r"\\.\PhysicalDrive17"),
(u32::MAX, r"\\.\PhysicalDrive4294967295"),
] {
let disk = DiskPath::number(number);
assert_eq!(disk.path(), path);
assert_eq!(disk.to_string(), path);
assert_eq!(disk.disk_number(), number);
}
assert_eq!(DiskPath::number(3), DiskPath::number(3));
assert_ne!(DiskPath::number(3), DiskPath::number(30));
}
#[test]
fn a_disks_flush_domain_is_itself_in_the_bytes_a_volume_on_it_would_name() {
let (disk, _temp) = assembled::<Unbuffered>(4, 512);
assert_eq!(disk.disk_number(), 4);
assert_eq!(disk.flush_domain(), disk_flush_domain(4));
}
#[test]
fn an_unbuffered_disk_needs_its_sector_in_offset_length_and_buffer() {
let (disk, _temp) = assembled::<Unbuffered>(1, 4096);
assert_eq!(disk.geometry(), Geometry::uniform(4096).expect("valid"));
}
#[test]
fn a_cached_disk_needs_its_sector_in_offset_and_length_only() {
let (disk, _temp) = assembled::<Cached>(1, 512);
assert_eq!(disk.geometry(), Geometry::new(512, 512, 1).expect("valid"));
}
#[test]
fn an_unbuffered_disks_target_claims_shared_device_and_reports_the_disk() {
let (disk, _temp) = assembled::<Unbuffered>(6, 512);
let target = Win32FileTarget::from_disk(disk);
assert_eq!(target.warranty(), WarrantyClass::SharedDevice);
assert_eq!(target.geometry(), Geometry::uniform(512).expect("valid"));
assert_eq!(target.flush_domains(), [disk_flush_domain(6)]);
assert_eq!(
target.capabilities(),
Capabilities::NONE.with_write_through()
);
}
#[test]
fn a_cached_disks_target_claims_best_effort_and_no_write_through() {
let (disk, _temp) = assembled::<Cached>(2, 512);
let target = Win32FileTarget::from_disk(disk);
assert_eq!(target.warranty(), WarrantyClass::BestEffort);
assert!(!target.capabilities().write_through());
assert_eq!(target.flush_domains(), [disk_flush_domain(2)]);
}
#[test]
fn an_attested_disks_target_is_complete_and_nothing_else_changes() {
for (number, sector) in [(0u32, 512u32), (6, 4096), (17, 512)] {
let (disk, _temp) = assembled::<Unbuffered>(number, sector);
let (sibling, _temp2) = assembled::<Unbuffered>(number, sector);
let attested = Win32FileTarget::from_disk_attested_exclusive(disk);
let plain = Win32FileTarget::from_disk(sibling);
assert_eq!(attested.warranty(), WarrantyClass::Complete);
assert_eq!(plain.warranty(), WarrantyClass::SharedDevice);
assert_eq!(attested.flush_domains(), [disk_flush_domain(number)]);
assert_eq!(attested.flush_domains(), plain.flush_domains());
assert_eq!(attested.geometry(), plain.geometry());
assert_eq!(attested.capabilities(), plain.capabilities());
assert_eq!(attested.access(), plain.access());
}
}
#[test]
fn an_attested_disk_still_adds_declared_domains_and_never_loses_its_own() {
let (disk, _temp) = assembled::<Unbuffered>(5, 512);
let other = durable_ioring::FlushDomain::new(b"a share".to_vec());
let target = Win32FileTarget::from_disk_attested_exclusive(disk).with_domains([other.clone()]);
assert_eq!(target.warranty(), WarrantyClass::Complete);
assert_eq!(target.flush_domains(), [disk_flush_domain(5), other]);
assert_eq!(
target.with_domains([]).flush_domains(),
[disk_flush_domain(5)]
);
}
#[test]
fn a_disks_target_is_not_complete_unless_attested() {
let (disk, _temp) = assembled::<Unbuffered>(0, 512);
assert_ne!(
Win32FileTarget::from_disk(disk).warranty(),
WarrantyClass::Complete
);
}
#[test]
fn declared_domains_are_added_to_the_disks_own_and_never_take_it_away() {
let (disk, _temp) = assembled::<Unbuffered>(5, 512);
let other = durable_ioring::FlushDomain::new(b"a share".to_vec());
let target = Win32FileTarget::from_disk(disk).with_domains([other.clone()]);
assert_eq!(target.flush_domains(), [disk_flush_domain(5), other]);
assert_eq!(
target.with_domains([]).flush_domains(),
[disk_flush_domain(5)]
);
}
#[test]
fn a_disk_number_nothing_has_is_refused() {
let error = OpenedDisk::<Unbuffered>::open(DiskPath::number(u32::MAX - 1), DiskOptions::new())
.expect_err("no such disk");
assert!(
matches!(
error.kind(),
io::ErrorKind::NotFound | io::ErrorKind::PermissionDenied
),
"{error}"
);
}