aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/coverage/testsupport.go
diff options
context:
space:
mode:
authorThan McIntosh <thanm@google.com>2023-05-12 08:20:08 -0400
committerThan McIntosh <thanm@google.com>2023-05-23 11:37:04 +0000
commitef67022471bb26973168827ebf41e09f839fa0a7 (patch)
tree1998bd5dfee920b3cf1d371fd59eacab700eadb3 /src/runtime/coverage/testsupport.go
parent380529d5c371ac036c757a155453f618465ee8d3 (diff)
downloadgo-ef67022471bb26973168827ebf41e09f839fa0a7.tar.xz
runtime/coverage: add coverage snapshot helper routine
Add a new function runtime/coverage.snapshot(), which samples the current values of coverage counters in a running "go test -cover" binary and returns percentage of statements executed so far. This function is intended to be used by the function testing.Coverage(). Updates #59590. Change-Id: I861393701c0cef47b4980aec14331168a9e64e8e Reviewed-on: https://go-review.googlesource.com/c/go/+/495449 Run-TryBot: Than McIntosh <thanm@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/runtime/coverage/testsupport.go')
-rw-r--r--src/runtime/coverage/testsupport.go47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/runtime/coverage/testsupport.go b/src/runtime/coverage/testsupport.go
index 2b9e58b5f6..332b39b76e 100644
--- a/src/runtime/coverage/testsupport.go
+++ b/src/runtime/coverage/testsupport.go
@@ -15,7 +15,9 @@ import (
"internal/coverage/pods"
"io"
"os"
+ "runtime/internal/atomic"
"strings"
+ "unsafe"
)
// processCoverTestDir is called (via a linknamed reference) from
@@ -232,3 +234,48 @@ func (ts *tstate) processPod(p pods.Pod) error {
type pkfunc struct {
pk, fcn uint32
}
+
+// snapshot returns a snapshot of coverage percentage at a moment of
+// time within a running test, so as to support the testing.Coverage()
+// function. This version doesn't examine coverage meta-data, so the
+// result it returns will be less accurate (more "slop") due to the
+// fact that we don't look at the meta data to see how many statements
+// are associated with each counter.
+func snapshot() float64 {
+ cl := getCovCounterList()
+ if len(cl) == 0 {
+ // no work to do here.
+ return 0.0
+ }
+
+ tot := uint64(0)
+ totExec := uint64(0)
+ for _, c := range cl {
+ sd := unsafe.Slice((*atomic.Uint32)(unsafe.Pointer(c.Counters)), c.Len)
+ tot += uint64(len(sd))
+ for i := 0; i < len(sd); i++ {
+ // Skip ahead until the next non-zero value.
+ if sd[i].Load() == 0 {
+ continue
+ }
+ // We found a function that was executed.
+ nCtrs := sd[i+coverage.NumCtrsOffset].Load()
+ cst := i + coverage.FirstCtrOffset
+
+ if cst+int(nCtrs) > len(sd) {
+ break
+ }
+ counters := sd[cst : cst+int(nCtrs)]
+ for i := range counters {
+ if counters[i].Load() != 0 {
+ totExec++
+ }
+ }
+ i += coverage.FirstCtrOffset + int(nCtrs) - 1
+ }
+ }
+ if tot == 0 {
+ return 0.0
+ }
+ return float64(totExec) / float64(tot)
+}