cmd/go: write coverage to file, add percentage statistic
Move the data dumper to the testing package, where it has access
to file I/O.
Print a percentage value at the end of the run.
R=rsc, adg
CC=golang-dev
https://golang.org/cl/10264045
diff --git a/src/pkg/testing/cover.go b/src/pkg/testing/cover.go
new file mode 100644
index 0000000..2419870
--- /dev/null
+++ b/src/pkg/testing/cover.go
@@ -0,0 +1,91 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Support for test coverage.
+
+package testing
+
+import (
+ "fmt"
+ "os"
+)
+
+// CoverBlock records the coverage data for a single basic block.
+// NOTE: This struct is internal to the testing infrastructure and may change.
+// It is not covered (yet) by the Go 1 compatibility guidelines.
+type CoverBlock struct {
+ Line0 uint32
+ Col0 uint16
+ Line1 uint32
+ Col1 uint16
+ Stmts uint16
+}
+
+var (
+ coverCounters map[string][]uint32
+ coverBlocks map[string][]CoverBlock
+)
+
+// RegisterCover records the coverage data accumulators for the tests.
+// 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
+}
+
+// mustBeNil checks the error and, if present, reports it and exits.
+func mustBeNil(err error) {
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+ os.Exit(2)
+ }
+}
+
+// coverReport reports the coverage percentage and writes a coverage profile if requested.
+func coverReport() {
+ var f *os.File
+ var err error
+ if *coverProfile != "" {
+ f, err = os.Create(toOutputDir(*coverProfile))
+ mustBeNil(err)
+ defer func() { mustBeNil(f.Close()) }()
+ }
+
+ var active, total int64
+ packageName := ""
+ for name, counts := range coverCounters {
+ if packageName == "" {
+ // Package name ends at last slash.
+ for i, c := range name {
+ if c == '/' {
+ packageName = name[:i]
+ }
+ }
+ }
+ blocks := coverBlocks[name]
+ for i, count := range counts {
+ stmts := int64(blocks[i].Stmts)
+ total += stmts
+ if count > 0 {
+ active += stmts
+ }
+ if f != nil {
+ _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n", name,
+ blocks[i].Line0, blocks[i].Col0,
+ blocks[i].Line1, blocks[i].Col1,
+ stmts,
+ count)
+ mustBeNil(err)
+ }
+ }
+ }
+ if total == 0 {
+ total = 1
+ }
+ if packageName == "" {
+ packageName = "package"
+ }
+ fmt.Printf("test coverage for %s: %.1f%% of statements\n", packageName, 100*float64(active)/float64(total))
+}