diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/gix-glob/tests/wildmatch/mod.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-glob/tests/wildmatch/mod.rs')
-rw-r--r-- | vendor/gix-glob/tests/wildmatch/mod.rs | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/vendor/gix-glob/tests/wildmatch/mod.rs b/vendor/gix-glob/tests/wildmatch/mod.rs new file mode 100644 index 000000000..2e74dabf3 --- /dev/null +++ b/vendor/gix-glob/tests/wildmatch/mod.rs @@ -0,0 +1,374 @@ +use std::{ + fmt::{Debug, Display, Formatter}, + panic::catch_unwind, +}; + +use bstr::ByteSlice; +use gix_glob::{pattern::Case, wildmatch, Pattern}; + +#[test] +fn corpus() { + // based on git/t/t3070.sh + let tests = [ + (1u8,1u8,1u8,1u8, "foo", "foo"), + (0,0,0,0, "foo", "bar"), + (1,1,1,1, "foo", "???"), + (0,0,0,0, "foo", "??"), + (1,1,1,1, "foo", "*"), + (1,1,1,1, "foo", "f*"), + (0,0,0,0, "foo", "*f"), + (1,1,1,1, "foo", "*foo*"), + (1,1,1,1, "foobar", "*ob*a*r*"), + (1,1,1,1, "aaaaaaabababab", "*ab"), + (1,1,1,1, "foo*", r"foo\*"), + (0,0,0,0, "foobar", r"foo\*bar"), + (1,1,1,1, r"f\oo", r"f\\oo"), + (1,1,1,1, "ball", "*[al]?"), + (0,0,0,0, "ten", "[ten]"), + (1,1,1,1, "ten", "**[!te]"), + (0,0,0,0, "ten", "**[!ten]"), + (1,1,1,1, "ten", "t[a-g]n"), + (0,0,0,0, "ten", "t[!a-g]n"), + (1,1,1,1, "ton", "t[!a-g]n"), + (1,1,1,1, "ton", "t[^a-g]n"), + (1,1,1,1, "a]b", "a[]]b"), + (1,1,1,1, "a-b", "a[]-]b"), + (1,1,1,1, "a]b", "a[]-]b"), + (0,0,0,0, "aab", "a[]-]b"), + (1,1,1,1, "aab", "a[]a-]b"), + (1,1,1,1, "]", "]"), + // Extended slash-matching features + (0,0,1,1, "foo/baz/bar", "foo*bar"), + (0,0,1,1, "foo/baz/bar", "foo**bar"), + (1,1,1,1, "foobazbar", "foo**bar"), + (1,1,1,1, "foo/baz/bar", "foo/**/bar"), + (1,1,0,0, "foo/baz/bar", "foo/**/**/bar"), + (1,1,1,1, "foo/b/a/z/bar", "foo/**/bar"), + (1,1,1,1, "foo/b/a/z/bar", "foo/**/**/bar"), + (1,1,0,0, "foo/bar", "foo/**/bar"), + (1,1,0,0, "foo/bar", "foo/**/**/bar"), + (0,0,1,1, "foo/bar", "foo?bar"), + (0,0,1,1, "foo/bar", "foo[/]bar"), + (0,0,1,1, "foo/bar", "foo[^a-z]bar"), + (0,0,1,1, "foo/bar", "f[^eiu][^eiu][^eiu][^eiu][^eiu]r"), + (1,1,1,1, "foo-bar", "f[^eiu][^eiu][^eiu][^eiu][^eiu]r"), + (1,1,0,0, "foo", "**/foo"), + (1,1,1,1, "XXX/foo", "**/foo"), + (1,1,1,1, "bar/baz/foo", "**/foo"), + (0,0,1,1, "bar/baz/foo", "*/foo"), + (0,0,1,1, "foo/bar/baz", "**/bar*"), + (1,1,1,1, "deep/foo/bar/baz", "**/bar/*"), + (0,0,1,1, "deep/foo/bar/baz/", "**/bar/*"), + (1,1,1,1, "deep/foo/bar/baz/", "**/bar/**"), + (0,0,0,0, "deep/foo/bar", "**/bar/*"), + (1,1,1,1, "deep/foo/bar/", "**/bar/**"), + (0,0,1,1, "foo/bar/baz", "**/bar**"), + (1,1,1,1, "foo/bar/baz/x", "*/bar/**"), + (0,0,1,1, "deep/foo/bar/baz/x", "*/bar/**"), + (1,1,1,1, "deep/foo/bar/baz/x", "**/bar/*/*"), + + // Various additional tests + (0,0,0,0, "acrt", "a[c-c]st"), + (1,1,1,1, "acrt", "a[c-c]rt"), + (0,0,0,0, "]", "[!]-]"), + (1,1,1,1, "a", "[!]-]"), + (0,0,0,0, "", r"\"), + (0,0,1,1, r"XXX/\", r"*/\"), + (0,0,1,1, r"XXX/\", r"*/\\"), + (1,1,1,1, "foo", "foo"), + (1,1,1,1, "@foo", "@foo"), + (0,0,0,0, "foo", "@foo"), + (1,1,1,1, "[ab]", r"\[ab]"), + (1,1,1,1, "[ab]", "[[]ab]"), + (1,1,1,1, "[ab]", "[[:]ab]"), + (0,0,0,0, "[ab]", "[[::]ab]"), + (1,1,1,1, "[ab]", "[[:digit]ab]"), + (1,1,1,1, "[ab]", r"[\[:]ab]"), + (1,1,1,1, "?a?b", r"\??\?b"), + (1,1,1,1, "abc", r"\a\b\c"), + (1,1,1,1, "foo/bar/baz/to", "**/t[o]"), + + // Character class tests + (1,1,1,1, "a1B", "[[:alpha:]][[:digit:]][[:upper:]]"), + (0,1,0,1, "a", "[[:digit:][:upper:][:space:]]"), + (1,1,1,1, "A", "[[:digit:][:upper:][:space:]]"), + (1,1,1,1, "1", "[[:digit:][:upper:][:space:]]"), + (0,0,0,0, "1", "[[:digit:][:upper:][:spaci:]]"), + (1,1,1,1, " ", "[[:digit:][:upper:][:space:]]"), + (0,0,0,0, ".", "[[:digit:][:upper:][:space:]]"), + (1,1,1,1, ".", "[[:digit:][:punct:][:space:]]"), + (1,1,1,1, "5", "[[:xdigit:]]"), + (1,1,1,1, "f", "[[:xdigit:]]"), + (1,1,1,1, "D", "[[:xdigit:]]"), + (1,1,1,1, "_", "[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]"), + (1,1,1,1, ".", "[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]"), + (1,1,1,1, "5", "[a-c[:digit:]x-z]"), + (1,1,1,1, "b", "[a-c[:digit:]x-z]"), + (1,1,1,1, "y", "[a-c[:digit:]x-z]"), + (0,0,0,0, "q", "[a-c[:digit:]x-z]"), + + // Additional tests, including some malformed wild(patterns + (1,1,1,1, "]", r"[\\-^]"), + (0,0,0,0, "[", r"[\\-^]"), + (1,1,1,1, "-", r"[\-_]"), + (1,1,1,1, "]", r"[\]]"), + (0,0,0,0, r"\]", r"[\]]"), + (0,0,0,0, r"\", r"[\]]"), + (0,0,0,0, "ab", "a[]b"), + (0,0,0,0, "ab", "[!"), + (0,0,0,0, "ab", "[-"), + (1,1,1,1, "-", "[-]"), + (0,0,0,0, "-", "[a-"), + (0,0,0,0, "-", "[!a-"), + (1,1,1,1, "-", "[--A]"), + (1,1,1,1, "5", "[--A]"), + (1,1,1,1, " ", "[ --]"), + (1,1,1,1, "$", "[ --]"), + (1,1,1,1, "-", "[ --]"), + (0,0,0,0, "0", "[ --]"), + (1,1,1,1, "-", "[---]"), + (1,1,1,1, "-", "[------]"), + (0,0,0,0, "j", "[a-e-n]"), + (1,1,1,1, "-", "[a-e-n]"), + (1,1,1,1, "a", "[!------]"), + (0,0,0,0, "[", "[]-a]"), + (1,1,1,1, "^", "[]-a]"), + (0,0,0,0, "^", "[!]-a]"), + (1,1,1,1, "[", "[!]-a]"), + (1,1,1,1, "^", "[a^bc]"), + (1,1,1,1, "-b]", "[a-]b]"), + (0,0,0,0, r"\", r"[\]"), + (1,1,1,1, r"\", r"[\\]"), + (0,0,0,0, r"\", r"[!\\]"), + (1,1,1,1, "G", r"[A-\\]"), + (0,0,0,0, "aaabbb", "b*a"), + (0,0,0,0, "aabcaa", "*ba*"), + (1,1,1,1, ",", "[,]"), + (1,1,1,1, ",", r"[\\,]"), + (1,1,1,1, r"\", r"[\\,]"), + (1,1,1,1, "-", "[,-.]"), + (0,0,0,0, "+", "[,-.]"), + (0,0,0,0, "-.]", "[,-.]"), + (1,1,1,1, "2", r"[\1-\3]"), + (1,1,1,1, "3", r"[\1-\3]"), + (0,0,0,0, "4", r"[\1-\3]"), + (1,1,1,1, r"\", r"[[-\]]"), + (1,1,1,1, "[", r"[[-\]]"), + (1,1,1,1, "]", r"[[-\]]"), + (0,0,0,0, "-", r"[[-\]]"), + + // Test recursion + (1,1,1,1, "-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1", "-*-*-*-*-*-*-12-*-*-*-m-*-*-*"), + (0,0,0,0, "-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1", "-*-*-*-*-*-*-12-*-*-*-m-*-*-*"), + (0,0,0,0, "-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1", "-*-*-*-*-*-*-12-*-*-*-m-*-*-*"), + (1,1,1,1, "XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1", "XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*"), + (0,0,0,0, "XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1", "XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*"), + (1,1,1,1, "abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt", "**/*a*b*g*n*t"), + (0,0,0,0, "abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz", "**/*a*b*g*n*t"), + (0,0,0,0, "foo", "*/*/*"), + (0,0,0,0, "foo/bar", "*/*/*"), + (1,1,1,1, "foo/bba/arr", "*/*/*"), + (0,0,1,1, "foo/bb/aa/rr", "*/*/*"), + (1,1,1,1, "foo/bb/aa/rr", "**/**/**"), + (1,1,1,1, "abcXdefXghi", "*X*i"), + (0,0,1,1, "ab/cXd/efXg/hi", "*X*i"), + (1,1,1,1, "ab/cXd/efXg/hi", "*/*X*/*/*i"), + (1,1,1,1, "ab/cXd/efXg/hi", "**/*X*/**/*i"), + + // Extra path(tests + (0,0,0,0, "foo", "fo"), + (1,1,1,1,"foo/bar", "foo/bar"), + (1,1,1,1, "foo/bar", "foo/*"), + (0,0,1,1, "foo/bba/arr", "foo/*"), + (1,1,1,1, "foo/bba/arr", "foo/**"), + (0,0,1,1, "foo/bba/arr", "foo*"), + (0,0,1,1, "foo/bba/arr", "foo/*arr"), + (0,0,1,1, "foo/bba/arr", "foo/**arr"), + (0,0,0,0, "foo/bba/arr", "foo/*z"), + (0,0,0,0, "foo/bba/arr", "foo/**z"), + (0,0,1,1, "foo/bar", "foo?bar"), + (0,0,1,1, "foo/bar", "foo[/]bar"), + (0,0,1,1, "foo/bar", "foo[^a-z]bar"), + (0,0,1,1, "ab/cXd/efXg/hi", "*Xg*i"), + + // Extra case-sensitivity tests + (0,1,0,1, "a", "[A-Z]"), + (1,1,1,1, "A", "[A-Z]"), + (0,1,0,1, "A", "[a-z]"), + (1,1,1,1, "a", "[a-z]"), + (0,1,0,1, "a", "[[:upper:]]"), + (1,1,1,1, "A", "[[:upper:]]"), + (0,1,0,1, "A", "[[:lower:]]"), + (1,1,1,1, "a", "[[:lower:]]"), + (0,1,0,1, "A", "[B-Za]"), + (1,1,1,1, "a", "[B-Za]"), + (0,1,0,1, "A", "[B-a]"), + (1,1,1,1, "a", "[B-a]"), + (0,1,0,1, "z", "[Z-y]"), + (1,1,1,1, "Z", "[Z-y]"), + ]; + + let mut failures = Vec::new(); + let mut at_least_one_panic = 0; + for (path_match, path_imatch, glob_match, glob_imatch, text, pattern_text) in tests { + let (pattern, actual) = multi_match(pattern_text, text); + let expected = expect_multi(path_match, path_imatch, glob_match, glob_imatch); + + if actual.all_panicked() { + at_least_one_panic += 1; + } else if actual != expected { + failures.push((pattern, pattern_text, text, actual, expected)); + } else { + at_least_one_panic += i32::from(actual.any_panicked()); + } + } + + dbg!(&failures); + assert_eq!(failures.len(), 0); + assert_eq!(at_least_one_panic, 0, "not a single panic in any invocation"); + + // TODO: reproduce these + // (0 0 0 0 \ + // 1 1 1 1 '\' '\' + // (0 0 0 0 \ + // E E E E 'foo' '' + // (0 0 0 0 \ + // 1 1 1 1 'a[]b' 'a[]b' + // (0 0 0 0 \ + // 1 1 1 1 'ab[' 'ab[' + // (0 0 1 1 \ + // 1 1 1 1 foo/bba/arr 'foo**' +} + +#[test] +fn brackets() { + let (_pattern, actual) = multi_match(r"[B-a]", "A"); + assert!(!actual.any_panicked()); + assert_eq!(actual, expect_multi(0, 1, 0, 1)); +} + +fn multi_match(pattern_text: &str, text: &str) -> (Pattern, MultiMatch) { + let pattern = gix_glob::Pattern::from_bytes(pattern_text.as_bytes()).expect("valid (enough) pattern"); + let actual_path_match: MatchResult = catch_unwind(|| match_file_path(&pattern, text, Case::Sensitive)).into(); + let actual_path_imatch: MatchResult = catch_unwind(|| match_file_path(&pattern, text, Case::Fold)).into(); + let actual_glob_match: MatchResult = + catch_unwind(|| gix_glob::wildmatch(pattern.text.as_bstr(), text.into(), wildmatch::Mode::empty())).into(); + let actual_glob_imatch: MatchResult = + catch_unwind(|| gix_glob::wildmatch(pattern.text.as_bstr(), text.into(), wildmatch::Mode::IGNORE_CASE)).into(); + let actual = MultiMatch { + path_match: actual_path_match, + path_imatch: actual_path_imatch, + glob_match: actual_glob_match, + glob_imatch: actual_glob_imatch, + }; + (pattern, actual) +} + +fn expect_multi(path_match: u8, path_imatch: u8, glob_match: u8, glob_imatch: u8) -> MultiMatch { + (path_match, path_imatch, glob_match, glob_imatch).into() +} + +#[derive(Eq, PartialEq)] +struct MultiMatch { + path_match: MatchResult, + path_imatch: MatchResult, + glob_match: MatchResult, + glob_imatch: MatchResult, +} + +impl MultiMatch { + fn all_panicked(&self) -> bool { + use MatchResult::Panic; + matches!(self.path_match, Panic) + && matches!(self.path_imatch, Panic) + && matches!(self.glob_match, Panic) + && matches!(self.glob_imatch, Panic) + } + fn any_panicked(&self) -> bool { + use MatchResult::Panic; + matches!(self.path_match, Panic) + || matches!(self.path_imatch, Panic) + || matches!(self.glob_match, Panic) + || matches!(self.glob_imatch, Panic) + } +} + +impl From<(u8, u8, u8, u8)> for MultiMatch { + fn from(t: (u8, u8, u8, u8)) -> Self { + MultiMatch { + path_match: t.0.into(), + path_imatch: t.1.into(), + glob_match: t.2.into(), + glob_imatch: t.3.into(), + } + } +} + +impl Debug for MultiMatch { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "({} {} {} {})", + self.path_match, self.path_imatch, self.glob_match, self.glob_imatch + ) + } +} + +enum MatchResult { + Match, + NoMatch, + Panic, +} + +impl PartialEq<Self> for MatchResult { + fn eq(&self, other: &Self) -> bool { + use MatchResult::*; + match (self, other) { + (Panic, _) | (_, Panic) => true, + (Match, NoMatch) | (NoMatch, Match) => false, + (Match, Match) | (NoMatch, NoMatch) => true, + } + } +} + +impl std::cmp::Eq for MatchResult {} + +impl From<std::thread::Result<bool>> for MatchResult { + fn from(v: std::thread::Result<bool>) -> Self { + use MatchResult::*; + match v { + Ok(v) if v => Match, + Ok(_) => NoMatch, + Err(_) => Panic, + } + } +} + +impl From<u8> for MatchResult { + fn from(v: u8) -> Self { + use MatchResult::*; + match v { + 1 => Match, + 0 => NoMatch, + _ => unreachable!("BUG: only use 0 or 1 for expected values"), + } + } +} + +impl Display for MatchResult { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + use MatchResult::*; + f.write_str(match self { + Match => "✔️", + NoMatch => "⨯", + Panic => "E", + }) + } +} + +fn match_file_path(pattern: &gix_glob::Pattern, path: &str, case: Case) -> bool { + pattern.matches_repo_relative_path(path, basename_of(path), false.into() /* is_dir */, case) +} +fn basename_of(path: &str) -> Option<usize> { + path.rfind('/').map(|pos| pos + 1) +} |