summaryrefslogtreecommitdiffstats
path: root/src/cmd/cover/testdata
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/cover/testdata')
-rw-r--r--src/cmd/cover/testdata/directives.go40
-rw-r--r--src/cmd/cover/testdata/html/html.go30
-rw-r--r--src/cmd/cover/testdata/html/html.golden18
-rw-r--r--src/cmd/cover/testdata/html/html_test.go8
-rw-r--r--src/cmd/cover/testdata/main.go116
-rw-r--r--src/cmd/cover/testdata/p.go27
-rw-r--r--src/cmd/cover/testdata/profile.cov5
-rw-r--r--src/cmd/cover/testdata/test.go300
-rw-r--r--src/cmd/cover/testdata/toolexec.go33
9 files changed, 577 insertions, 0 deletions
diff --git a/src/cmd/cover/testdata/directives.go b/src/cmd/cover/testdata/directives.go
new file mode 100644
index 0000000..dfb7b8e
--- /dev/null
+++ b/src/cmd/cover/testdata/directives.go
@@ -0,0 +1,40 @@
+// 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.
+
+// This file is processed by the cover command, then a test verifies that
+// all compiler directives are preserved and positioned appropriately.
+
+//go:a
+
+//go:b
+package main
+
+//go:c1
+
+//go:c2
+//doc
+func c() {
+}
+
+//go:d1
+
+//doc
+//go:d2
+type d int
+
+//go:e1
+
+//doc
+//go:e2
+type (
+ e int
+ f int
+)
+
+//go:_empty1
+//doc
+//go:_empty2
+type ()
+
+//go:f
diff --git a/src/cmd/cover/testdata/html/html.go b/src/cmd/cover/testdata/html/html.go
new file mode 100644
index 0000000..2057825
--- /dev/null
+++ b/src/cmd/cover/testdata/html/html.go
@@ -0,0 +1,30 @@
+package html
+
+import "fmt"
+
+// This file is tested by html_test.go.
+// The comments below are markers for extracting the annotated source
+// from the HTML output.
+
+// This is a regression test for incorrect sorting of boundaries
+// that coincide, specifically for empty select clauses.
+// START f
+func f() {
+ ch := make(chan int)
+ select {
+ case <-ch:
+ default:
+ }
+}
+
+// END f
+
+// https://golang.org/issue/25767
+// START g
+func g() {
+ if false {
+ fmt.Printf("Hello")
+ }
+}
+
+// END g
diff --git a/src/cmd/cover/testdata/html/html.golden b/src/cmd/cover/testdata/html/html.golden
new file mode 100644
index 0000000..84377d1
--- /dev/null
+++ b/src/cmd/cover/testdata/html/html.golden
@@ -0,0 +1,18 @@
+// START f
+func f() <span class="cov8" title="1">{
+ ch := make(chan int)
+ select </span>{
+ case &lt;-ch:<span class="cov0" title="0"></span>
+ default:<span class="cov8" title="1"></span>
+ }
+}
+
+// END f
+// START g
+func g() <span class="cov8" title="1">{
+ if false </span><span class="cov0" title="0">{
+ fmt.Printf("Hello")
+ }</span>
+}
+
+// END g
diff --git a/src/cmd/cover/testdata/html/html_test.go b/src/cmd/cover/testdata/html/html_test.go
new file mode 100644
index 0000000..c15561f
--- /dev/null
+++ b/src/cmd/cover/testdata/html/html_test.go
@@ -0,0 +1,8 @@
+package html
+
+import "testing"
+
+func TestAll(t *testing.T) {
+ f()
+ g()
+}
diff --git a/src/cmd/cover/testdata/main.go b/src/cmd/cover/testdata/main.go
new file mode 100644
index 0000000..be74b4a
--- /dev/null
+++ b/src/cmd/cover/testdata/main.go
@@ -0,0 +1,116 @@
+// 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.
+
+// Test runner for coverage test. This file is not coverage-annotated; test.go is.
+// It knows the coverage counter is called
+// "thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest".
+
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func main() {
+ testAll()
+ verify()
+}
+
+type block struct {
+ count uint32
+ line uint32
+}
+
+var counters = make(map[block]bool)
+
+// shorthand for the long counter variable.
+var coverTest = &thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest
+
+// check records the location and expected value for a counter.
+func check(line, count uint32) {
+ b := block{
+ count,
+ line,
+ }
+ counters[b] = true
+}
+
+// checkVal is a version of check that returns its extra argument,
+// so it can be used in conditionals.
+func checkVal(line, count uint32, val int) int {
+ b := block{
+ count,
+ line,
+ }
+ counters[b] = true
+ return val
+}
+
+var PASS = true
+
+// verify checks the expected counts against the actual. It runs after the test has completed.
+func verify() {
+ for b := range counters {
+ got, index := count(b.line)
+ if b.count == anything && got != 0 {
+ got = anything
+ }
+ if got != b.count {
+ fmt.Fprintf(os.Stderr, "test_go:%d expected count %d got %d [counter %d]\n", b.line, b.count, got, index)
+ PASS = false
+ }
+ }
+ verifyPanic()
+ if !PASS {
+ fmt.Fprintf(os.Stderr, "FAIL\n")
+ os.Exit(2)
+ }
+}
+
+// verifyPanic is a special check for the known counter that should be
+// after the panic call in testPanic.
+func verifyPanic() {
+ if coverTest.Count[panicIndex-1] != 1 {
+ // Sanity check for test before panic.
+ fmt.Fprintf(os.Stderr, "bad before panic")
+ PASS = false
+ }
+ if coverTest.Count[panicIndex] != 0 {
+ fmt.Fprintf(os.Stderr, "bad at panic: %d should be 0\n", coverTest.Count[panicIndex])
+ PASS = false
+ }
+ if coverTest.Count[panicIndex+1] != 1 {
+ fmt.Fprintf(os.Stderr, "bad after panic")
+ PASS = false
+ }
+}
+
+// count returns the count and index for the counter at the specified line.
+func count(line uint32) (uint32, int) {
+ // Linear search is fine. Choose perfect fit over approximate.
+ // We can have a closing brace for a range on the same line as a condition for an "else if"
+ // and we don't want that brace to steal the count for the condition on the "if".
+ // Therefore we test for a perfect (lo==line && hi==line) match, but if we can't
+ // find that we take the first imperfect match.
+ index := -1
+ indexLo := uint32(1e9)
+ for i := range coverTest.Count {
+ lo, hi := coverTest.Pos[3*i], coverTest.Pos[3*i+1]
+ if lo == line && line == hi {
+ return coverTest.Count[i], i
+ }
+ // Choose the earliest match (the counters are in unpredictable order).
+ if lo <= line && line <= hi && indexLo > lo {
+ index = i
+ indexLo = lo
+ }
+ }
+ if index == -1 {
+ fmt.Fprintln(os.Stderr, "cover_test: no counter for line", line)
+ PASS = false
+ return 0, 0
+ }
+ return coverTest.Count[index], index
+}
diff --git a/src/cmd/cover/testdata/p.go b/src/cmd/cover/testdata/p.go
new file mode 100644
index 0000000..ce3a8c0
--- /dev/null
+++ b/src/cmd/cover/testdata/p.go
@@ -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
index 0000000..db08602
--- /dev/null
+++ b/src/cmd/cover/testdata/profile.cov
@@ -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
diff --git a/src/cmd/cover/testdata/test.go b/src/cmd/cover/testdata/test.go
new file mode 100644
index 0000000..0e1dbc6
--- /dev/null
+++ b/src/cmd/cover/testdata/test.go
@@ -0,0 +1,300 @@
+// 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.
+
+// This program is processed by the cover command, and then testAll is called.
+// The test driver in main.go can then compare the coverage statistics with expectation.
+
+// The word LINE is replaced by the line number in this file. When the file is executed,
+// the coverage processing has changed the line numbers, so we can't use runtime.Caller.
+
+package main
+
+import _ "unsafe" // for go:linkname
+
+//go:linkname some_name some_name
+var some_name int
+
+const anything = 1e9 // Just some unlikely value that means "we got here, don't care how often"
+
+func testAll() {
+ testSimple()
+ testBlockRun()
+ testIf()
+ testFor()
+ testRange()
+ testSwitch()
+ testTypeSwitch()
+ testSelect1()
+ testSelect2()
+ testPanic()
+ testEmptySwitches()
+ testFunctionLiteral()
+ testGoto()
+}
+
+// The indexes of the counters in testPanic are known to main.go
+const panicIndex = 3
+
+// This test appears first because the index of its counters is known to main.go
+func testPanic() {
+ defer func() {
+ recover()
+ }()
+ check(LINE, 1)
+ panic("should not get next line")
+ check(LINE, 0) // this is GoCover.Count[panicIndex]
+ // The next counter is in testSimple and it will be non-zero.
+ // If the panic above does not trigger a counter, the test will fail
+ // because GoCover.Count[panicIndex] will be the one in testSimple.
+}
+
+func testSimple() {
+ check(LINE, 1)
+}
+
+func testIf() {
+ if true {
+ check(LINE, 1)
+ } else {
+ check(LINE, 0)
+ }
+ if false {
+ check(LINE, 0)
+ } else {
+ check(LINE, 1)
+ }
+ for i := 0; i < 3; i++ {
+ if checkVal(LINE, 3, i) <= 2 {
+ check(LINE, 3)
+ }
+ if checkVal(LINE, 3, i) <= 1 {
+ check(LINE, 2)
+ }
+ if checkVal(LINE, 3, i) <= 0 {
+ check(LINE, 1)
+ }
+ }
+ for i := 0; i < 3; i++ {
+ if checkVal(LINE, 3, i) <= 1 {
+ check(LINE, 2)
+ } else {
+ check(LINE, 1)
+ }
+ }
+ for i := 0; i < 3; i++ {
+ if checkVal(LINE, 3, i) <= 0 {
+ check(LINE, 1)
+ } else if checkVal(LINE, 2, i) <= 1 {
+ check(LINE, 1)
+ } else if checkVal(LINE, 1, i) <= 2 {
+ check(LINE, 1)
+ } else if checkVal(LINE, 0, i) <= 3 {
+ check(LINE, 0)
+ }
+ }
+ if func(a, b int) bool { return a < b }(3, 4) {
+ check(LINE, 1)
+ }
+}
+
+func testFor() {
+ for i := 0; i < 10; func() { i++; check(LINE, 10) }() {
+ check(LINE, 10)
+ }
+}
+
+func testRange() {
+ for _, f := range []func(){
+ func() { check(LINE, 1) },
+ } {
+ f()
+ check(LINE, 1)
+ }
+}
+
+func testBlockRun() {
+ check(LINE, 1)
+ {
+ check(LINE, 1)
+ }
+ {
+ check(LINE, 1)
+ }
+ check(LINE, 1)
+ {
+ check(LINE, 1)
+ }
+ {
+ check(LINE, 1)
+ }
+ check(LINE, 1)
+}
+
+func testSwitch() {
+ for i := 0; i < 5; func() { i++; check(LINE, 5) }() {
+ goto label2
+ label1:
+ goto label1
+ label2:
+ switch i {
+ case 0:
+ check(LINE, 1)
+ case 1:
+ check(LINE, 1)
+ case 2:
+ check(LINE, 1)
+ default:
+ check(LINE, 2)
+ }
+ }
+}
+
+func testTypeSwitch() {
+ var x = []any{1, 2.0, "hi"}
+ for _, v := range x {
+ switch func() { check(LINE, 3) }(); v.(type) {
+ case int:
+ check(LINE, 1)
+ case float64:
+ check(LINE, 1)
+ case string:
+ check(LINE, 1)
+ case complex128:
+ check(LINE, 0)
+ default:
+ check(LINE, 0)
+ }
+ }
+}
+
+func testSelect1() {
+ c := make(chan int)
+ go func() {
+ for i := 0; i < 1000; i++ {
+ c <- i
+ }
+ }()
+ for {
+ select {
+ case <-c:
+ check(LINE, anything)
+ case <-c:
+ check(LINE, anything)
+ default:
+ check(LINE, 1)
+ return
+ }
+ }
+}
+
+func testSelect2() {
+ c1 := make(chan int, 1000)
+ c2 := make(chan int, 1000)
+ for i := 0; i < 1000; i++ {
+ c1 <- i
+ c2 <- i
+ }
+ for {
+ select {
+ case <-c1:
+ check(LINE, 1000)
+ case <-c2:
+ check(LINE, 1000)
+ default:
+ check(LINE, 1)
+ return
+ }
+ }
+}
+
+// Empty control statements created syntax errors. This function
+// is here just to be sure that those are handled correctly now.
+func testEmptySwitches() {
+ check(LINE, 1)
+ switch 3 {
+ }
+ check(LINE, 1)
+ switch i := (any)(3).(int); i {
+ }
+ check(LINE, 1)
+ c := make(chan int)
+ go func() {
+ check(LINE, 1)
+ c <- 1
+ select {}
+ }()
+ <-c
+ check(LINE, 1)
+}
+
+func testFunctionLiteral() {
+ a := func(f func()) error {
+ f()
+ f()
+ return nil
+ }
+
+ b := func(f func()) bool {
+ f()
+ f()
+ return true
+ }
+
+ check(LINE, 1)
+ a(func() {
+ check(LINE, 2)
+ })
+
+ if err := a(func() {
+ check(LINE, 2)
+ }); err != nil {
+ }
+
+ switch b(func() {
+ check(LINE, 2)
+ }) {
+ }
+
+ x := 2
+ switch x {
+ case func() int { check(LINE, 1); return 1 }():
+ check(LINE, 0)
+ panic("2=1")
+ case func() int { check(LINE, 1); return 2 }():
+ check(LINE, 1)
+ case func() int { check(LINE, 0); return 3 }():
+ check(LINE, 0)
+ panic("2=3")
+ }
+}
+
+func testGoto() {
+ for i := 0; i < 2; i++ {
+ if i == 0 {
+ goto Label
+ }
+ check(LINE, 1)
+ Label:
+ check(LINE, 2)
+ }
+ // Now test that we don't inject empty statements
+ // between a label and a loop.
+loop:
+ for {
+ check(LINE, 1)
+ break loop
+ }
+}
+
+// This comment didn't appear in generated go code.
+func haha() {
+ // Needed for cover to add counter increment here.
+ _ = 42
+}
+
+// Some someFunction.
+//
+//go:nosplit
+func someFunction() {
+}
diff --git a/src/cmd/cover/testdata/toolexec.go b/src/cmd/cover/testdata/toolexec.go
new file mode 100644
index 0000000..458adae
--- /dev/null
+++ b/src/cmd/cover/testdata/toolexec.go
@@ -0,0 +1,33 @@
+// Copyright 2018 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.
+
+// The toolexec program is a helper program for cmd/cover tests.
+// It is used so that the go tool will call the newly built version
+// of the cover program, rather than the installed one.
+//
+// The tests arrange to run the go tool with the argument
+// -toolexec="/path/to/toolexec /path/to/testcover"
+// The go tool will invoke this program (compiled into /path/to/toolexec)
+// with the arguments shown above followed by the command to run.
+// This program will check whether it is expected to run the cover
+// program, and if so replace it with /path/to/testcover.
+package main
+
+import (
+ exec "internal/execabs"
+ "os"
+ "strings"
+)
+
+func main() {
+ if strings.HasSuffix(strings.TrimSuffix(os.Args[2], ".exe"), "cover") {
+ os.Args[2] = os.Args[1]
+ }
+ cmd := exec.Command(os.Args[2], os.Args[3:]...)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ os.Exit(1)
+ }
+}