Skip to content

Commit

Permalink
cmd/go: redefine -coverpkg to be a pattern list
Browse files Browse the repository at this point in the history
If you run

	go test -coverpkg=all fmt

one possible interpretation is that you want coverage for all the
packages involved in the fmt test, not all the packages in the world.
Because coverpkg was previously defined as a list of packages
to be loaded, however, it meant all packages in the world.

Now that the go command has a concept of package notation
being used as a matching filter instead of a direct enumeration,
apply that to -coverpkg, so that -coverpkg=all now has the
more useful filter interpretation.

Fixes #10271.
Fixes #21283.

Change-Id: Iddb77b21ba286d3dd65b62507af27e244865072d
Reviewed-on: https://go-review.googlesource.com/76876
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
  • Loading branch information
rsc committed Nov 10, 2017
1 parent 283558e commit e33794f
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 32 deletions.
32 changes: 19 additions & 13 deletions src/cmd/go/alldocs.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@
//
// Usage:
//
// go list [-e] [-f format] [-json] [build flags] [packages]
// go list [-deps] [-e] [-f format] [-json] [build flags] [packages]
//
// List lists the packages named by the import paths, one per line.
//
Expand Down Expand Up @@ -680,6 +680,9 @@
// The -json flag causes the package data to be printed in JSON format
// instead of using the template format.
//
// The -deps flag causes list to add to its output all the dependencies of
// the packages named on the command line.
//
// The -e flag changes the handling of erroneous packages, those that
// cannot be found or are malformed. By default, the list command
// prints an error to standard error for each erroneous package and
Expand Down Expand Up @@ -761,20 +764,21 @@
//
// In local directory mode, go test compiles and tests the package sources
// found in the current directory and then runs the resulting test binary.
// In this mode, the test binary runs with standard output and standard error
// connected directly to the go command's own standard output and standard
// error, and test result caching (discussed below) is disabled.
// After the package test finishes, go test prints to standard output a
// summary line showing the test status ('ok' or 'FAIL'), package name,
// and elapsed time.
// In this mode, caching (discussed below) is disabled. After the package test
// finishes, go test prints a summary line showing the test status ('ok' or 'FAIL'),
// package name, and elapsed time.
//
// In package list mode, go test compiles and tests each of the packages
// listed on the command line. If a package test passes, go test prints only
// the final 'ok' summary line. If a package test fails, go test prints the
// full test output. If invoked with the -bench or -v flag, go test prints
// the full output even for passing package tests, in order to display the
// requested benchmark results or verbose logging. In package list mode,
// go test prints all test output and summary lines to standard output.
// requested benchmark results or verbose logging.
//
// All test output and summary lines are printed to the go command's standard
// output, even if the test printed them to its own standard error.
// (The go command's standard error is reserved for printing errors building
// the tests.)
//
// In package list mode, go test also caches successful package test results.
// If go test has cached a previous test run using the same test binary and
Expand All @@ -784,7 +788,9 @@
// binary again. In the summary line, go test prints '(cached)' in place of
// the elapsed time. To disable test caching, use any test flag or argument
// other than the cacheable flags. The idiomatic way to disable test caching
// explicitly is to use -count=1.
// explicitly is to use -count=1. A cached result is treated as executing in
// no time at all, so a successful package test result will be cached and reused
// regardless of -timeout setting.
//
// In addition to the build flags, the flags handled by 'go test' itself are:
//
Expand Down Expand Up @@ -1517,10 +1523,10 @@
// significantly more expensive.
// Sets -cover.
//
// -coverpkg pkg1,pkg2,pkg3
// Apply coverage analysis in each test to the given list of packages.
// -coverpkg pattern1,pattern2,pattern3
// Apply coverage analysis in each test to packages matching the patterns.
// The default is for each test to analyze only the package being tested.
// Packages are specified as import paths.
// See 'go help packages' for a description of package patterns.
// Sets -cover.
//
// -cpu 1,2,4
Expand Down
14 changes: 14 additions & 0 deletions src/cmd/go/go_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2416,6 +2416,20 @@ func TestCoverageImportMainLoop(t *testing.T) {
tg.grepStderr("not an importable package", "did not detect import main")
}

