diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 0ac56666201..5a8cc1e8c12 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -858,7 +858,10 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { if cfg.BuildCoverPkg != nil { match := make([]func(*load.Package) bool, len(cfg.BuildCoverPkg)) for i := range cfg.BuildCoverPkg { - match[i] = load.MatchPackage(cfg.BuildCoverPkg[i], base.Cwd()) + match[i] = func(p *load.Package) bool { + cwd := base.Cwd() + return load.MatchPackage(cfg.BuildCoverPkg[i], cwd)(p) && !isUnderSpecial(cwd, p.Dir) + } } // Select for coverage all dependencies matching the -coverpkg @@ -2112,3 +2115,36 @@ func testBinaryName(p *load.Package) string { return elem + ".test" } + +// isUnderSpecial checks whether dir is contained within a 'special' directory under 'cwd'. +// A directory is special if it beings with "." or "_" , or is called "testdata" +func isUnderSpecial(cwd string, dir string) bool { + rel, err := filepath.Rel(cwd, dir) + if err != nil { + return false + } + + hasAnyPrefix := func(dir string, prefixes ...string) bool { + for _, prefix := range prefixes { + if strings.HasPrefix(dir, prefix) { + return true + } + } + return false + } + + sep := string(filepath.Separator) + if rel == "." || hasAnyPrefix(rel, ".."+sep) { + // Not a special directory under 'cwd', so can return immediately + return false + } + + // Otherwise avoid special directories "testdata" or beginning with ".", "_". + pathComponents := strings.Split(rel, sep) + for _, elem := range pathComponents { + if hasAnyPrefix(elem, ".", "_") || elem == "testdata" { + return true + } + } + return false +} diff --git a/src/cmd/go/testdata/script/coverpkg_ignores_special_dirs.txt b/src/cmd/go/testdata/script/coverpkg_ignores_special_dirs.txt new file mode 100644 index 00000000000..9ce3cbc4c4c --- /dev/null +++ b/src/cmd/go/testdata/script/coverpkg_ignores_special_dirs.txt @@ -0,0 +1,57 @@ +# test for https://github.com/golang/go/issues/66038 +[short] skip + +env GO111MODULE=off +# files +env GOPATH=$WORK/.dir${:}$WORK/_dir${:}$WORK/testdata + +cd $WORK +go test -coverpkg=./... ./... +stdout 'coverage: 100.0%' + +-- $WORK/a.go -- +package a + +// trivial function with 100% test coverage + +import ( + _ "dot_dir" + _ "under_dir" + _ "testdata_dir" +) + +func F(i int) int { + return i*i +} + +-- $WORK/a_test.go -- +package a + +import ( + "testing" +) + +func TestF(t *testing.T) { + F(2) +} + +-- $WORK/.dir/src/dot_dir/b.go -- +package dot_dir + +func G(i int) int { + return i*i +} + +-- $WORK/_dir/src/under_dir/b.go -- +package dot_dir + +func G(i int) int { + return i*i +} + +-- $WORK/testdata/src/testdata_dir/b.go -- +package testdata_dir + +func G(i int) int { + return i*i +}