use super::{scan_normalized_records, PathScanRecords};
use crate::path_name_bytes::{count_prefix_parts, normalize_bytes};
use crate::frx_load::LoadedRules;
use crate::ScanFinding;
struct PrefixForm {
prefix: &'static [u8],
hit: &'static [u8],
hit_display: &'static str,
clean: &'static [u8],
clean_display: &'static str,
}
fn load_rules() -> LoadedRules {
return crate::frx_load::test_rules("VAULTTOKEN_LONG\n");
}
fn scan_windows_form(path: &[u8], prefix: &[u8], loaded: &LoadedRules) -> PathScanRecords {
assert!(path.starts_with(prefix), "fixture prefix must be a byte prefix of its path");
let normalized: Vec<u8> = normalize_bytes(path, true);
let parts: usize = count_prefix_parts(prefix);
return scan_normalized_records(&normalized, parts, loaded);
}
fn first_name() -> Vec<ScanFinding> {
return vec![ScanFinding::Name { component: 1, rule: String::from("0") }];
}
fn assert_prefix_form(form: &PrefixForm) {
let loaded: LoadedRules = load_rules();
let hit: PathScanRecords = scan_windows_form(form.hit, form.prefix, &loaded);
assert_eq!(hit.display, form.hit_display);
assert_eq!(hit.findings, first_name());
let clean: PathScanRecords = scan_windows_form(form.clean, form.prefix, &loaded);
assert_eq!(clean.display, form.clean_display);
assert!(clean.findings.is_empty());
}
#[test]
fn drive_prefix_form() {
assert_prefix_form(&PrefixForm {
prefix: br"C:",
hit: br"C:\VAULTTOKEN_LONG\clean.txt",
hit_display: r"C\x3a/[REDACTED]/clean.txt",
clean: br"C:\clean\clean.txt",
clean_display: r"C\x3a/clean/clean.txt",
});
}
#[test]
fn drive_relative_prefix_form() {
assert_prefix_form(&PrefixForm {
prefix: br"C:",
hit: br"C:VAULTTOKEN_LONG.txt",
hit_display: r"C\x3a/[REDACTED]",
clean: br"C:clean.txt",
clean_display: r"C\x3a/clean.txt",
});
}
#[test]
fn unc_backslash_prefix_form() {
assert_prefix_form(&PrefixForm {
prefix: br"\\server\share",
hit: br"\\server\share\VAULTTOKEN_LONG\clean.txt",
hit_display: "//server/share/[REDACTED]/clean.txt",
clean: br"\\server\share\clean\clean.txt",
clean_display: "//server/share/clean/clean.txt",
});
}
#[test]
fn unc_slash_prefix_form() {
assert_prefix_form(&PrefixForm {
prefix: b"//server/share",
hit: b"//server/share/VAULTTOKEN_LONG/clean.txt",
hit_display: "//server/share/[REDACTED]/clean.txt",
clean: b"//server/share/clean/clean.txt",
clean_display: "//server/share/clean/clean.txt",
});
}
#[test]
fn verbatim_drive_prefix_form() {
assert_prefix_form(&PrefixForm {
prefix: br"\\?\C:",
hit: br"\\?\C:\VAULTTOKEN_LONG\clean.txt",
hit_display: r"//?/C\x3a/[REDACTED]/clean.txt",
clean: br"\\?\C:\clean\clean.txt",
clean_display: r"//?/C\x3a/clean/clean.txt",
});
}
#[test]
fn verbatim_unc_prefix_form() {
assert_prefix_form(&PrefixForm {
prefix: br"\\?\UNC\server\share",
hit: br"\\?\UNC\server\share\VAULTTOKEN_LONG\clean.txt",
hit_display: "//?/UNC/server/share/[REDACTED]/clean.txt",
clean: br"\\?\UNC\server\share\clean\clean.txt",
clean_display: "//?/UNC/server/share/clean/clean.txt",
});
}
#[test]
fn verbatim_name_prefix_form() {
assert_prefix_form(&PrefixForm {
prefix: br"\\?\name",
hit: br"\\?\name\VAULTTOKEN_LONG\clean.txt",
hit_display: "//?/name/[REDACTED]/clean.txt",
clean: br"\\?\name\clean\clean.txt",
clean_display: "//?/name/clean/clean.txt",
});
}
#[test]
fn device_namespace_port_prefix_form() {
assert_prefix_form(&PrefixForm {
prefix: br"\\.\COM1",
hit: br"\\.\COM1\VAULTTOKEN_LONG\clean.txt",
hit_display: "//./COM1/[REDACTED]/clean.txt",
clean: br"\\.\COM1\clean\clean.txt",
clean_display: "//./COM1/clean/clean.txt",
});
}
#[test]
fn device_namespace_drive_prefix_form() {
assert_prefix_form(&PrefixForm {
prefix: br"\\.\C:",
hit: br"\\.\C:\VAULTTOKEN_LONG\clean.txt",
hit_display: r"//./C\x3a/[REDACTED]/clean.txt",
clean: br"\\.\C:\clean\clean.txt",
clean_display: r"//./C\x3a/clean/clean.txt",
});
}
#[test]
fn device_namespace_pipe_name_with_dots() {
assert_prefix_form(&PrefixForm {
prefix: br"\\.\pipe",
hit: br"\\.\pipe\VAULTTOKEN_LONG.with.dots",
hit_display: "//./pipe/[REDACTED]",
clean: br"\\.\pipe\name.with.dots",
clean_display: "//./pipe/name.with.dots",
});
}
#[test]
fn device_name_containing_dots() {
assert_prefix_form(&PrefixForm {
prefix: br"\\.\device.with.dots",
hit: br"\\.\device.with.dots\VAULTTOKEN_LONG",
hit_display: "//./device.with.dots/[REDACTED]",
clean: br"\\.\device.with.dots\clean.txt",
clean_display: "//./device.with.dots/clean.txt",
});
}
#[test]
fn navigation_markers_after_prefix_are_not_names() {
assert_prefix_form(&PrefixForm {
prefix: br"\\.\COM1",
hit: br"\\.\COM1\.\..\VAULTTOKEN_LONG\clean.txt",
hit_display: "//./COM1/./../[REDACTED]/clean.txt",
clean: br"\\.\COM1\.\..\clean.txt",
clean_display: "//./COM1/./../clean.txt",
});
assert_prefix_form(&PrefixForm {
prefix: br"\\server\share",
hit: br"\\server\share\..\.\VAULTTOKEN_LONG",
hit_display: "//server/share/.././[REDACTED]",
clean: br"\\server\share\..\.\clean.txt",
clean_display: "//server/share/.././clean.txt",
});
}
#[test]
fn empty_components_after_prefix_are_not_names() {
assert_prefix_form(&PrefixForm {
prefix: br"\\.\COM1",
hit: br"\\.\COM1\\\VAULTTOKEN_LONG\\clean.txt",
hit_display: "//./COM1///[REDACTED]//clean.txt",
clean: br"\\.\COM1\\\clean.txt",
clean_display: "//./COM1///clean.txt",
});
}
#[test]
fn mixed_separators_keep_prefix_boundary() {
assert_prefix_form(&PrefixForm {
prefix: br"//.\COM1",
hit: br"//.\COM1/VAULTTOKEN_LONG\clean.txt",
hit_display: "//./COM1/[REDACTED]/clean.txt",
clean: br"//.\COM1/clean\clean.txt",
clean_display: "//./COM1/clean/clean.txt",
});
assert_prefix_form(&PrefixForm {
prefix: br"\\?/C:",
hit: br"\\?/C:\VAULTTOKEN_LONG",
hit_display: r"//?/C\x3a/[REDACTED]",
clean: br"\\?/C:\clean.txt",
clean_display: r"//?/C\x3a/clean.txt",
});
}
#[test]
fn non_utf8_name_after_prefix() {
assert_prefix_form(&PrefixForm {
prefix: b"\\\\.\\COM1",
hit: b"\\\\.\\COM1\\\xed\xa0\x80VAULTTOKEN_LONG\\clean.txt",
hit_display: "//./COM1/[REDACTED]/clean.txt",
clean: b"\\\\.\\COM1\\\xed\xa0\x80\\clean.txt",
clean_display: r"//./COM1/\xed\xa0\x80/clean.txt",
});
}
#[test]
fn device_name_spelled_parent_marker_is_prefix() {
assert_prefix_form(&PrefixForm {
prefix: br"\\.\..",
hit: br"\\.\..\VAULTTOKEN_LONG",
hit_display: "//./../[REDACTED]",
clean: br"\\.\..\clean.txt",
clean_display: "//./../clean.txt",
});
}
#[test]
fn empty_device_name_prefix_is_one_part() {
assert_prefix_form(&PrefixForm {
prefix: br"\\.\",
hit: br"\\.\\VAULTTOKEN_LONG",
hit_display: "//.//[REDACTED]",
clean: br"\\.\\clean.txt",
clean_display: "//.//clean.txt",
});
}
#[test]
fn unc_share_spelled_parent_marker_is_prefix() {
assert_prefix_form(&PrefixForm {
prefix: br"\\server\..",
hit: br"\\server\..\VAULTTOKEN_LONG",
hit_display: "//server/../[REDACTED]",
clean: br"\\server\..\clean.txt",
clean_display: "//server/../clean.txt",
});
}
#[test]
fn verbatim_prefix_with_current_marker_run_is_prefix() {
assert_prefix_form(&PrefixForm {
prefix: br"\\?\a/./b",
hit: br"\\?\a/./b\VAULTTOKEN_LONG",
hit_display: "//?/a/./b/[REDACTED]",
clean: br"\\?\a/./b\clean.txt",
clean_display: "//?/a/./b/clean.txt",
});
}
#[test]
fn verbatim_unc_server_spelled_parent_marker_is_prefix() {
assert_prefix_form(&PrefixForm {
prefix: br"\\?\UNC\..\share",
hit: br"\\?\UNC\..\share\VAULTTOKEN_LONG",
hit_display: "//?/UNC/../share/[REDACTED]",
clean: br"\\?\UNC\..\share\clean.txt",
clean_display: "//?/UNC/../share/clean.txt",
});
}
#[test]
fn prefix_without_following_component() {
let loaded: LoadedRules = load_rules();
let cases: [(&[u8], &[u8], &str); 5] = [
(br"\\.\COM1", br"\\.\COM1", "//./COM1"),
(br"\\.\COM1\", br"\\.\COM1", "//./COM1/"),
(br"\\?\UNC\server", br"\\?\UNC\server", "//?/UNC/server"),
(br"\\server\share", br"\\server\share", "//server/share"),
(br"C:", br"C:", r"C\x3a"),
];
for (path, prefix, display) in &cases {
let records: PathScanRecords = scan_windows_form(path, prefix, &loaded);
assert_eq!(records.display, *display);
assert!(records.findings.is_empty());
}
}