func TestCoveragePattern(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.makeTempdir()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))

// If coverpkg=sleepy... expands by package loading
// (as opposed to pattern matching on deps)
// then it will try to load sleepybad, which does not compile,
// and the test command will fail.
tg.run("test", "-coverprofile="+filepath.Join(tg.tempdir, "cover.out"), "-coverpkg=sleepy...", "-run=^$", "sleepy1")
}

func TestPluginNonMain(t *testing.T) {
wd, err := os.Getwd()
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/go/internal/load/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (f *PerPackageFlag) set(v, cwd string) error {
return fmt.Errorf("missing <pattern> in <pattern>=<value>")
}
pattern := v[:i]
match = matchPackage(pattern, cwd)
match = MatchPackage(pattern, cwd)
v = v[i+1:]
}
flags, err := str.SplitQuotedFields(v)
Expand Down Expand Up @@ -104,7 +104,7 @@ func setCmdlinePatterns(args []string, cwd string) {
}
cmdlineMatchers = nil // allow reset for testing
for _, arg := range args {
cmdlineMatchers = append(cmdlineMatchers, matchPackage(arg, cwd))
cmdlineMatchers = append(cmdlineMatchers, MatchPackage(arg, cwd))
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/cmd/go/internal/load/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ func matchPattern(pattern string) func(name string) bool {
}
}

// matchPackage(pattern, cwd)(p) reports whether package p matches pattern in the working directory cwd.
func matchPackage(pattern, cwd string) func(*Package) bool {
// MatchPackage(pattern, cwd)(p) reports whether package p matches pattern in the working directory cwd.
func MatchPackage(pattern, cwd string) func(*Package) bool {
switch {
case strings.HasPrefix(pattern, "./") || strings.HasPrefix(pattern, "../") || pattern == "." || pattern == "..":
// Split pattern into leading pattern-free directory path
Expand Down
39 changes: 24 additions & 15 deletions src/cmd/go/internal/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,10 @@ const testFlag2 = `
significantly more expensive.
Sets -cover.
-coverpkg pkg1,pkg2,pkg3
Apply coverage analysis in each test to the given list of packages.
-coverpkg pattern1,pattern2,pattern3
Apply coverage analysis in each test to packages matching the patterns.
The default is for each test to analyze only the package being tested.
Packages are specified as import paths.
See 'go help packages' for a description of package patterns.
Sets -cover.
-cpu 1,2,4
Expand Down Expand Up @@ -604,21 +604,30 @@ func runTest(cmd *base.Command, args []string) {
var builds, runs, prints []*work.Action

if testCoverPaths != nil {
// Load packages that were asked about for coverage.
// packagesForBuild exits if the packages cannot be loaded.
testCoverPkgs = load.PackagesForBuild(testCoverPaths)
match := make([]func(*load.Package) bool, len(testCoverPaths))
matched := make([]bool, len(testCoverPaths))
for i := range testCoverPaths {
match[i] = load.MatchPackage(testCoverPaths[i], base.Cwd)
}

// Warn about -coverpkg arguments that are not actually used.
used := make(map[string]bool)
for _, p := range pkgs {
used[p.ImportPath] = true
for _, dep := range p.Deps {
used[dep] = true
// Select for coverage all dependencies matching the testCoverPaths patterns.
for _, p := range load.PackageList(pkgs) {
haveMatch := false
for i := range testCoverPaths {
if match[i](p) {
matched[i] = true
haveMatch = true
}
}
if haveMatch {
testCoverPkgs = append(testCoverPkgs, p)
}
}
for _, p := range testCoverPkgs {
if !used[p.ImportPath] {
fmt.Fprintf(os.Stderr, "warning: no packages being tested depend on %s\n", p.ImportPath)

// Warn about -coverpkg arguments that are not actually used.
for i := range testCoverPaths {
if !matched[i] {
fmt.Fprintf(os.Stderr, "warning: no packages being tested depend on matches for pattern %s\n", testCoverPaths[i])
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/cmd/go/testdata/src/sleepybad/p.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package p

// missing import

var _ = io.DoesNotExist

0 comments on commit e33794f

Please sign in to comment.