]> Cypherpunks.ru repositories - gostls13.git/blob - src/testing/cover.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / testing / cover.go
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Support for test coverage.
6
7 package testing
8
9 import (
10         "fmt"
11         "internal/goexperiment"
12         "os"
13         "sync/atomic"
14 )
15
16 // CoverBlock records the coverage data for a single basic block.
17 // The fields are 1-indexed, as in an editor: The opening line of
18 // the file is number 1, for example. Columns are measured
19 // in bytes.
20 // NOTE: This struct is internal to the testing infrastructure and may change.
21 // It is not covered (yet) by the Go 1 compatibility guidelines.
22 type CoverBlock struct {
23         Line0 uint32 // Line number for block start.
24         Col0  uint16 // Column number for block start.
25         Line1 uint32 // Line number for block end.
26         Col1  uint16 // Column number for block end.
27         Stmts uint16 // Number of statements included in this block.
28 }
29
30 var cover Cover
31
32 // Cover records information about test coverage checking.
33 // NOTE: This struct is internal to the testing infrastructure and may change.
34 // It is not covered (yet) by the Go 1 compatibility guidelines.
35 type Cover struct {
36         Mode            string
37         Counters        map[string][]uint32
38         Blocks          map[string][]CoverBlock
39         CoveredPackages string
40 }
41
42 // Coverage reports the current code coverage as a fraction in the range [0, 1].
43 // If coverage is not enabled, Coverage returns 0.
44 //
45 // When running a large set of sequential test cases, checking Coverage after each one
46 // can be useful for identifying which test cases exercise new code paths.
47 // It is not a replacement for the reports generated by 'go test -cover' and
48 // 'go tool cover'.
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 // RegisterCover records the coverage data accumulators for the tests.
69 // NOTE: This function is internal to the testing infrastructure and may change.
70 // It is not covered (yet) by the Go 1 compatibility guidelines.
71 func RegisterCover(c Cover) {
72         cover = c
73 }
74
75 // mustBeNil checks the error and, if present, reports it and exits.
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 // coverReport reports the coverage percentage and writes a coverage profile if requested.
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]) // For -mode=atomic.
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 }