]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cover: take default value of total only once.
authorDhananjay Nakrani <dhananjaynakrani@gmail.com>
Sun, 28 May 2017 16:09:07 +0000 (09:09 -0700)
committerIan Lance Taylor <iant@golang.org>
Fri, 2 Jun 2017 17:59:12 +0000 (17:59 +0000)
Defaulting total to 1 for each function, adds up to the
counting error. testing/cover.go already does this once.

Fixes #20515

Change-Id: I0e3f524c2ccb628eb9a8f0a1f81c22365c24cf9a
Reviewed-on: https://go-review.googlesource.com/44337
Run-TryBot: Dhananjay Nakrani <dhananjayn@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/cover/cover_test.go
src/cmd/cover/func.go
src/cmd/cover/testdata/p.go [new file with mode: 0644]
src/cmd/cover/testdata/profile.cov [new file with mode: 0644]
src/cmd/vet/all/whitelist/all.txt

index 81ac8ae467775d070370cb793d75b71f98f68042..1584a73b591787456ebfd469e7c07e5a0a044f25 100644 (file)
@@ -26,10 +26,11 @@ const (
 
 var (
        // Files we use.
-       testMain    = filepath.Join(testdata, "main.go")
-       testTest    = filepath.Join(testdata, "test.go")
-       coverInput  = filepath.Join(testdata, "test_line.go")
-       coverOutput = filepath.Join(testdata, "test_cover.go")
+       testMain     = filepath.Join(testdata, "main.go")
+       testTest     = filepath.Join(testdata, "test.go")
+       coverInput   = filepath.Join(testdata, "test_line.go")
+       coverOutput  = filepath.Join(testdata, "test_cover.go")
+       coverProfile = filepath.Join(testdata, "profile.cov")
 )
 
 var debug = false // Keeps the rewritten files around if set.
@@ -102,6 +103,25 @@ func TestCover(t *testing.T) {
        }
 }
 
+// Makes sure that `cover -func=profile.cov` reports accurate coverage.
+// Issue #20515.
+func TestCoverFunc(t *testing.T) {
+       // go tool cover -func ./testdata/profile.cov
+       cmd := exec.Command(testenv.GoToolPath(t), "tool", "cover", "-func", coverProfile)
+       out, err := cmd.Output()
+       if err != nil {
+               if ee, ok := err.(*exec.ExitError); ok {
+                       t.Logf("%s", ee.Stderr)
+               }
+               t.Fatal(err)
+       }
+
+       if got, err := regexp.Match(".*total:.*100.0.*", out); err != nil || !got {
+               t.Logf("%s", out)
+               t.Errorf("invalid coverage counts. got=(%v, %v); want=(true; nil)", got, err)
+       }
+}
+
 func run(c *exec.Cmd, t *testing.T) {
        c.Stdout = os.Stdout
        c.Stderr = os.Stderr
index 66ec242a402a9505822c143213bbd45b4b26bbb7..05c7c12c994636f4c00371c65a06ccea1c2abf79 100644 (file)
@@ -66,12 +66,12 @@ func funcOutput(profile, outputFile string) error {
                // Now match up functions and profile blocks.
                for _, f := range funcs {
                        c, t := f.coverage(profile)
-                       fmt.Fprintf(tabber, "%s:%d:\t%s\t%.1f%%\n", fn, f.startLine, f.name, 100.0*float64(c)/float64(t))
+                       fmt.Fprintf(tabber, "%s:%d:\t%s\t%.1f%%\n", fn, f.startLine, f.name, percent(c, t))
                        total += t
                        covered += c
                }
        }
-       fmt.Fprintf(tabber, "total:\t(statements)\t%.1f%%\n", 100.0*float64(covered)/float64(total))
+       fmt.Fprintf(tabber, "total:\t(statements)\t%.1f%%\n", percent(covered, total))
 
        return nil
 }
@@ -147,9 +147,6 @@ func (f *FuncExtent) coverage(profile *Profile) (num, den int64) {
                        covered += int64(b.NumStmt)
                }
        }
-       if total == 0 {
-               total = 1 // Avoid zero denominator.
-       }
        return covered, total
 }
 
@@ -162,3 +159,10 @@ func findFile(file string) (string, error) {
        }
        return filepath.Join(pkg.Dir, file), nil
 }
+
+func percent(covered, total int64) float64 {
+       if total == 0 {
+               total = 1 // Avoid zero denominator.
+       }
+       return 100.0 * float64(covered) / float64(total)
+}
diff --git a/src/cmd/cover/testdata/p.go b/src/cmd/cover/testdata/p.go
new file mode 100644 (file)
index 0000000..ce3a8c0
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2017 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.
+
+// A package such that there are 3 functions with zero total and covered lines.
+// And one with 1 total and covered lines. Reproduces issue #20515.
+package p
+
+//go:noinline
+func A() {
+
+}
+
+//go:noinline
+func B() {
+
+}
+
+//go:noinline
+func C() {
+
+}
+
+//go:noinline
+func D() int64 {
+       return 42
+}
diff --git a/src/cmd/cover/testdata/profile.cov b/src/cmd/cover/testdata/profile.cov
new file mode 100644 (file)
index 0000000..db08602
--- /dev/null
@@ -0,0 +1,5 @@
+mode: set
+./testdata/p.go:10.10,12.2 0 0
+./testdata/p.go:15.10,17.2 0 0
+./testdata/p.go:20.10,22.2 0 0
+./testdata/p.go:25.16,27.2 1 1
index 177aeaa3f6d1ac1edcd3881855dfd94e4c9a3705..c28035f8bb9ceed874c8168ddbafb00e599acf6b 100644 (file)
@@ -24,7 +24,6 @@ runtime/asm_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: I
 
 // Legitimate vet complaints in which we are testing for correct runtime behavior
 // in bad situations that vet can also detect statically.
-cmd/cover/testdata/test.go: unreachable code
 encoding/json/decode_test.go: struct field m has json tag but is not exported
 encoding/json/decode_test.go: struct field m2 has json tag but is not exported
 encoding/json/tagkey_test.go: struct field tag `:"BadFormat"` not compatible with reflect.StructTag.Get: bad syntax for struct tag key