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 if goexperiment.CoverageRedesign {
51 return coverage2()
52 }
53 var n, d int64
54 for _, counters := range cover.Counters {
55 for i := range counters {
56 if atomic.LoadUint32(&counters[i]) > 0 {
57 n++
58 }
59 d++
60 }
61 }
62 if d == 0 {
63 return 0
64 }
65 return float64(n) / float64(d)
66 }
67
68
69
70
71 func RegisterCover(c Cover) {
72 cover = c
73 }
74
75
76 func mustBeNil(err error) {
77 if err != nil {
78 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
79 os.Exit(2)
80 }
81 }
82
83
84 func coverReport() {
85 if goexperiment.CoverageRedesign {
86 coverReport2()
87 return
88 }
89 var f *os.File
90 var err error
91 if *coverProfile != "" {
92 f, err = os.Create(toOutputDir(*coverProfile))
93 mustBeNil(err)
94 fmt.Fprintf(f, "mode: %s\n", cover.Mode)
95 defer func() { mustBeNil(f.Close()) }()
96 }
97
98 var active, total int64
99 var count uint32
100 for name, counts := range cover.Counters {
101 blocks := cover.Blocks[name]
102 for i := range counts {
103 stmts := int64(blocks[i].Stmts)
104 total += stmts
105 count = atomic.LoadUint32(&counts[i])
106 if count > 0 {
107 active += stmts
108 }
109 if f != nil {
110 _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n", name,
111 blocks[i].Line0, blocks[i].Col0,
112 blocks[i].Line1, blocks[i].Col1,
113 stmts,
114 count)
115 mustBeNil(err)
116 }
117 }
118 }
119 if total == 0 {
120 fmt.Println("coverage: [no statements]")
121 return
122 }
123 fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
124 }
125
View as plain text