sdk/glob/glob_test.go

220 lines
6 KiB
Go
Raw Permalink Normal View History

package glob
import (
"errors"
"fmt"
"reflect"
"strings"
"testing"
"testing/fstest"
)
type test struct {
pattern, f string
match bool
err error
}
func escape(name string) string {
// use a math division slash for correct visual
return strings.ReplaceAll(name, "/", "")
}
func TestPattern_Match(t *testing.T) {
tests := []test{
// Test cases not covered by path.Match
{"main.go", "main.go", true, nil},
{"main_test.go", "main_test.go", true, nil},
{"foo/foo_test.go", "foo/foo_test.go", true, nil},
{"?.go", "m.go", true, nil},
{"*.go", "main.go", true, nil},
{"**/*.go", "main.go", true, nil},
{"*.go", "*.go", true, nil},
{"//", "", false, ErrBadPattern},
{"foo//", "", false, ErrBadPattern},
{"*?.go", "", false, ErrBadPattern},
{"?*.go", "", false, ErrBadPattern},
{"**?.go", "", false, ErrBadPattern},
{"**f", "", false, ErrBadPattern},
{"[a-", "", false, ErrBadPattern},
{"[a-\\", "", false, ErrBadPattern},
{"[\\", "", false, ErrBadPattern},
{"**/m.go", "foo.go", false, nil},
{"**/m.go", "foo/a.go", false, nil},
{"**/m.go", "m.go", true, nil},
{"**/m.go", "foo/m.go", true, nil},
{"**/m.go", "bar/m.go", true, nil},
{"**/m.go", "foo/bar/m.go", true, nil},
{"ab[cde]", "abc", true, nil},
{"ab[cde]", "abd", true, nil},
{"ab[cde]", "abe", true, nil},
{"ab[+-\\-]", "ab-", true, nil},
{"ab[\\--a]", "ab-", true, nil},
{"[a-fA-F]", "a", true, nil},
{"[a-fA-F]", "f", true, nil},
{"[a-fA-F]", "A", true, nil},
{"[a-fA-F]", "F", true, nil},
// The following test cases are taken from
// https://github.com/golang/go/blob/master/src/path/match_test.go and are
// provided here to test compatebility of the match implementation with the
// test cases from the golang standard lib.
{"abc", "abc", true, nil},
{"*", "abc", true, nil},
{"*c", "abc", true, nil},
{"a*", "a", true, nil},
{"a*", "abc", true, nil},
{"a*", "ab/c", false, nil},
{"a*/b", "abc/b", true, nil},
{"a*/b", "a/c/b", false, nil},
{"a*b*c*d*e*/f", "axbxcxdxe/f", true, nil},
{"a*b*c*d*e*/f", "axbxcxdxexxx/f", true, nil},
{"a*b*c*d*e*/f", "axbxcxdxe/xxx/f", false, nil},
{"a*b*c*d*e*/f", "axbxcxdxexxx/fff", false, nil},
{"a*b?c*x", "abxbbxdbxebxczzx", true, nil},
{"a*b?c*x", "abxbbxdbxebxczzy", false, nil},
{"ab[c]", "abc", true, nil},
{"ab[b-d]", "abc", true, nil},
{"ab[e-g]", "abc", false, nil},
{"ab[^c]", "abc", false, nil},
{"ab[^b-d]", "abc", false, nil},
{"ab[^e-g]", "abc", true, nil},
{"a\\*b", "a*b", true, nil},
{"a\\*b", "ab", false, nil},
{"a?b", "a☺b", true, nil},
{"a[^a]b", "a☺b", true, nil},
{"a???b", "a☺b", false, nil},
{"a[^a][^a][^a]b", "a☺b", false, nil},
{"[a-ζ]*", "α", true, nil},
{"*[a-ζ]", "A", false, nil},
{"a?b", "a/b", false, nil},
{"a*b", "a/b", false, nil},
{"[\\]a]", "]", true, nil},
{"[\\-]", "-", true, nil},
{"[x\\-]", "x", true, nil},
{"[x\\-]", "-", true, nil},
{"[x\\-]", "z", false, nil},
{"[\\-x]", "x", true, nil},
{"[\\-x]", "-", true, nil},
{"[\\-x]", "a", false, nil},
{"[]a]", "]", false, ErrBadPattern},
{"[-]", "-", false, ErrBadPattern},
{"[x-]", "x", false, ErrBadPattern},
{"[x-]", "-", false, ErrBadPattern},
{"[x-]", "z", false, ErrBadPattern},
{"[-x]", "x", false, ErrBadPattern},
{"[-x]", "-", false, ErrBadPattern},
{"[-x]", "a", false, ErrBadPattern},
{"\\", "a", false, ErrBadPattern},
{"[a-b-c]", "a", false, ErrBadPattern},
{"[", "a", false, ErrBadPattern},
{"[^", "a", false, ErrBadPattern},
{"[^bc", "a", false, ErrBadPattern},
{"a[", "a", false, ErrBadPattern},
{"a[", "ab", false, ErrBadPattern},
{"a[", "x", false, ErrBadPattern},
{"a/b[", "x", false, ErrBadPattern},
{"*x", "xxx", true, nil},
}
for _, tt := range tests {
pat, err := New(tt.pattern)
if err != tt.err && !errors.Is(err, tt.err) {
t.Errorf("New(%#q): wanted error %v but got %v", tt.pattern, tt.err, err)
}
if pat != nil {
match := pat.Match(tt.f)
if match != tt.match {
t.Errorf("New(%#q).Match(%#q): wanted match %v but got %v", tt.pattern, tt.f, tt.match, match)
}
}
}
}
func TestPattern_MatchPrefix(t *testing.T) {
tests := []test{
{"**/*.go", "foo/", true, nil},
{"**/*.go", "foo", true, nil},
{"**/*.go", "foo/bar/", true, nil},
{"**/*.go", "foo/bar", true, nil},
{"*/*.go", "foo", true, nil},
}
for _, tc := range tests {
tc := tc // capture range variable
t.Run(fmt.Sprintf("%s (%s)", escape(tc.pattern), escape(tc.f)), func(t *testing.T) {
pat, err := New(tc.pattern)
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
got := pat.MatchPrefix(tc.f)
if got != tc.match {
t.Errorf("got %v; want %v", got, tc.match)
}
})
}
}
func TestPattern_GlobFS(t *testing.T) {
fsys := fstest.MapFS{
"go.mod": &fstest.MapFile{Mode: 0644},
"go.sum": &fstest.MapFile{Mode: 0644},
"cmd/main.go": &fstest.MapFile{Mode: 0644},
"cmd/main_test.go": &fstest.MapFile{Mode: 0644},
"internal/tool/tool.go": &fstest.MapFile{Mode: 0644},
"internal/tool/tool_test.go": &fstest.MapFile{Mode: 0644},
"internal/cli/cli.go": &fstest.MapFile{Mode: 0644},
"internal/cli/cli_test.go": &fstest.MapFile{Mode: 0644},
}
pat, err := New("**/*_test.go")
if err != nil {
t.Fatal(err)
}
files, err := pat.GlobFS(fsys, ".")
if err != nil {
t.Fatal(err)
}
expect := []string{
"cmd/main_test.go",
"internal/cli/cli_test.go",
"internal/tool/tool_test.go",
}
if !reflect.DeepEqual(expect, files) {
t.Errorf("got %v; want %v", files, expect)
}
}
func TestPattern_String(t *testing.T) {
tests := []string{
"main.go",
"*.go",
"**/*.go",
"foo/bar/*",
"foo/?ar.go",
"foo/[abc].go",
"foo/[a-c].go",
"foo/**/",
"foo/*/bar.go",
"foo/\\*bar.go",
}
for _, patstr := range tests {
t.Run(escape(patstr), func(t *testing.T) {
pat, err := New(patstr)
if err != nil {
t.Fatalf("New(%q) failed: %v", patstr, err)
}
if pat.String() != patstr {
t.Fatalf("Pattern.String() = %q, want %q", pat.String(), patstr)
}
})
}
}