// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filepath_test import ( "io/ioutil" "os" . "path/filepath" "runtime" "strings" "testing" ) type MatchTest struct { pattern, s string match bool err error } var matchTests = []MatchTest{ {"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, nil}, {"a[", "ab", false, ErrBadPattern}, {"*x", "xxx", true, nil}, } func errp(e error) string { if e == nil { return "" } return e.Error() } func TestMatch(t *testing.T) { for _, tt := range matchTests { pattern := tt.pattern s := tt.s if runtime.GOOS == "windows" { if strings.Contains(pattern, "\\") { // no escape allowed on windows. continue } pattern = Clean(pattern) s = Clean(s) } ok, err := Match(pattern, s) if ok != tt.match || err != tt.err { t.Errorf("Match(%#q, %#q) = %v, %q want %v, %q", pattern, s, ok, errp(err), tt.match, errp(tt.err)) } } } // contains returns true if vector contains the string s. func contains(vector []string, s string) bool { for _, elem := range vector { if elem == s { return true } } return false } var globTests = []struct { pattern, result string }{ {"match.go", "match.go"}, {"mat?h.go", "match.go"}, {"*", "match.go"}, {"../*/match.go", "../filepath/match.go"}, } func TestGlob(t *testing.T) { for _, tt := range globTests { pattern := tt.pattern result := tt.result if runtime.GOOS == "windows" { pattern = Clean(pattern) result = Clean(result) } matches, err := Glob(pattern) if err != nil { t.Errorf("Glob error for %q: %s", pattern, err) continue } if !contains(matches, result) { t.Errorf("Glob(%#q) = %#v want %v", pattern, matches, result) } } for _, pattern := range []string{"no_match", "../*/no_match"} { matches, err := Glob(pattern) if err != nil { t.Errorf("Glob error for %q: %s", pattern, err) continue } if len(matches) != 0 { t.Errorf("Glob(%#q) = %#v want []", pattern, matches) } } } func TestGlobError(t *testing.T) { _, err := Glob("[7]") if err != nil { t.Error("expected error for bad pattern; got none") } } var globSymlinkTests = []struct { path, dest string brokenLink bool }{ {"test1", "link1", false}, {"test2", "link2", true}, } func TestGlobSymlink(t *testing.T) { switch runtime.GOOS { case "android", "nacl", "plan9": t.Skipf("skipping on %s", runtime.GOOS) case "windows": if !supportsSymlinks { t.Skipf("skipping on %s", runtime.GOOS) } } tmpDir, err := ioutil.TempDir("", "globsymlink") if err != nil { t.Fatal("creating temp dir:", err) } defer os.RemoveAll(tmpDir) for _, tt := range globSymlinkTests { path := Join(tmpDir, tt.path) dest := Join(tmpDir, tt.dest) f, err := os.Create(path) if err != nil { t.Fatal(err) } if err := f.Close(); err != nil { t.Fatal(err) } err = os.Symlink(path, dest) if err != nil { t.Fatal(err) } if tt.brokenLink { // Break the symlink. os.Remove(path) } matches, err := Glob(dest) if err != nil { t.Errorf("GlobSymlink error for %q: %s", dest, err) } if !contains(matches, dest) { t.Errorf("Glob(%#q) = %#v want %v", dest, matches, dest) } } }