Browse Source

Add unit test for (*Pattern).compile

Signed-off-by: Aaron Lehmann <alehmann@netflix.com>
Aaron Lehmann 3 years ago
parent
commit
8d250be008
2 changed files with 73 additions and 4 deletions
  1. 2 3
      pkg/fileutils/fileutils.go
  2. 71 1
      pkg/fileutils/fileutils_test.go

+ 2 - 3
pkg/fileutils/fileutils.go

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

+ 71 - 1
pkg/fileutils/fileutils_test.go

@@ -675,7 +675,7 @@ func errp(e error) string {
 	return e.Error()
 	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) {
 func TestMatch(t *testing.T) {
 	for _, tt := range matchTests {
 	for _, tt := range matchTests {
 		pattern := tt.pattern
 		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)
+				}
+			}
+		}
+	}
+}