diff options
Diffstat (limited to 'src/cmd/cover/testdata')
-rw-r--r-- | src/cmd/cover/testdata/directives.go | 40 | ||||
-rw-r--r-- | src/cmd/cover/testdata/html/html.go | 30 | ||||
-rw-r--r-- | src/cmd/cover/testdata/html/html.golden | 18 | ||||
-rw-r--r-- | src/cmd/cover/testdata/html/html_test.go | 8 | ||||
-rw-r--r-- | src/cmd/cover/testdata/main.go | 116 | ||||
-rw-r--r-- | src/cmd/cover/testdata/p.go | 27 | ||||
-rw-r--r-- | src/cmd/cover/testdata/profile.cov | 5 | ||||
-rw-r--r-- | src/cmd/cover/testdata/test.go | 299 | ||||
-rw-r--r-- | src/cmd/cover/testdata/toolexec.go | 33 |
9 files changed, 576 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 <-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..b794962 --- /dev/null +++ b/src/cmd/cover/testdata/test.go @@ -0,0 +1,299 @@ +// 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 + +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 = []interface{}{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 := (interface{})(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..386de79 --- /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 ( + "os" + exec "internal/execabs" + "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) + } +} |