blob: c9360e38d34e737dfadc72286fce80f20402aeb7 [file] [log] [blame]
// Copyright 2015 The Vanadium 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 main
import (
"go/build"
"testing"
)
func allow(expr string) rule { return rule{Allow: &expr} }
func deny(expr string) rule { return rule{Deny: &expr} }
func pkg(path string) *build.Package { return &build.Package{ImportPath: path} }
func pkgGoroot(path string) *build.Package {
p := pkg(path)
p.Goroot = true
return p
}
func TestEnforceRule(t *testing.T) {
tests := []struct {
rule rule
pkg *build.Package
result result
}{
{deny("..."), pkg("foo"), resultRejected},
{deny("..."), pkgGoroot("foo"), resultUndecided},
{allow("..."), pkg("foo"), resultApproved},
{allow("..."), pkgGoroot("foo"), resultUndecided},
{deny("foo"), pkg("foo"), resultRejected},
{deny("foo"), pkg("foo/a"), resultUndecided},
{deny("foo"), pkg("bar"), resultUndecided},
{allow("foo"), pkg("foo"), resultApproved},
{allow("foo"), pkg("foo/a"), resultUndecided},
{allow("foo"), pkg("bar"), resultUndecided},
{deny("foo/..."), pkg("foo"), resultRejected},
{deny("foo/..."), pkg("foo/a"), resultRejected},
{deny("foo/..."), pkg("foo/a/b/c"), resultRejected},
{deny("foo/..."), pkg("bar"), resultUndecided},
{deny("foo/..."), pkg("bar/foo"), resultUndecided},
{allow("foo/..."), pkg("foo"), resultApproved},
{allow("foo/..."), pkg("foo/a"), resultApproved},
{allow("foo/..."), pkg("foo/a/b/c"), resultApproved},
{allow("foo/..."), pkg("bar"), resultUndecided},
{allow("foo/..."), pkg("bar/foo"), resultUndecided},
}
for _, test := range tests {
result, err := enforceRule(test.rule, test.pkg)
if err != nil {
t.Errorf("%v %s failed: %v", test.rule, test.pkg.ImportPath, err)
}
if got, want := result, test.result; got != want {
t.Errorf("%v %s got %v, want %v", test.rule, test.pkg.ImportPath, got, want)
}
}
}
func TestVerifyGo15InternalRule(t *testing.T) {
tests := []struct {
src, dst string
want bool
}{
{"foo", "bar", true},
// Anything rooted at "a/b/c" is allowed.
{"a/b/c", "a/b/c/internal", true},
{"a/b/c/X", "a/b/c/internal", true},
{"a/b/c/X/Y", "a/b/c/internal", true},
{"a/b/c", "a/b/c/internal/d/e/f", true},
{"a/b/c/X", "a/b/c/internal/d/e/f", true},
{"a/b/c/X/Y", "a/b/c/internal/d/e/f", true},
// Things not rooted at "a/b/c" are rejected.
{"a", "a/b/c/internal", false},
{"z", "a/b/c/internal", false},
{"a/b", "a/b/c/internal", false},
{"a/b/X", "a/b/c/internal", false},
{"a/b/X/Y", "a/b/c/internal", false},
{"a/b/ccc", "a/b/c/internal", false},
{"a", "a/b/c/internal/d/e/f", false},
{"z", "a/b/c/internal/d/e/f", false},
{"a/b", "a/b/c/internal/d/e/f", false},
{"a/b/X", "a/b/c/internal/d/e/f", false},
{"a/b/X/Y", "a/b/c/internal/d/e/f", false},
{"a/b/ccc", "a/b/c/internal/d/e/f", false},
// The path component must be "internal".
{"a", "a/b/c/intern", true},
{"z", "a/b/c/intern", true},
{"a/b", "a/b/c/intern", true},
{"a/b/X", "a/b/c/intern", true},
{"a/b/X/Y", "a/b/c/intern", true},
{"a/b/ccc", "a/b/c/intern", true},
{"a", "a/b/c/internalZ/d/e/f", true},
{"z", "a/b/c/internalZ/d/e/f", true},
{"a/b", "a/b/c/internalZ/d/e/f", true},
{"a/b/X", "a/b/c/internalZ/d/e/f", true},
{"a/b/X/Y", "a/b/c/internalZ/d/e/f", true},
{"a/b/ccc", "a/b/c/internalZ/d/e/f", true},
// Multiple internal, anything rooted at "a/b/c/internal/d/e/f" is allowed.
{"a/b/c/internal/d/e/f", "a/b/c/internal/d/e/f/internal", true},
{"a/b/c/internal/d/e/f/X", "a/b/c/internal/d/e/f/internal", true},
{"a/b/c/internal/d/e/f/X/Y", "a/b/c/internal/d/e/f/internal", true},
{"a/b/c/internal/d/e/f", "a/b/c/internal/d/e/f/internal/g/h/i", true},
{"a/b/c/internal/d/e/f/X", "a/b/c/internal/d/e/f/internal/g/h/i", true},
{"a/b/c/internal/d/e/f/X/Y", "a/b/c/internal/d/e/f/internal/g/h/i", true},
// Multiple internal, things not rooted at "a/b/c/internal/d/e/f" are rejected.
{"a/b/c", "a/b/c/internal/d/e/f/internal", false},
{"a/b/c/X", "a/b/c/internal/d/e/f/internal", false},
{"a/b/c/X/Y", "a/b/c/internal/d/e/f/internal", false},
{"a/b/c/internal", "a/b/c/internal/d/e/f/internal", false},
{"a/b/c/internal/d", "a/b/c/internal/d/e/f/internal", false},
{"a/b/c/internal/d/e", "a/b/c/internal/d/e/f/internal", false},
{"a/b/c/internal/d/e/X", "a/b/c/internal/d/e/f/internal", false},
{"a/b/c/internal/d/e/X/Y", "a/b/c/internal/d/e/f/internal", false},
{"a/b/c/internal/d/e/fff", "a/b/c/internal/d/e/f/internal", false},
{"a/b/c", "a/b/c/internal/d/e/f/internal/g/h/i", false},
{"a/b/c/X", "a/b/c/internal/d/e/f/internal/g/h/i", false},
{"a/b/c/X/Y", "a/b/c/internal/d/e/f/internal/g/h/i", false},
{"a/b/c/internal", "a/b/c/internal/d/e/f/internal/g/h/i", false},
{"a/b/c/internal/d", "a/b/c/internal/d/e/f/internal/g/h/i", false},
{"a/b/c/internal/d/e", "a/b/c/internal/d/e/f/internal/g/h/i", false},
{"a/b/c/internal/d/e/X", "a/b/c/internal/d/e/f/internal/g/h/i", false},
{"a/b/c/internal/d/e/X/Y", "a/b/c/internal/d/e/f/internal/g/h/i", false},
{"a/b/c/internal/d/e/fff", "a/b/c/internal/d/e/f/internal/g/h/i", false},
}
for _, test := range tests {
got, want := verifyGo15InternalRule(test.src, test.dst), test.want
if got != want {
t.Errorf("%v failed", test)
}
}
}
func TestCheckDeps(t *testing.T) {
tests := []struct {
name string
pass bool
}{
{"v.io/x/devtools/godepcop/testdata/test-a", true},
{"v.io/x/devtools/godepcop/testdata/test-b", false},
{"v.io/x/devtools/godepcop/testdata/test-c", false},
{"v.io/x/devtools/godepcop/testdata/test-c/child", true},
{"v.io/x/devtools/godepcop/testdata/test-d", false},
{"v.io/x/devtools/godepcop/testdata/test-e", false},
{"v.io/x/devtools/godepcop/testdata/test-f", false},
{"v.io/x/devtools/godepcop/testdata/test-internal", true},
{"v.io/x/devtools/godepcop/testdata/test-internal/child", true},
{"v.io/x/devtools/godepcop/testdata/test-internal/internal/child", true},
{"v.io/x/devtools/godepcop/testdata/test-internal-fail", false},
{"v.io/x/devtools/godepcop/testdata/import-C", true},
{"v.io/x/devtools/godepcop/testdata/import-unsafe", true},
}
for _, test := range tests {
p, err := importPackage(test.name)
if err != nil {
t.Errorf("%s error loading package: %v", test.name, err)
continue
}
v, err := checkDeps(p)
if err != nil {
t.Errorf("%s failed: %v", test.name, err)
continue
}
if got, want := test.pass, len(v) == 0; got != want {
t.Errorf("%s didn't %s as expected", test.name, map[bool]string{true: "pass", false: "fail"}[test.pass])
}
}
}