]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: redefine -coverpkg to be a pattern list
authorRuss Cox <rsc@golang.org>
Thu, 9 Nov 2017 15:29:23 +0000 (10:29 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 10 Nov 2017 18:39:10 +0000 (18:39 +0000)
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>
src/cmd/go/alldocs.go
src/cmd/go/go_test.go
src/cmd/go/internal/load/flag.go
src/cmd/go/internal/load/search.go
src/cmd/go/internal/test/test.go
src/cmd/go/testdata/src/sleepybad/p.go [new file with mode: 0644]

index 5649211aeec9553528a823da1a5b7ca2a02995d4..ddda393f471620ceb2f8aa19cb7056dbd28c55fc 100644 (file)
 //
 // 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.
 //
 // 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
 //
 // 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
 // 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:
 //
 //                     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
index 84fcac25ed4b605b10c99401e4c6481ad022c7c1..5e3c2704a6762de91fb85b99760da6d584c38967 100644 (file)
@@ -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 {
index 0a15368b1cd77325c9eed9e64a3d6307ced1b48e..d2db3ee4a053c3e302645d6d3cf0061b790a0392 100644 (file)
@@ -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)
@@ -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))
        }
 }
 
index e18f69a223b4126884be5719e7f8bf2020379377..595de079046607819192ff3ee35b72de8d8f6ac3 100644 (file)
@@ -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
index 0ead178b9a307e05e41c4dca7fd43b8c6dcc41b1..0a0f149e7d703e38652e114de7f6cf9e690e3a9c 100644 (file)
@@ -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
@@ -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])
                        }
                }
 
diff --git a/src/cmd/go/testdata/src/sleepybad/p.go b/src/cmd/go/testdata/src/sleepybad/p.go
new file mode 100644 (file)
index 0000000..e05b403
--- /dev/null
@@ -0,0 +1,5 @@
+package p
+
+// missing import
+
+var _ = io.DoesNotExist