LEFT | RIGHT |
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Support for test coverage. | 5 // Support for test coverage. |
6 | 6 |
7 package testing | 7 package testing |
8 | 8 |
9 import ( | 9 import ( |
10 "fmt" | 10 "fmt" |
11 "os" | 11 "os" |
12 ) | 12 ) |
13 | 13 |
14 // CoverBlock records the coverage data for a single basic block. | 14 // CoverBlock records the coverage data for a single basic block. |
15 // NOTE: This struct is internal to the testing infrastructure and may change. | 15 // NOTE: This struct is internal to the testing infrastructure and may change. |
16 // It is not covered (yet) by the Go 1 compatibility guidelines. | 16 // It is not covered (yet) by the Go 1 compatibility guidelines. |
17 type CoverBlock struct { | 17 type CoverBlock struct { |
18 Line0 uint32 | 18 Line0 uint32 |
19 Col0 uint16 | 19 Col0 uint16 |
20 Line1 uint32 | 20 Line1 uint32 |
21 Col1 uint16 | 21 Col1 uint16 |
22 Stmts uint16 | 22 Stmts uint16 |
23 } | 23 } |
24 | 24 |
25 var ( | 25 var ( |
26 coverCounters map[string][]uint32 | 26 coverCounters map[string][]uint32 |
27 coverBlocks map[string][]CoverBlock | 27 coverBlocks map[string][]CoverBlock |
28 ) | 28 ) |
29 | 29 |
30 // CoverRegisters records the coverage data accumulators for the tests. | 30 // RegisterCover records the coverage data accumulators for the tests. |
31 // NOTE: This struct is internal to the testing infrastructure and may change. | 31 // NOTE: This struct is internal to the testing infrastructure and may change. |
32 // It is not covered (yet) by the Go 1 compatibility guidelines. | 32 // It is not covered (yet) by the Go 1 compatibility guidelines. |
33 func CoverRegister(c map[string][]uint32, b map[string][]CoverBlock) { | 33 func RegisterCover(c map[string][]uint32, b map[string][]CoverBlock) { |
34 coverCounters = c | 34 coverCounters = c |
35 coverBlocks = b | 35 coverBlocks = b |
| 36 } |
| 37 |
| 38 // mustBeNil checks the error and, if present, reports it and exits. |
| 39 func mustBeNil(err error) { |
| 40 if err != nil { |
| 41 fmt.Fprintf(os.Stderr, "testing: %s\n", err) |
| 42 os.Exit(2) |
| 43 } |
36 } | 44 } |
37 | 45 |
38 // coverReport reports the coverage percentage and writes a coverage profile if
requested. | 46 // coverReport reports the coverage percentage and writes a coverage profile if
requested. |
39 func coverReport() { | 47 func coverReport() { |
40 var f *os.File | 48 var f *os.File |
41 var err error | 49 var err error |
42 if *coverProfile != "" { | 50 if *coverProfile != "" { |
43 f, err = os.Create(toOutputDir(*coverProfile)) | 51 f, err = os.Create(toOutputDir(*coverProfile)) |
44 » » if err != nil { | 52 » » mustBeNil(err) |
45 » » » fmt.Fprintf(os.Stderr, "testing: %s\n", err) | 53 » » defer func() { mustBeNil(f.Close()) }() |
46 » » » os.Exit(2) | |
47 » » } | |
48 » » defer func() { | |
49 » » » // adg made me do this. | |
50 » » » err := f.Close() | |
51 » » » if err != nil { | |
52 » » » » fmt.Fprintf(os.Stderr, "testing: %s\n", err) | |
53 » » » » os.Exit(2) | |
54 » » » } | |
55 » » }() | |
56 } | 54 } |
57 | 55 |
58 var active, total int64 | 56 var active, total int64 |
59 packageName := "" | 57 packageName := "" |
60 for name, counts := range coverCounters { | 58 for name, counts := range coverCounters { |
61 if packageName == "" { | 59 if packageName == "" { |
62 // Package name ends at last slash. | 60 // Package name ends at last slash. |
63 for i, c := range name { | 61 for i, c := range name { |
64 if c == '/' { | 62 if c == '/' { |
65 packageName = name[:i] | 63 packageName = name[:i] |
66 } | 64 } |
67 } | 65 } |
68 } | 66 } |
69 blocks := coverBlocks[name] | 67 blocks := coverBlocks[name] |
70 for i, count := range counts { | 68 for i, count := range counts { |
71 stmts := int64(blocks[i].Stmts) | 69 stmts := int64(blocks[i].Stmts) |
72 total += stmts | 70 total += stmts |
73 if count > 0 { | 71 if count > 0 { |
74 active += stmts | 72 active += stmts |
75 } | 73 } |
76 if f != nil { | 74 if f != nil { |
77 _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n
", name, | 75 _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n
", name, |
78 blocks[i].Line0, blocks[i].Col0, | 76 blocks[i].Line0, blocks[i].Col0, |
79 blocks[i].Line1, blocks[i].Col1, | 77 blocks[i].Line1, blocks[i].Col1, |
80 stmts, | 78 stmts, |
81 count) | 79 count) |
82 » » » » if err != nil { | 80 » » » » mustBeNil(err) |
83 » » » » » fmt.Fprintf(os.Stderr, "testing: %s\n",
err) | |
84 » » » » » os.Exit(2) | |
85 » » » » } | |
86 } | 81 } |
87 } | 82 } |
88 } | 83 } |
89 if total == 0 { | 84 if total == 0 { |
90 total = 1 | 85 total = 1 |
91 } | 86 } |
92 if packageName == "" { | 87 if packageName == "" { |
93 packageName = "package" | 88 packageName = "package" |
94 } | 89 } |
95 fmt.Printf("test coverage for %s: %.1f%% of statements\n", packageName,
100*float64(active)/float64(total)) | 90 fmt.Printf("test coverage for %s: %.1f%% of statements\n", packageName,
100*float64(active)/float64(total)) |
96 } | 91 } |
LEFT | RIGHT |