362 lines Β· 13.9 KB Β· Rust
RawDownload
#[test]fn component_is_windows_device() {    for device in ["con", "CONIN$", "lpt1.txt", "AUX", "Prn", "NUL", "COM9", "nul.a.b "] {        assert!(gix_validate::path::component_is_windows_device(device.into()));    }    for not_device in ["coni", "CONIN", "lpt", "AUXi", "aPrn", "NULl", "COM", "a.nul.b "] {        assert!(!gix_validate::path::component_is_windows_device(not_device.into()));    }} mod component {    use gix_validate::path::component;     const NO_OPTS: component::Options = component::Options {        protect_windows: false,        protect_hfs: false,        protect_ntfs: false,    };    const ALL_OPTS: component::Options = component::Options {        protect_windows: true,        protect_hfs: true,        protect_ntfs: true,    };     mod valid {        use bstr::ByteSlice;        use gix_validate::path::{component, component::Mode::Symlink};         use crate::path::component::{ALL_OPTS, NO_OPTS};        macro_rules! mktest {            ($name:ident, $input:expr) => {                mktest!($name, $input, ALL_OPTS);            };            ($name:ident, $input:expr, $opts:expr) => {                #[test]                fn $name() {                    assert!(gix_validate::path::component($input.as_bstr(), None, $opts).is_ok())                }            };            ($name:ident, $input:expr, $mode:expr, $opts:expr) => {                #[test]                fn $name() {                    assert!(gix_validate::path::component($input.as_bstr(), Some($mode), $opts).is_ok())                }            };        }         const UNIX_OPTS: component::Options = component::Options {            protect_windows: false,            protect_hfs: true,            protect_ntfs: true,        };         mktest!(ascii, b"ascii-only_and-that");        mktest!(unicode, "πŸ˜πŸ‘πŸ‘Œ".as_bytes());        mktest!(backslashes_on_unix, br"\", UNIX_OPTS);        mktest!(drive_letters_on_unix, b"c:", UNIX_OPTS);        mktest!(virtual_drive_letters_on_unix, "֍:".as_bytes(), UNIX_OPTS);        mktest!(unc_path_on_unix, br"\\?\pictures", UNIX_OPTS);        mktest!(not_dot_git_longer, b".gitu", NO_OPTS);        mktest!(not_dot_git_longer_all, b".gitu");        mktest!(not_dot_gitmodules_shorter, b".gitmodule", Symlink, NO_OPTS);        mktest!(not_dot_gitmodules_shorter_all, b".gitmodule", Symlink, ALL_OPTS);        mktest!(not_dot_gitmodules_longer, b".gitmodulesa", Symlink, NO_OPTS);        mktest!(not_dot_gitmodules_longer_all, b".gitmodulesa", Symlink, ALL_OPTS);        mktest!(dot_gitmodules_as_file, b".gitmodules", UNIX_OPTS);        mktest!(            starts_with_dot_git_with_backslashes_on_linux,            br".git\hooks\pre-commit",            UNIX_OPTS        );        mktest!(not_dot_git_shorter, b".gi", NO_OPTS);        mktest!(not_dot_git_shorter_ntfs_8_3, b"gi~1");        mktest!(not_dot_git_longer_ntfs_8_3, b"gitu~1");        mktest!(not_dot_git_shorter_ntfs_8_3_disabled, b"git~1", NO_OPTS);        mktest!(not_dot_git_longer_hfs, ".g\u{200c}itu".as_bytes());        mktest!(not_dot_git_shorter_hfs, ".g\u{200c}i".as_bytes());        mktest!(com_0_lower, b"com0");        mktest!(com_without_number_0_lower, b"comm");        mktest!(conout_without_dollar_with_extension, b"conout.c");        mktest!(conin_without_dollar_with_extension, b"conin.c");        mktest!(conin_without_dollar, b"conin");        mktest!(not_con, b"com");        mktest!(also_not_con, b"co");        mktest!(con_as_middle, b"x.CON.zip");        mktest!(con_after_space, b" CON");        mktest!(con_after_space_mixed, b" coN.tar.xz");        mktest!(not_nul, b"null");        mktest!(            not_dot_gitmodules_shorter_hfs,            ".gitm\u{200c}odule".as_bytes(),            Symlink,            UNIX_OPTS        );        mktest!(dot_gitmodules_as_file_hfs, ".g\u{200c}itmodules".as_bytes(), UNIX_OPTS);        mktest!(dot_gitmodules_ntfs_8_3_disabled, b"gItMOD~1", Symlink, NO_OPTS);        mktest!(            not_dot_gitmodules_longer_hfs,            "\u{200c}.gitmodulesa".as_bytes(),            Symlink,            UNIX_OPTS        );    }     mod invalid {        use bstr::ByteSlice;        use gix_validate::path::component::{Error, Mode::Symlink};         use crate::path::component::{ALL_OPTS, NO_OPTS};         macro_rules! mktest {            ($name:ident, $input:expr, $expected:pat) => {                mktest!($name, $input, $expected, ALL_OPTS);            };            ($name:ident, $input:expr, $expected:pat, $opts:expr) => {                #[test]                fn $name() {                    match gix_validate::path::component($input.as_bstr(), None, $opts) {                        Err($expected) => {}                        got => panic!("Wanted {}, got {:?}", stringify!($expected), got),                    }                }            };            ($name:ident, $input:expr, $expected:pat, $mode:expr, $opts:expr) => {                #[test]                fn $name() {                    match gix_validate::path::component($input.as_bstr(), Some($mode), $opts) {                        Err($expected) => {}                        got => panic!("Wanted {}, got {:?}", stringify!($expected), got),                    }                }            };        }         mktest!(empty, b"", Error::Empty);        mktest!(dot_git_lower, b".git", Error::DotGitDir, NO_OPTS);        mktest!(dot_git_lower_hfs, ".g\u{200c}it".as_bytes(), Error::DotGitDir);        mktest!(dot_git_mixed_hfs_simple, b".Git", Error::DotGitDir);        mktest!(dot_git_upper, b".GIT", Error::DotGitDir, NO_OPTS);        mktest!(            starts_with_dot_git_with_backslashes_on_windows,            br".git\hooks\pre-commit",            Error::PathSeparator        );        mktest!(dot_git_upper_hfs, ".GIT\u{200e}".as_bytes(), Error::DotGitDir);        mktest!(dot_git_upper_ntfs_8_3, b"GIT~1", Error::DotGitDir);        mktest!(dot_git_mixed, b".gIt", Error::DotGitDir, NO_OPTS);        mktest!(dot_git_mixed_ntfs_8_3, b"gIt~1", Error::DotGitDir);        mktest!(            dot_gitmodules_mixed,            b".gItmodules",            Error::SymlinkedGitModules,            Symlink,            NO_OPTS        );        mktest!(dot_git_mixed_hfs, "\u{206e}.gIt".as_bytes(), Error::DotGitDir);        mktest!(            dot_git_ntfs_8_3_numbers_only,            b"~1000000",            Error::SymlinkedGitModules,            Symlink,            ALL_OPTS        );        mktest!(            dot_git_ntfs_8_3_numbers_only_too,            b"~9999999",            Error::SymlinkedGitModules,            Symlink,            ALL_OPTS        );        mktest!(            dot_gitmodules_mixed_hfs,            "\u{206e}.gItmodules".as_bytes(),            Error::SymlinkedGitModules,            Symlink,            ALL_OPTS        );        mktest!(            dot_gitmodules_mixed_ntfs_8_3,            b"gItMOD~1",            Error::SymlinkedGitModules,            Symlink,            ALL_OPTS        );        mktest!(            dot_gitmodules_mixed_ntfs_stream,            b".giTmodUles:$DATA",            Error::SymlinkedGitModules,            Symlink,            ALL_OPTS        );        mktest!(            dot_gitmodules_lower_ntfs_stream_default_implicit,            b".gitmodules::$DATA",            Error::SymlinkedGitModules,            Symlink,            ALL_OPTS        );        mktest!(            ntfs_stream_default_implicit,            b"file::$DATA",            Error::WindowsIllegalCharacter        );        mktest!(            ntfs_stream_explicit,            b"file:ANYTHING_REALLY:$DATA",            Error::WindowsIllegalCharacter        );        mktest!(            dot_gitmodules_lower_ntfs_stream,            b".gitmodules:$DATA:$DATA",            Error::SymlinkedGitModules,            Symlink,            ALL_OPTS        );        mktest!(            not_gitmodules_trailing_space,            b".gitmodules x ",            Error::WindowsIllegalCharacter        );        mktest!(            not_gitmodules_trailing_stream,            b".gitmodules,:$DATA",            Error::WindowsIllegalCharacter        );        mktest!(path_separator_slash_between, b"a/b", Error::PathSeparator);        mktest!(path_separator_slash_leading, b"/a", Error::PathSeparator);        mktest!(path_separator_slash_trailing, b"a/", Error::PathSeparator);        mktest!(path_separator_slash_only, b"/", Error::PathSeparator);        mktest!(slashes_on_windows, b"/", Error::PathSeparator, ALL_OPTS);        mktest!(backslashes_on_windows, br"\", Error::PathSeparator, ALL_OPTS);        mktest!(path_separator_backslash_between, br"a\b", Error::PathSeparator);        mktest!(path_separator_backslash_leading, br"\a", Error::PathSeparator);        mktest!(path_separator_backslash_trailing, br"a\", Error::PathSeparator);        mktest!(aux_mixed, b"Aux", Error::WindowsReservedName);        mktest!(aux_with_extension, b"aux.c", Error::WindowsReservedName);        mktest!(com_lower, b"com1", Error::WindowsReservedName);        mktest!(com_upper_with_extension, b"COM9.c", Error::WindowsReservedName);        mktest!(trailing_space, b"win32 ", Error::WindowsIllegalCharacter);        mktest!(trailing_dot, b"win32.", Error::WindowsIllegalCharacter);        mktest!(trailing_dot_dot, b"win32 . .", Error::WindowsIllegalCharacter);        mktest!(colon_inbetween, b"colon:separates", Error::WindowsIllegalCharacter);        mktest!(left_arrow, b"arrow<left", Error::WindowsIllegalCharacter);        mktest!(right_arrow, b"arrow>right", Error::WindowsIllegalCharacter);        mktest!(apostrophe, b"a\"b", Error::WindowsIllegalCharacter);        mktest!(pipe, b"a|b", Error::WindowsIllegalCharacter);        mktest!(questionmark, b"a?b", Error::WindowsIllegalCharacter);        mktest!(asterisk, b"a*b", Error::WindowsIllegalCharacter);        mktest!(lpt_mixed_with_number, b"LPt8", Error::WindowsReservedName);        mktest!(nul_mixed, b"NuL", Error::WindowsReservedName);        mktest!(prn_mixed_with_extension, b"PrN.abc", Error::WindowsReservedName);        mktest!(con, b"CON", Error::WindowsReservedName);        mktest!(con_with_extension, b"CON.abc", Error::WindowsReservedName);        mktest!(con_with_middle, b"CON.tar.xz", Error::WindowsReservedName);        mktest!(con_mixed_with_middle, b"coN.tar.xz ", Error::WindowsReservedName);        mktest!(dot_dot, b"..", Error::Relative);        mktest!(dot_dot_no_opts, b"..", Error::Relative, NO_OPTS);        mktest!(single_dot, b".", Error::Relative);        mktest!(single_dot_no_opts, b".", Error::Relative, NO_OPTS);        mktest!(            conout_mixed_with_extension,            b"ConOut$  .xyz",            Error::WindowsReservedName        );        mktest!(conin_mixed, b"conIn$  ", Error::WindowsReservedName);        mktest!(drive_letters, b"c:", Error::WindowsPathPrefix, ALL_OPTS);        mktest!(            virtual_drive_letters,            "֍:".as_bytes(),            Error::WindowsPathPrefix,            ALL_OPTS        );        mktest!(unc_net_path, br"\\host", Error::PathSeparator, ALL_OPTS);        mktest!(unc_path, br"\\?\pictures", Error::PathSeparator, ALL_OPTS);        mktest!(unc_device_path, br"\\.\pictures", Error::PathSeparator, ALL_OPTS);        mktest!(unc_nt_obj_path, br"\??\pictures", Error::PathSeparator, ALL_OPTS);         #[test]        fn ntfs_gitmodules() {            for invalid in [                ".gitmodules",                ".Gitmodules",                ".gitmoduleS",                ".gitmodules ",                ".gitmodules.",                ".gitmodules  ",                ".gitmodules. ",                ".gitmodules .",                ".gitmodules..",                ".gitmodules   ",                ".gitmodules.  ",                ".gitmodules . ",                ".gitmodules  .",                ".Gitmodules ",                ".Gitmodules.",                ".Gitmodules  ",                ".Gitmodules. ",                ".Gitmodules .",                ".Gitmodules..",                ".Gitmodules   ",                ".Gitmodules.  ",                ".Gitmodules . ",                ".Gitmodules  .",                "GITMOD~1",                "gitmod~1",                "GITMOD~2",                "giTmod~3",                "GITMOD~4",                "GITMOD~1 ",                "gitMod~2.",                "GITMOD~3  ",                "gitmod~4. ",                "GITMoD~1 .",                "gitmod~2   ",                "GITMOD~3.  ",                "gitmoD~4 . ",                "GI7EBA~1",                "gi7eba~9",                "GI7EB~10",                "GI7EB~11",                "GI7EB~99",                "GI7EB~10",                "GI7E~100",                "GI7E~101",                "GI7E~999",                ".gitmodules:$DATA",                "gitmod~4 . :$DATA",            ] {                match gix_validate::path::component(invalid.into(), Some(Symlink), ALL_OPTS) {                    Ok(_) => {                        unreachable!("{invalid:?} should not validate successfully")                    }                    Err(err) => {                        assert!(matches!(err, Error::SymlinkedGitModules));                    }                }            }             for valid in [                ".gitmodules x",                ".gitmodules .x",                " .gitmodules",                "..gitmodules",                "gitmodules",                ".gitmodule",                ".gitmodules .x",                "GI7EBA~",                "GI7EBA~0",                "GI7EBA~~1",                "GI7EBA~X",                "Gx7EBA~1",                "GI7EBX~1",                "GI7EB~1",                "GI7EB~01",                "GI7EB~1X",            ] {                gix_validate::path::component(valid.into(), Some(Symlink), ALL_OPTS)                    .unwrap_or_else(|_| panic!("{valid:?} should have been valid"));            }        }    }}