Skip to content

Commit

Permalink
cmd/go: fix -coverpkg not ignoring special directories
Browse files Browse the repository at this point in the history
The pattern passed to `-coverpkg` when running `go test` would not
ignore directories usually ignored by the `go` command, i.e. those
beginning with "." or "_" are ignored by the go tool, as are directories
named "testdata".

Fix this by adding an explicit check for these (by following a similar
check in `src/cmd/doc/dirs.go`[1]) allowing us to ignore them. The
scope of the change is limted to package matching to only the -coverpkg
flag of `go test` to avoid impacting -gcflags and the other per package
flags, e.g. we don't want to change behaviour for a user building
something that imports a leading dot package who wants to set gcflags
for it

Two tests are added for this change, one is a regression test attempting
to directly replicate the behaviour described in the issue, the other is
updating another test I saw fail when trialling other solutions to this
issue so I thought it worthwhile to be explicit about the change there.

See linked issue for a reproduction.

Fixes #66038

[1] https://go.googlesource.com/go/+/16e5d24480dca7ddcbdffb78a8ed5de3e5155dec/src/cmd/doc/dirs.go#136
  • Loading branch information
matthewhughes934 committed Apr 11, 2024
1 parent 5b5d6f8 commit 09944b0
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 1 deletion.
38 changes: 37 additions & 1 deletion src/cmd/go/internal/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
57 changes: 57 additions & 0 deletions src/cmd/go/testdata/script/coverpkg_ignores_special_dirs.txt
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 09944b0

Please sign in to comment.