diff options
Diffstat (limited to 'lib/git/ignore_pattern_test.go')
| -rw-r--r-- | lib/git/ignore_pattern_test.go | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/lib/git/ignore_pattern_test.go b/lib/git/ignore_pattern_test.go new file mode 100644 index 00000000..544cb0d8 --- /dev/null +++ b/lib/git/ignore_pattern_test.go @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2025 M. Shulhan <ms@kilabit.info> + +package git + +import ( + "regexp" + "testing" + + "git.sr.ht/~shulhan/pakakeh.go/lib/test" +) + +func TestParsePattern(t *testing.T) { + type testCase struct { + pattern string + exp ignorePattern + } + var listCase = []testCase{{ + pattern: `#`, + exp: ignorePattern{ + pattern: nil, + }, + }, { + pattern: `a #`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^(.*/|/)?a/?$`), + }, + }, { + pattern: `a \#`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^(.*/|/)?a \#/?$`), + }, + }, { + pattern: `?`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^(.*/|/)?[^/]/?$`), + }, + }, { + pattern: `!a`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^(.*/|/)?a/?$`), + isNegate: true, + }, + }, { + pattern: `*`, + exp: ignorePattern{ + pattern: nil, + }, + }, { + pattern: `*/`, + exp: ignorePattern{ + pattern: nil, + isDir: true, + }, + }, { + pattern: `**`, + exp: ignorePattern{ + pattern: nil, + }, + }, { + pattern: `***`, + exp: ignorePattern{ + pattern: nil, + }, + }, { + pattern: `**/**`, + exp: ignorePattern{ + pattern: nil, + }, + }, { + pattern: `**/**/`, + exp: ignorePattern{ + pattern: nil, + isDir: true, + }, + }, { + pattern: `**/**foo`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^(.*/|/)?[^/]*foo/?$`), + }, + }, { + pattern: `foo`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^(.*/|/)?foo/?$`), + }, + }, { + pattern: `foo/`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^(.*/|/)?foo/$`), + isDir: true, + }, + }, { + pattern: `/foo`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^/?foo/?$`), + }, + }, { + pattern: `foo/**/bar`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^/?foo(/.*)?/bar/?$`), + }, + }, { + pattern: `a+b|c`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^(.*/|/)?a\+b\|c/?$`), + }, + }, { + pattern: `(a|b)`, + exp: ignorePattern{ + pattern: regexp.MustCompile(`^(.*/|/)?\(a\|b\)/?$`), + }, + }} + for _, tc := range listCase { + var got = parsePattern([]byte(tc.pattern)) + test.Assert(t, tc.pattern, tc.exp, got) + } +} + +func TestIgnorePattern_isMatch(t *testing.T) { + type testCase struct { + listCase map[string]bool + pattern string + } + var listCase = []testCase{{ + pattern: ` foo # comment`, + listCase: map[string]bool{ + `foo`: true, + `foo/`: true, + `a/foo`: true, + `a/b/foo`: true, + `afoo`: false, + `a/foo/bar`: false, + }, + }, { + pattern: `foo/`, + listCase: map[string]bool{ + `foo/bar`: true, + `a/foo/bar`: true, + `foo`: false, + `afoo`: false, + `a/foo`: false, + }, + }, { + pattern: `/foo`, + listCase: map[string]bool{ + `foo`: true, + `foo/bar`: false, + `a/foo`: false, + `a/foo/bar`: false, + `afoo`: false, + }, + }, { + pattern: `/foo/bar`, + listCase: map[string]bool{ + `foo/bar`: true, + `foo/bar/`: true, + `foo/bar/z`: false, + `afoo/bar`: false, + `a/foo/bar`: false, + `a/foo/bar/z`: false, + }, + }, { + pattern: `foo/bar/`, + listCase: map[string]bool{ + `foo/bar/`: true, + `foo/bar/z`: true, + `foo/bar`: false, + `afoo/bar`: false, + `a/foo/bar`: false, + `a/foo/bar/z`: false, + }, + }, { + pattern: `/foo/bar/`, + listCase: map[string]bool{ + `/foo/bar/`: true, + `foo/bar/`: true, + `foo/bar/z`: true, + `foo/bar`: false, + `afoo/bar`: false, + `a/foo/bar`: false, + `a/foo/bar/z`: false, + }, + }, { + pattern: `foo*`, + listCase: map[string]bool{ + `foo`: true, + `foobar`: true, + `a/foo`: true, + `a/foobar`: true, + `a/foo/bar`: false, + }, + }, { + pattern: `foo.*`, + listCase: map[string]bool{ + `foo.`: true, + `foo.bar`: true, + `a/foo.bar`: true, + `a/foo./bar`: false, + `a/foobar`: false, + }, + }, { + pattern: `*foo`, + listCase: map[string]bool{ + `foo`: true, + `afoo`: true, + `a/foo`: true, + `a/bfoo`: true, + `foobar`: false, + `a/foo/bar`: false, + `a/foobar`: false, + }, + }, { + pattern: `foo?`, + listCase: map[string]bool{ + `food`: true, + `a/food`: true, + `foo`: false, + `foobar`: false, + `afoo`: false, + `a/foo`: false, + `a/foobar`: false, + `a/foo/bar`: false, + }, + }, { + pattern: `?foo`, + listCase: map[string]bool{ + `afoo`: true, + `a/afoo`: true, + `foo`: false, + `a/foo`: false, + `a/foobar`: false, + }, + }, { + pattern: `foo/*`, + listCase: map[string]bool{ + `foo`: false, + `foo/bar`: true, + `foo/bar/z`: false, + }, + }, { + pattern: `**/foo`, + listCase: map[string]bool{ + `foo`: true, + `/foo`: true, + `a/foo`: true, + `a/b/foo`: true, + `a/b/foo/bar`: false, + }, + }, { + pattern: `foo/**`, + listCase: map[string]bool{ + `foo/bar`: true, + `foo/bar/foo`: true, + `foo`: false, + `a/foo/bar`: false, + }, + }, { + pattern: `foo/**/bar`, + listCase: map[string]bool{ + `foo/bar`: true, + `foo/a/bar`: true, + `foo/a/b/bar`: true, + `foo/bar/foo`: false, + `bar`: false, + `a/foo/bar`: false, + `a/foo/b/bar`: false, + }, + }, { + pattern: `a+b|c`, + listCase: map[string]bool{ + `a+b|c`: true, + `aab|c`: false, + `aab`: false, + }, + }, { + pattern: `(a|b)`, + listCase: map[string]bool{ + `(a|b)`: true, + `a`: false, + `b`: false, + }, + }} + for _, tc := range listCase { + var pat = parsePattern([]byte(tc.pattern)) + for name, exp := range tc.listCase { + var got = pat.isMatch(name) + if exp != got { + t.Fatalf("%q: on %q want %t, got %t", + tc.pattern, name, exp, got) + } + } + } +} + +func TestRemoveComment(t *testing.T) { + type testCase struct { + pattern string + exp string + } + var listCase = []testCase{{ + pattern: `a#`, + exp: `a`, + }, { + pattern: `a\#`, + exp: `a\#`, + }, { + pattern: `a\##`, + exp: `a\#`, + }} + for _, tc := range listCase { + got := removeComment([]byte(tc.pattern)) + test.Assert(t, tc.pattern, tc.exp, string(got)) + } +} |
