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