Source file
src/testing/cover.go
1
2
3
4
5
6
7 package testing
8
9 import (
10 "fmt"
11 "internal/goexperiment"
12 "os"
13 "sync/atomic"
14 )
15
16
17
18
19
20
21
22 type CoverBlock struct {
23 Line0 uint32
24 Col0 uint16
25 Line1 uint32
26 Col1 uint16
27 Stmts uint16
28 }
29
30 var cover Cover
31
32
33
34
35 type Cover struct {
36 Mode string
37 Counters map[string][]uint32
38 Blocks map[string][]CoverBlock
39 CoveredPackages string
40 }
41
42
43
44
45
46
47
48
49 func Coverage() float64 {
50 var n, d int64
51 for _, counters := range cover.Counters {
52 for i := range counters {
53 if atomic.LoadUint32(&counters[i]) > 0 {
54 n++
55 }
56 d++
57 }
58 }
59 if d == 0 {
60 return 0
61 }
62 return float64(n) / float64(d)
63 }
64
65
66
67
68 func RegisterCover(c Cover) {
69 cover = c
70 }
71
72
73 func mustBeNil(err error) {
74 if err != nil {
75 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
76 os.Exit(2)
77 }
78 }
79
80
81 func coverReport() {
82 if goexperiment.CoverageRedesign {
83 coverReport2()
84 return
85 }
86 var f *os.File
87 var err error
88 if *coverProfile != "" {
89 f, err = os.Create(toOutputDir(*coverProfile))
90 mustBeNil(err)
91 fmt.Fprintf(f, "mode: %s\n", cover.Mode)
92 defer func() { mustBeNil(f.Close()) }()
93 }
94
95 var active, total int64
96 var count uint32
97 for name, counts := range cover.Counters {
98 blocks := cover.Blocks[name]
99 for i := range counts {
100 stmts := int64(blocks[i].Stmts)
101 total += stmts
102 count = atomic.LoadUint32(&counts[i])
103 if count > 0 {
104 active += stmts
105 }
106 if f != nil {
107 _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n", name,
108 blocks[i].Line0, blocks[i].Col0,
109 blocks[i].Line1, blocks[i].Col1,
110 stmts,
111 count)
112 mustBeNil(err)
113 }
114 }
115 }
116 if total == 0 {
117 fmt.Println("coverage: [no statements]")
118 return
119 }
120 fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
121 }
122
View as plain text