Add unit test for (*Pattern).compile

Signed-off-by: Aaron Lehmann <alehmann@netflix.com>
This commit is contained in:
Aaron Lehmann 2022-01-12 10:31:13 -08:00
parent dd66dcad9c
commit 8d250be008
2 changed files with 73 additions and 4 deletions

View File

@ -313,7 +313,7 @@ func (p *Pattern) Exclusion() bool {
func (p *Pattern) match(path string) (bool, error) {
if p.matchType == unknownMatch {
if err := p.compile(); err != nil {
if err := p.compile(string(os.PathSeparator)); err != nil {
return false, filepath.ErrBadPattern
}
}
@ -339,7 +339,7 @@ func (p *Pattern) match(path string) (bool, error) {
return false, nil
}
func (p *Pattern) compile() error {
func (p *Pattern) compile(sl string) error {
regStr := "^"
pattern := p.cleanedPattern
// Go through the pattern and convert it to a regexp.
@ -347,7 +347,6 @@ func (p *Pattern) compile() error {
var scan scanner.Scanner
scan.Init(strings.NewReader(pattern))
sl := string(os.PathSeparator)
escSL := sl
if sl == `\` {
escSL += `\`

View File

@ -675,7 +675,7 @@ func errp(e error) string {
return e.Error()
}
// TestMatch test's our version of filepath.Match, called regexpMatch.
// TestMatch tests our version of filepath.Match, called Matches.
func TestMatch(t *testing.T) {
for _, tt := range matchTests {
pattern := tt.pattern
@ -694,3 +694,73 @@ func TestMatch(t *testing.T) {
}
}
}
type compileTestCase struct {
pattern string
matchType matchType
compiledRegexp string
windowsCompiledRegexp string
}
var compileTests = []compileTestCase{
{"*", regexpMatch, `^[^/]*$`, `^[^\\]*$`},
{"file*", regexpMatch, `^file[^/]*$`, `^file[^\\]*$`},
{"*file", regexpMatch, `^[^/]*file$`, `^[^\\]*file$`},
{"a*/b", regexpMatch, `^a[^/]*/b$`, `^a[^\\]*\\b$`},
{"**", suffixMatch, "", ""},
{"**/**", regexpMatch, `^(.*/)?.*$`, `^(.*\\)?.*$`},
{"dir/**", prefixMatch, "", ""},
{"**/dir", suffixMatch, "", ""},
{"**/dir2/*", regexpMatch, `^(.*/)?dir2/[^/]*$`, `^(.*\\)?dir2\\[^\\]*$`},
{"**/dir2/**", regexpMatch, `^(.*/)?dir2/.*$`, `^(.*\\)?dir2\\.*$`},
{"**file", suffixMatch, "", ""},
{"**/file*txt", regexpMatch, `^(.*/)?file[^/]*txt$`, `^(.*\\)?file[^\\]*txt$`},
{"**/**/*.txt", regexpMatch, `^(.*/)?(.*/)?[^/]*\.txt$`, `^(.*\\)?(.*\\)?[^\\]*\.txt$`},
{"a[b-d]e", regexpMatch, `^a[b-d]e$`, `^a[b-d]e$`},
{".*", regexpMatch, `^\.[^/]*$`, `^\.[^\\]*$`},
{"abc.def", exactMatch, "", ""},
{"abc?def", regexpMatch, `^abc[^/]def$`, `^abc[^\\]def$`},
{"**/foo/bar", suffixMatch, "", ""},
{"a(b)c/def", exactMatch, "", ""},
{"a.|)$(}+{bc", exactMatch, "", ""},
{"dist/proxy.py-2.4.0rc3.dev36+g08acad9-py3-none-any.whl", exactMatch, "", ""},
}
// TestCompile confirms that "compile" assigns the correct match type to a
// variety of test case patterns. If the match type is regexp, it also confirms
// that the compiled regexp matches the expected regexp.
func TestCompile(t *testing.T) {
t.Run("slash", testCompile("/"))
t.Run("backslash", testCompile(`\`))
}
func testCompile(sl string) func(*testing.T) {
return func(t *testing.T) {
for _, tt := range compileTests {
pattern := tt.pattern
if sl != "/" {
pattern = strings.ReplaceAll(pattern, "/", sl)
}
pm, err := NewPatternMatcher([]string{pattern})
if err != nil {
t.Fatalf("Failed to create PatternMatcher for pattern %q: %v", pattern, err)
}
if err := pm.patterns[0].compile(sl); err != nil {
t.Fatalf("Failed to compile pattern %q: %v", pattern, err)
}
if pm.patterns[0].matchType != tt.matchType {
t.Errorf("pattern %q: matchType = %v, want %v", pattern, pm.patterns[0].matchType, tt.matchType)
continue
}
if tt.matchType == regexpMatch {
if sl == `\` {
if pm.patterns[0].regexp.String() != tt.windowsCompiledRegexp {
t.Errorf("pattern %q: regexp = %s, want %s", pattern, pm.patterns[0].regexp, tt.windowsCompiledRegexp)
}
} else if pm.patterns[0].regexp.String() != tt.compiledRegexp {
t.Errorf("pattern %q: regexp = %s, want %s", pattern, pm.patterns[0].regexp, tt.compiledRegexp)
}
}
}
}
}