]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go, testing: streamline direct use of test binaries
authorRuss Cox <rsc@golang.org>
Sat, 13 Jul 2013 00:40:30 +0000 (20:40 -0400)
committerRuss Cox <rsc@golang.org>
Sat, 13 Jul 2013 00:40:30 +0000 (20:40 -0400)
Before:

        $ go test -c -cover fmt
        $ ./fmt.test -test.covermode=set
        PASS
        coverage: 65.1% of statements in strconv
        $

After:

        $ go test -c -cover fmt
        $ ./fmt.test
        PASS
        coverage: 65.1% of statements in strconv
        $

In addition to being cumbersome, the old flag didn't make sense:
the cover mode cannot be changed after the binary has been built.

Another useful effect of this CL is that if you happen to do

        $ go test -c -covermode=atomic fmt

and then forget you did that and run benchmarks,
the final line of the output (the coverage summary) reminds you
that you are benchmarking with coverage enabled, which might
not be what you want.

        $ ./fmt.test -test.bench .
        PASS
        BenchmarkSprintfEmpty 10000000        217 ns/op
        BenchmarkSprintfString  2000000        755 ns/op
        BenchmarkSprintfInt  2000000        774 ns/op
        BenchmarkSprintfIntInt  1000000       1363 ns/op
        BenchmarkSprintfPrefixedInt  1000000       1501 ns/op
        BenchmarkSprintfFloat  1000000       1257 ns/op
        BenchmarkManyArgs   500000       5346 ns/op
        BenchmarkScanInts     1000    2562402 ns/op
        BenchmarkScanRecursiveInt      500    3189457 ns/op
        coverage: 91.4% of statements
        $

As part of passing the new mode setting in via _testmain.go, merge
the two registration mechanisms into one extensible mechanism
(a struct).

R=r
CC=golang-dev
https://golang.org/cl/11219043

src/cmd/go/doc.go
src/cmd/go/test.go
src/cmd/go/testflag.go
src/pkg/testing/cover.go
src/pkg/testing/testing.go

index b22e9e87c141e26271cf6c38d73d2206c10d9cb7..85aebe24e965e66bd7fe95a6f04c4cf9b8b50680 100644 (file)
@@ -744,7 +744,6 @@ control the execution of any test:
 
        -cover
            Enable coverage analysis.
-           TODO: This feature is not yet fully implemented.
 
        -covermode set,count,atomic
            Set the mode for coverage analysis for the package[s]
@@ -754,18 +753,18 @@ control the execution of any test:
                count: int: how many times does this statement run?
                atomic: int: count, but correct in multithreaded tests;
                        significantly more expensive.
-           Implies -cover.
+           Sets -cover.
 
        -coverpkg pkg1,pkg2,pkg3
            Apply coverage analysis in each test to the given list of packages.
-           If this option is not present, each test applies coverage analysis to
-           the package being tested. Packages are specified as import paths.
-           Implies -cover.
+           The default is for each test to analyze only the package being tested.
+           Packages are specified as import paths.
+           Sets -cover.
 
        -coverprofile cover.out
            Write a coverage profile to the specified file after all tests
            have passed.
-           Implies -cover.
+           Sets -cover.
 
        -cpu 1,2,4
            Specify a list of GOMAXPROCS values for which the tests or
index 50de8f292cc8dae8edb757aeb381ae3c962514a5..e51b5a45d165ce0baa7017d62aa2ec22b0257634 100644 (file)
@@ -139,18 +139,18 @@ control the execution of any test:
                count: int: how many times does this statement run?
                atomic: int: count, but correct in multithreaded tests;
                        significantly more expensive.
-           Implies -cover.
+           Sets -cover.
 
        -coverpkg pkg1,pkg2,pkg3
            Apply coverage analysis in each test to the given list of packages.
            The default is for each test to analyze only the package being tested.
            Packages are specified as import paths.
-           Implies -cover.
+           Sets -cover.
 
        -coverprofile cover.out
            Write a coverage profile to the specified file after all tests
            have passed.
-           Implies -cover.
+           Sets -cover.
 
        -cpu 1,2,4
            Specify a list of GOMAXPROCS values for which the tests or
@@ -1040,6 +1040,10 @@ type testFuncs struct {
        Cover      []coverInfo
 }
 
+func (t *testFuncs) CoverMode() string {
+       return testCoverMode
+}
+
 func (t *testFuncs) CoverEnabled() bool {
        return testCover
 }
@@ -1201,8 +1205,12 @@ func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts
 
 func main() {
 {{if .CoverEnabled}}
-       testing.CoveredPackage({{printf "%q" .Tested}}, {{printf "%q" .Covered}})
-       testing.RegisterCover(coverCounters, coverBlocks)
+       testing.RegisterCover(testing.Cover{
+               Mode: {{printf "%q" .CoverMode}},
+               Counters: coverCounters,
+               Blocks: coverBlocks,
+               CoveredPackages: {{printf "%q" .Covered}},
+       })
 {{end}}
        testing.Main(matchString, tests, benchmarks, examples)
 }
