use super::*;
use std::env;
fn prepare_str(path: &str) -> Result<Wtf16String, RequestError> {
prepare(&Wtf16String::from(path))
}
fn text(path: &Wtf16Str) -> String {
path.to_string_lossy()
}
#[test]
fn an_empty_path_is_rejected() {
let error = prepare(&Wtf16String::new()).expect_err("an empty path names nothing");
assert_eq!(error.failure(), RequestFailure::EmptyPath);
assert_eq!(error.code(), None);
}
#[test]
fn an_interior_nul_is_rejected() {
let path = Wtf16String::from_units(&[0x0043, 0x003A, 0x005C, 0x0000, 0x0061]);
let error = prepare(&path).expect_err("an interior NUL truncates the path");
assert_eq!(error.failure(), RequestFailure::InteriorNul);
}
#[test]
fn a_verbatim_drive_path_is_kept_exactly() {
let prepared = prepare_str(r"\\?\C:\Windows\System32").expect("fully qualified");
assert_eq!(text(&prepared), r"\\?\C:\Windows\System32");
}
#[test]
fn a_verbatim_path_keeps_its_trailing_separator() {
let prepared = prepare_str(r"\\?\C:\Windows\").expect("fully qualified");
assert_eq!(text(&prepared), r"\\?\C:\Windows\");
}
#[test]
fn a_verbatim_path_keeps_dot_components_verbatim() {
let prepared = prepare_str(r"\\?\C:\a\..\b").expect("fully qualified");
assert_eq!(text(&prepared), r"\\?\C:\a\..\b");
}
#[test]
fn a_verbatim_path_may_exceed_max_path() {
let long = format!(r"\\?\C:\{}", "a".repeat(400));
let prepared = prepare_str(&long).expect("verbatim paths carry no MAX_PATH limit");
assert_eq!(text(&prepared), long);
}
#[test]
fn a_verbatim_unc_path_is_accepted() {
let prepared = prepare_str(r"\\?\UNC\server\share\dir").expect("fully qualified");
assert_eq!(text(&prepared), r"\\?\UNC\server\share\dir");
prepare_str(r"\\?\UNC\server\share").expect("a share root is fully qualified");
}
#[test]
fn a_verbatim_volume_guid_path_is_accepted() {
prepare_str(r"\\?\Volume{12345678-1234-1234-1234-123456789abc}\dir")
.expect("a volume GUID names an absolute root");
}
#[test]
fn a_drive_relative_verbatim_path_is_rejected() {
let error = prepare_str(r"\\?\C:foo").expect_err("not fully qualified");
assert_eq!(error.failure(), RequestFailure::NotFullyQualified);
}
#[test]
fn a_rootless_verbatim_path_is_rejected() {
let error = prepare_str(r"\\?\name").expect_err("no root component");
assert_eq!(error.failure(), RequestFailure::NotFullyQualified);
}
#[test]
fn a_verbatim_path_with_an_empty_root_is_rejected() {
let error = prepare_str(r"\\?\\dir").expect_err("the root component is empty");
assert_eq!(error.failure(), RequestFailure::NotFullyQualified);
}
#[test]
fn an_incomplete_verbatim_unc_path_is_rejected() {
for path in [
r"\\?\UNC\server",
r"\\?\UNC\server\",
r"\\?\UNC\\share",
r"\\?\UNC\",
] {
let error = prepare_str(path).expect_err("a server without a share names no filesystem");
assert_eq!(
error.failure(),
RequestFailure::NotFullyQualified,
"for {path}"
);
}
}
#[test]
fn an_ordinary_absolute_path_is_resolved_and_kept() {
let prepared = prepare_str(r"C:\Windows\System32").expect("resolvable");
assert_eq!(text(&prepared), r"C:\Windows\System32");
}
#[test]
fn an_ordinary_path_is_normalised_by_win32() {
let prepared = prepare_str(r"C:\Windows\..\Windows\System32").expect("resolvable");
assert_eq!(text(&prepared), r"C:\Windows\System32");
}
#[test]
fn forward_slashes_are_normalised() {
let prepared = prepare_str("C:/Windows/System32").expect("resolvable");
assert_eq!(text(&prepared), r"C:\Windows\System32");
}
#[test]
fn a_relative_path_is_snapshotted_against_the_current_directory() {
let current = env::current_dir().expect("a current directory");
let prepared = prepare_str("subdir").expect("resolvable");
let expected = current.join("subdir");
assert_eq!(text(&prepared), expected.to_string_lossy());
}
#[test]
fn an_ordinary_path_longer_than_max_path_is_rejected() {
let long = format!(r"C:\{}", "a".repeat(400));
let error = prepare_str(&long).expect_err("beyond the ordinary limit");
assert_eq!(error.failure(), RequestFailure::PathTooLong);
}
#[test]
fn a_relative_path_that_resolves_past_max_path_is_rejected() {
let current = env::current_dir().expect("a current directory");
let room = 259usize.saturating_sub(current.to_string_lossy().len());
let error = prepare_str(&"a".repeat(room + 8)).expect_err("resolves past the ordinary limit");
assert_eq!(error.failure(), RequestFailure::PathTooLong);
}
#[test]
fn a_reserved_device_name_resolves_into_the_device_namespace() {
let prepared = prepare_str("NUL").expect("resolvable");
assert_eq!(text(&prepared), r"\\.\NUL");
}
#[test]
fn a_device_namespace_path_is_resolved_rather_than_kept_verbatim() {
let prepared = prepare_str(r"\\.\C:\Windows\..\Windows").expect("resolvable");
assert_eq!(text(&prepared), r"\\.\C:\Windows");
}