blob: a4ce37f7c2dfb8130685ec489ff7608d0fe691f8 [file] [log] [blame]
Rob Pike8e8b8b82013-06-18 14:18:25 -07001// 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
7package testing
8
9import (
10 "fmt"
11 "os"
Rob Piked33ee0c2014-09-09 12:31:07 -070012 "sync/atomic"
Rob Pike8e8b8b82013-06-18 14:18:25 -070013)
14
15// CoverBlock records the coverage data for a single basic block.
16// NOTE: This struct is internal to the testing infrastructure and may change.
17// It is not covered (yet) by the Go 1 compatibility guidelines.
18type CoverBlock struct {
19 Line0 uint32
20 Col0 uint16
21 Line1 uint32
22 Col1 uint16
23 Stmts uint16
24}
25
Russ Coxccc45532013-07-12 20:40:30 -040026var cover Cover
Rob Pike8e8b8b82013-06-18 14:18:25 -070027
Russ Coxccc45532013-07-12 20:40:30 -040028// Cover records information about test coverage checking.
Rob Pike8e8b8b82013-06-18 14:18:25 -070029// NOTE: This struct is internal to the testing infrastructure and may change.
30// It is not covered (yet) by the Go 1 compatibility guidelines.
Russ Coxccc45532013-07-12 20:40:30 -040031type Cover struct {
32 Mode string
33 Counters map[string][]uint32
34 Blocks map[string][]CoverBlock
35 CoveredPackages string
Rob Pike8e8b8b82013-06-18 14:18:25 -070036}
37
Russ Coxd2d71872014-07-22 22:56:35 -040038// Coverage reports the current code coverage as a fraction in the range [0, 1].
39// If coverage is not enabled, Coverage returns 0.
40//
41// When running a large set of sequential test cases, checking Coverage after each one
42// can be useful for identifying which test cases exercise new code paths.
43// It is not a replacement for the reports generated by 'go test -cover' and
44// 'go tool cover'.
45func Coverage() float64 {
46 var n, d int64
47 for _, counters := range cover.Counters {
Rob Piked33ee0c2014-09-09 12:31:07 -070048 for i := range counters {
49 if atomic.LoadUint32(&counters[i]) > 0 {
Russ Coxd2d71872014-07-22 22:56:35 -040050 n++
51 }
52 d++
53 }
54 }
55 if d == 0 {
56 return 0
57 }
58 return float64(n) / float64(d)
59}
60
Russ Coxccc45532013-07-12 20:40:30 -040061// RegisterCover records the coverage data accumulators for the tests.
Rob Pike6d86c142013-07-10 09:52:36 +100062// NOTE: This function is internal to the testing infrastructure and may change.
63// It is not covered (yet) by the Go 1 compatibility guidelines.
Russ Coxccc45532013-07-12 20:40:30 -040064func RegisterCover(c Cover) {
65 cover = c
Rob Pike6d86c142013-07-10 09:52:36 +100066}
67
Rob Pike8e8b8b82013-06-18 14:18:25 -070068// mustBeNil checks the error and, if present, reports it and exits.
69func mustBeNil(err error) {
70 if err != nil {
71 fmt.Fprintf(os.Stderr, "testing: %s\n", err)
72 os.Exit(2)
73 }
74}
75
76// coverReport reports the coverage percentage and writes a coverage profile if requested.
77func coverReport() {
78 var f *os.File
79 var err error
80 if *coverProfile != "" {
81 f, err = os.Create(toOutputDir(*coverProfile))
82 mustBeNil(err)
Russ Coxccc45532013-07-12 20:40:30 -040083 fmt.Fprintf(f, "mode: %s\n", cover.Mode)
Rob Pike8e8b8b82013-06-18 14:18:25 -070084 defer func() { mustBeNil(f.Close()) }()
85 }
86
87 var active, total int64
Rob Piked33ee0c2014-09-09 12:31:07 -070088 var count uint32
Russ Coxccc45532013-07-12 20:40:30 -040089 for name, counts := range cover.Counters {
90 blocks := cover.Blocks[name]
Rob Piked33ee0c2014-09-09 12:31:07 -070091 for i := range counts {
Rob Pike8e8b8b82013-06-18 14:18:25 -070092 stmts := int64(blocks[i].Stmts)
93 total += stmts
Rob Piked33ee0c2014-09-09 12:31:07 -070094 count = atomic.LoadUint32(&counts[i]) // For -mode=atomic.
Rob Pike8e8b8b82013-06-18 14:18:25 -070095 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 }
Russ Coxccc45532013-07-12 20:40:30 -0400111 fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
Rob Pike8e8b8b82013-06-18 14:18:25 -0700112}