index 02544a7fc1b4728b0d13edc4d7f23034687f67c4..0509fcdfdf5cfa91cc93ecc83067825ab1c54483 100644 (file)
@@ -28,7 +28,7 @@ var usageMessage = `Usage of go test:
   -benchmem=false: print memory allocation statistics for benchmarks
   -benchtime=1s: passes -test.benchtime to test
   -cover=false: enable coverage analysis
-  -covermode="set": passes -test.covermode to test if -cover
+  -covermode="set": specifies mode for coverage analysis
   -coverpkg="": comma-separated list of packages for coverage analysis
   -coverprofile="": passes -test.coverprofile to test if -cover
   -cpu="": passes -test.cpu to test
@@ -115,6 +115,7 @@ var testFlagDefn = []*testFlagSpec{
 func testFlags(args []string) (packageNames, passToTest []string) {
        inPkg := false
        outputDir := ""
+       testCoverMode = "set"
        for i := 0; i < len(args); i++ {
                if !strings.HasPrefix(args[i], "-") {
                        if !inPkg && packageNames == nil {
@@ -208,12 +209,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
                        passToTest = append(passToTest, "-test."+f.name+"="+value)
                }
        }
-       if testCover {
-               if testCoverMode == "" {
-                       testCoverMode = "set"
-               }
-               passToTest = append(passToTest, "-test.covermode", testCoverMode)
-       }
+
        // Tell the test what directory we're running in, so it can write the profiles there.
        if testProfile && outputDir == "" {
                dir, err := os.Getwd()
index 22a5299b8f5b4160f6eb026b0e64ff17a94b7c2b..dd29364d87e56dbd4adc4551588dc96bc79fdc4e 100644 (file)
@@ -22,30 +22,23 @@ type CoverBlock struct {
        Stmts uint16
 }
 
-var (
-       coverCounters map[string][]uint32
-       coverBlocks   map[string][]CoverBlock
-)
-
-var (
-       testedPackage  string // The package being tested.
-       coveredPackage string // List of the package[s] being covered, if distinct from the tested package.
-)
+var cover Cover
 
-// RegisterCover records the coverage data accumulators for the tests.
+// Cover records information about test coverage checking.
 // NOTE: This struct is internal to the testing infrastructure and may change.
 // It is not covered (yet) by the Go 1 compatibility guidelines.
-func RegisterCover(c map[string][]uint32, b map[string][]CoverBlock) {
-       coverCounters = c
-       coverBlocks = b
+type Cover struct {
+       Mode            string
+       Counters        map[string][]uint32
+       Blocks          map[string][]CoverBlock
+       CoveredPackages string
 }
 
-// CoveredPackage records the names of the packages being tested and covered.
+// RegisterCover records the coverage data accumulators for the tests.
 // NOTE: This function is internal to the testing infrastructure and may change.
 // It is not covered (yet) by the Go 1 compatibility guidelines.
-func CoveredPackage(tested, covered string) {
-       testedPackage = tested
-       coveredPackage = covered
+func RegisterCover(c Cover) {
+       cover = c
 }
 
 // mustBeNil checks the error and, if present, reports it and exits.
@@ -63,13 +56,13 @@ func coverReport() {
        if *coverProfile != "" {
                f, err = os.Create(toOutputDir(*coverProfile))
                mustBeNil(err)
-               fmt.Fprintf(f, "mode: %s\n", *coverMode)
+               fmt.Fprintf(f, "mode: %s\n", cover.Mode)
                defer func() { mustBeNil(f.Close()) }()
        }
 
        var active, total int64
-       for name, counts := range coverCounters {
-               blocks := coverBlocks[name]
+       for name, counts := range cover.Counters {
+               blocks := cover.Blocks[name]
                for i, count := range counts {
                        stmts := int64(blocks[i].Stmts)
                        total += stmts
@@ -89,5 +82,5 @@ func coverReport() {
        if total == 0 {
                total = 1
        }
-       fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), coveredPackage)
+       fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
 }
index 8ef26ebfb394943f0ad758258f541518f2a2256c..330f3bdb8066611f7453027524e8a167473051f3 100644 (file)
@@ -122,8 +122,7 @@ var (
 
        // Report as tests are run; default is silent for success.
        chatty           = flag.Bool("test.v", false, "verbose: print additional output")
-       coverMode        = flag.String("test.covermode", "", "cover mode: set, count, atomic; default is none")
-       coverProfile     = flag.String("test.coverprofile", "", "write a coveraage profile to the named file after execution")
+       coverProfile     = flag.String("test.coverprofile", "", "write a coverage profile to the named file after execution")
        match            = flag.String("test.run", "", "regular expression to select tests and examples to run")
        memProfile       = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
        memProfileRate   = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
@@ -489,6 +488,10 @@ func before() {
        if *blockProfile != "" && *blockProfileRate >= 0 {
                runtime.SetBlockProfileRate(*blockProfileRate)
        }
+       if *coverProfile != "" && cover.Mode == "" {
+               fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
+               os.Exit(2)
+       }
 }
 
 // after runs after all testing.
@@ -520,7 +523,7 @@ func after() {
                }
                f.Close()
        }
-       if *coverMode != "" {
+       if cover.Mode != "" {
                coverReport()
        }
 }