Commit e33794fb authored by Russ Cox's avatar Russ Cox

cmd/go: redefine -coverpkg to be a pattern list

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: default avatarDavid Crawshaw <crawshaw@golang.org>
parent 283558e4
...@@ -576,7 +576,7 @@ ...@@ -576,7 +576,7 @@
// //
// Usage: // 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. // List lists the packages named by the import paths, one per line.
// //
...@@ -680,6 +680,9 @@ ...@@ -680,6 +680,9 @@
// The -json flag causes the package data to be printed in JSON format // The -json flag causes the package data to be printed in JSON format
// instead of using the template 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 // The -e flag changes the handling of erroneous packages, those that
// cannot be found or are malformed. By default, the list command // cannot be found or are malformed. By default, the list command
// prints an error to standard error for each erroneous package and // prints an error to standard error for each erroneous package and
...@@ -761,20 +764,21 @@ ...@@ -761,20 +764,21 @@
// //
// In local directory mode, go test compiles and tests the package sources // In local directory mode, go test compiles and tests the package sources
// found in the current directory and then runs the resulting test binary. // 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 // In this mode, caching (discussed below) is disabled. After the package test
// connected directly to the go command's own standard output and standard // finishes, go test prints a summary line showing the test status ('ok' or 'FAIL'),
// error, and test result caching (discussed below) is disabled. // package name, and elapsed time.
// 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 package list mode, go test compiles and tests each of the packages // 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 // 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 // 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 // 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 // the full output even for passing package tests, in order to display the
// requested benchmark results or verbose logging. In package list mode, // requested benchmark results or verbose logging.
// go test prints all test output and summary lines to standard output. //
// 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. // 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 // If go test has cached a previous test run using the same test binary and
...@@ -784,7 +788,9 @@ ...@@ -784,7 +788,9 @@
// binary again. In the summary line, go test prints '(cached)' in place of // 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 // 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 // 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: // In addition to the build flags, the flags handled by 'go test' itself are:
// //
...@@ -1517,10 +1523,10 @@ ...@@ -1517,10 +1523,10 @@
// significantly more expensive. // significantly more expensive.
// Sets -cover. // Sets -cover.
// //
// -coverpkg pkg1,pkg2,pkg3 // -coverpkg pattern1,pattern2,pattern3
// Apply coverage analysis in each test to the given list of packages. // Apply coverage analysis in each test to packages matching the patterns.
// The default is for each test to analyze only the package being tested. // 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. // Sets -cover.
// //
// -cpu 1,2,4 // -cpu 1,2,4
......
...@@ -2416,6 +2416,20 @@ func TestCoverageImportMainLoop(t *testing.T) { ...@@ -2416,6 +2416,20 @@ func TestCoverageImportMainLoop(t *testing.T) {
tg.grepStderr("not an importable package", "did not detect import main") 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) { func TestPluginNonMain(t *testing.T) {
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
......
...@@ -56,7 +56,7 @@ func (f *PerPackageFlag) set(v, cwd string) error { ...@@ -56,7 +56,7 @@ func (f *PerPackageFlag) set(v, cwd string) error {
return fmt.Errorf("missing <pattern> in <pattern>=<value>") return fmt.Errorf("missing <pattern> in <pattern>=<value>")
} }
pattern := v[:i] pattern := v[:i]
match = matchPackage(pattern, cwd) match = MatchPackage(pattern, cwd)
v = v[i+1:] v = v[i+1:]
} }
flags, err := str.SplitQuotedFields(v) flags, err := str.SplitQuotedFields(v)
...@@ -104,7 +104,7 @@ func setCmdlinePatterns(args []string, cwd string) { ...@@ -104,7 +104,7 @@ func setCmdlinePatterns(args []string, cwd string) {
} }
cmdlineMatchers = nil // allow reset for testing cmdlineMatchers = nil // allow reset for testing
for _, arg := range args { for _, arg := range args {
cmdlineMatchers = append(cmdlineMatchers, matchPackage(arg, cwd)) cmdlineMatchers = append(cmdlineMatchers, MatchPackage(arg, cwd))
} }
} }
......
...@@ -266,8 +266,8 @@ func matchPattern(pattern string) func(name string) bool { ...@@ -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. // MatchPackage(pattern, cwd)(p) reports whether package p matches pattern in the working directory cwd.
func matchPackage(pattern, cwd string) func(*Package) bool { func MatchPackage(pattern, cwd string) func(*Package) bool {
switch { switch {
case strings.HasPrefix(pattern, "./") || strings.HasPrefix(pattern, "../") || pattern == "." || pattern == "..": case strings.HasPrefix(pattern, "./") || strings.HasPrefix(pattern, "../") || pattern == "." || pattern == "..":
// Split pattern into leading pattern-free directory path // Split pattern into leading pattern-free directory path
......
...@@ -220,10 +220,10 @@ const testFlag2 = ` ...@@ -220,10 +220,10 @@ const testFlag2 = `
significantly more expensive. significantly more expensive.
Sets -cover. Sets -cover.
-coverpkg pkg1,pkg2,pkg3 -coverpkg pattern1,pattern2,pattern3
Apply coverage analysis in each test to the given list of packages. Apply coverage analysis in each test to packages matching the patterns.
The default is for each test to analyze only the package being tested. 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. Sets -cover.
-cpu 1,2,4 -cpu 1,2,4
...@@ -604,21 +604,30 @@ func runTest(cmd *base.Command, args []string) { ...@@ -604,21 +604,30 @@ func runTest(cmd *base.Command, args []string) {
var builds, runs, prints []*work.Action var builds, runs, prints []*work.Action
if testCoverPaths != nil { if testCoverPaths != nil {
// Load packages that were asked about for coverage. match := make([]func(*load.Package) bool, len(testCoverPaths))
// packagesForBuild exits if the packages cannot be loaded. matched := make([]bool, len(testCoverPaths))
testCoverPkgs = load.PackagesForBuild(testCoverPaths) for i := range testCoverPaths {
match[i] = load.MatchPackage(testCoverPaths[i], base.Cwd)
}
// Warn about -coverpkg arguments that are not actually used. // Select for coverage all dependencies matching the testCoverPaths patterns.
used := make(map[string]bool) for _, p := range load.PackageList(pkgs) {
for _, p := range pkgs { haveMatch := false
used[p.ImportPath] = true for i := range testCoverPaths {
for _, dep := range p.Deps { if match[i](p) {
used[dep] = true matched[i] = true
haveMatch = true
}
}
if haveMatch {
testCoverPkgs = append(testCoverPkgs, p)
} }
} }
for _, p := range testCoverPkgs {
if !used[p.ImportPath] { // Warn about -coverpkg arguments that are not actually used.
fmt.Fprintf(os.Stderr, "warning: no packages being tested depend on %s\n", p.ImportPath) 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])
} }
} }
......
package p
// missing import
var _ = io.DoesNotExist
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment