func runtime_coverage_processCoverTestDir(dir string, cfile string, cmode string, cpkgs string) error
//go:linkname testing_registerCover2 testing.registerCover2
-func testing_registerCover2(mode string, tearDown func(coverprofile string, gocoverdir string) (string, error))
+func testing_registerCover2(mode string, tearDown func(coverprofile string, gocoverdir string) (string, error), snapcov func() float64)
//go:linkname runtime_coverage_markProfileEmitted runtime/coverage.markProfileEmitted
func runtime_coverage_markProfileEmitted(val bool)
+//go:linkname runtime_coverage_snapshot runtime/coverage.snapshot
+func runtime_coverage_snapshot() float64
+
func coverTearDown(coverprofile string, gocoverdir string) (string, error) {
var err error
if gocoverdir == "" {
func main() {
{{if .Cover}}
- testing_registerCover2({{printf "%q" .Cover.Mode}}, coverTearDown)
+ testing_registerCover2({{printf "%q" .Cover.Mode}}, coverTearDown, runtime_coverage_snapshot)
{{end}}
m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
{{with .TestMain}}
--- /dev/null
+
+# Rudimentary test of testing.Coverage().
+
+[short] skip
+[!GOEXPERIMENT:coverageredesign] skip
+
+# Simple test.
+go test -v -cover -count=1
+
+# Make sure test still passes when test executable is built and
+# run outside the go command.
+go test -c -o t.exe -cover
+exec ./t.exe
+
+-- go.mod --
+module hello
+
+go 1.20
+-- hello.go --
+package hello
+
+func Hello() {
+ println("hello")
+}
+
+// contents not especially interesting, just need some code
+func foo(n int) int {
+ t := 0
+ for i := 0; i < n; i++ {
+ for j := 0; j < i; j++ {
+ t += i ^ j
+ if t == 1010101 {
+ break
+ }
+ }
+ }
+ return t
+}
+
+-- hello_test.go --
+package hello
+
+import "testing"
+
+func TestTestCoverage(t *testing.T) {
+ Hello()
+ C1 := testing.Coverage()
+ foo(29)
+ C2 := testing.Coverage()
+ if C1 == 0.0 || C2 == 0.0 {
+ t.Errorf("unexpected zero values C1=%f C2=%f", C1, C2)
+ }
+ if C1 >= C2 {
+ t.Errorf("testing.Coverage() not monotonically increasing C1=%f C2=%f", C1, C2)
+ }
+}
+
// It is not a replacement for the reports generated by 'go test -cover' and
// 'go tool cover'.
func Coverage() float64 {
+ if goexperiment.CoverageRedesign {
+ return coverage2()
+ }
var n, d int64
for _, counters := range cover.Counters {
for i := range counters {
// cover2 variable stores the current coverage mode and a
// tear-down function to be called at the end of the testing run.
var cover2 struct {
- mode string
- tearDown func(coverprofile string, gocoverdir string) (string, error)
+ mode string
+ tearDown func(coverprofile string, gocoverdir string) (string, error)
+ snapshotcov func() float64
}
// registerCover2 is invoked during "go test -cover" runs by the test harness
// code in _testmain.go; it is used to record a 'tear down' function
// (to be called when the test is complete) and the coverage mode.
-func registerCover2(mode string, tearDown func(coverprofile string, gocoverdir string) (string, error)) {
+func registerCover2(mode string, tearDown func(coverprofile string, gocoverdir string) (string, error), snapcov func() float64) {
cover2.mode = mode
cover2.tearDown = tearDown
+ cover2.snapshotcov = snapcov
}
// coverReport2 invokes a callback in _testmain.go that will
func testGoCoverDir() string {
return *gocoverdir
}
+
+// coverage2 returns a rough "coverage percentage so far"
+// number to support the testing.Coverage() function.
+func coverage2() float64 {
+ if cover2.mode == "" {
+ return 0.0
+ }
+ return cover2.snapshotcov()
+}