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