liyujie
2025-08-28 d9927380ed7c8366f762049be9f3fee225860833
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 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.
 
// Support for test coverage.
 
package testing
 
import (
   "fmt"
   "os"
   "sync/atomic"
)
 
// CoverBlock records the coverage data for a single basic block.
// The fields are 1-indexed, as in an editor: The opening line of
// the file is number 1, for example. Columns are measured
// in bytes.
// NOTE: This struct is internal to the testing infrastructure and may change.
// It is not covered (yet) by the Go 1 compatibility guidelines.
type CoverBlock struct {
   Line0 uint32 // Line number for block start.
   Col0  uint16 // Column number for block start.
   Line1 uint32 // Line number for block end.
   Col1  uint16 // Column number for block end.
   Stmts uint16 // Number of statements included in this block.
}
 
var cover Cover
 
// Cover records information about test coverage checking.
// NOTE: This struct is internal to the testing infrastructure and may change.
// It is not covered (yet) by the Go 1 compatibility guidelines.
type Cover struct {
   Mode            string
   Counters        map[string][]uint32
   Blocks          map[string][]CoverBlock
   CoveredPackages string
}
 
// Coverage reports the current code coverage as a fraction in the range [0, 1].
// If coverage is not enabled, Coverage returns 0.
//
// When running a large set of sequential test cases, checking Coverage after each one
// can be useful for identifying which test cases exercise new code paths.
// It is not a replacement for the reports generated by 'go test -cover' and
// 'go tool cover'.
func Coverage() float64 {
   var n, d int64
   for _, counters := range cover.Counters {
       for i := range counters {
           if atomic.LoadUint32(&counters[i]) > 0 {
               n++
           }
           d++
       }
   }
   if d == 0 {
       return 0
   }
   return float64(n) / float64(d)
}
 
// RegisterCover records the coverage data accumulators for the tests.
// NOTE: This function is internal to the testing infrastructure and may change.
// It is not covered (yet) by the Go 1 compatibility guidelines.
func RegisterCover(c Cover) {
   cover = c
}
 
// mustBeNil checks the error and, if present, reports it and exits.
func mustBeNil(err error) {
   if err != nil {
       fmt.Fprintf(os.Stderr, "testing: %s\n", err)
       os.Exit(2)
   }
}
 
// coverReport reports the coverage percentage and writes a coverage profile if requested.
func coverReport() {
   var f *os.File
   var err error
   if *coverProfile != "" {
       f, err = os.Create(toOutputDir(*coverProfile))
       mustBeNil(err)
       fmt.Fprintf(f, "mode: %s\n", cover.Mode)
       defer func() { mustBeNil(f.Close()) }()
   }
 
   var active, total int64
   var count uint32
   for name, counts := range cover.Counters {
       blocks := cover.Blocks[name]
       for i := range counts {
           stmts := int64(blocks[i].Stmts)
           total += stmts
           count = atomic.LoadUint32(&counts[i]) // For -mode=atomic.
           if count > 0 {
               active += stmts
           }
           if f != nil {
               _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n", name,
                   blocks[i].Line0, blocks[i].Col0,
                   blocks[i].Line1, blocks[i].Col1,
                   stmts,
                   count)
               mustBeNil(err)
           }
       }
   }
   if total == 0 {
       total = 1
   }
   fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
}