blob: 3c83b8f5434f4787450562150e9859d9c01e5e07 [file] [log] [blame]
// Copyright 2018 The CUE Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package load
import (
"strings"
"testing"
)
var matchPatternTests = `
pattern ...
match foo
pattern net
match net
not net/http
pattern net/http
match net/http
not net
pattern net...
match net net/http netchan
not not/http not/net/http
# Special cases. Quoting docs:
# First, /... at the end of the pattern can match an empty string,
# so that net/... matches both net and packages in its subdirectories, like net/http.
pattern net/...
match net net/http
not not/http not/net/http netchan
# Second, any slash-separted pattern element containing a wildcard never
# participates in a match of the "vendor" element in the path of a vendored
# package, so that ./... does not match packages in subdirectories of
# ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
# Note, however, that a directory named vendor that itself contains code
# is not a vendored package: cmd/vendor would be a command named vendor,
# and the pattern cmd/... matches it.
pattern ./...
match ./vendor ./mycode/vendor
not ./vendor/foo ./mycode/vendor/foo
pattern ./vendor/...
match ./vendor/foo ./vendor/foo/vendor
not ./vendor/foo/vendor/bar
pattern mycode/vendor/...
match mycode/vendor mycode/vendor/foo mycode/vendor/foo/vendor
not mycode/vendor/foo/vendor/bar
pattern x/vendor/y
match x/vendor/y
not x/vendor
pattern x/vendor/y/...
match x/vendor/y x/vendor/y/z x/vendor/y/vendor x/vendor/y/z/vendor
not x/vendor/y/vendor/z
pattern .../vendor/...
match x/vendor/y x/vendor/y/z x/vendor/y/vendor x/vendor/y/z/vendor
`
func TestMatchPattern(t *testing.T) {
testPatterns(t, "MatchPattern", matchPatternTests, func(pattern, name string) bool {
return matchPattern(pattern)(name)
})
}
var treeCanMatchPatternTests = `
pattern ...
match foo
pattern net
match net
not net/http
pattern net/http
match net net/http
pattern net...
match net netchan net/http
not not/http not/net/http
pattern net/...
match net net/http
not not/http netchan
pattern abc.../def
match abcxyz
not xyzabc
pattern x/y/z/...
match x x/y x/y/z x/y/z/w
pattern x/y/z
match x x/y x/y/z
not x/y/z/w
pattern x/.../y/z
match x/a/b/c
not y/x/a/b/c
`
func TestTreeCanMatchPattern(t *testing.T) {
testPatterns(t, "TreeCanMatchPattern", treeCanMatchPatternTests, func(pattern, name string) bool {
return treeCanMatchPattern(pattern)(name)
})
}
var hasPathPrefixTests = []stringPairTest{
{"abc", "a", false},
{"a/bc", "a", true},
{"a", "a", true},
{"a/bc", "a/", true},
}
func TestHasPathPrefix(t *testing.T) {
testStringPairs(t, "hasPathPrefix", hasPathPrefixTests, hasPathPrefix)
}
type stringPairTest struct {
in1 string
in2 string
out bool
}
func testStringPairs(t *testing.T, name string, tests []stringPairTest, f func(string, string) bool) {
for _, tt := range tests {
if out := f(tt.in1, tt.in2); out != tt.out {
t.Errorf("%s(%q, %q) = %v, want %v", name, tt.in1, tt.in2, out, tt.out)
}
}
}
func testPatterns(t *testing.T, name, tests string, fn func(string, string) bool) {
var patterns []string
for _, line := range strings.Split(tests, "\n") {
if i := strings.Index(line, "#"); i >= 0 {
line = line[:i]
}
f := strings.Fields(line)
if len(f) == 0 {
continue
}
switch f[0] {
default:
t.Fatalf("unknown directive %q", f[0])
case "pattern":
patterns = f[1:]
case "match", "not":
want := f[0] == "match"
for _, pattern := range patterns {
for _, in := range f[1:] {
if fn(pattern, in) != want {
t.Errorf("%s(%q, %q) = %v, want %v", name, pattern, in, !want, want)
}
}
}
}
}
}