github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/testing/cover.go (about) 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 "os" 12 "sync/atomic" 13 ) 14 15 // CoverBlock records the coverage data for a single basic block. 16 // The fields are 1-indexed, as in an editor: The opening line of 17 // the file is number 1, for example. Columns are measured 18 // in bytes. 19 // NOTE: This struct is internal to the testing infrastructure and may change. 20 // It is not covered (yet) by the Go 1 compatibility guidelines. 21 type CoverBlock struct { 22 Line0 uint32 // Line number for block start. 23 Col0 uint16 // Column number for block start. 24 Line1 uint32 // Line number for block end. 25 Col1 uint16 // Column number for block end. 26 Stmts uint16 // Number of statements included in this block. 27 } 28 29 var cover Cover 30 31 // Cover records information about test coverage checking. 32 // NOTE: This struct is internal to the testing infrastructure and may change. 33 // It is not covered (yet) by the Go 1 compatibility guidelines. 34 type Cover struct { 35 Mode string 36 Counters map[string][]uint32 37 Blocks map[string][]CoverBlock 38 CoveredPackages string 39 } 40 41 // Coverage reports the current code coverage as a fraction in the range [0, 1]. 42 // If coverage is not enabled, Coverage returns 0. 43 // 44 // When running a large set of sequential test cases, checking Coverage after each one 45 // can be useful for identifying which test cases exercise new code paths. 46 // It is not a replacement for the reports generated by 'go test -cover' and 47 // 'go tool cover'. 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 // RegisterCover records the coverage data accumulators for the tests. 65 // NOTE: This function is internal to the testing infrastructure and may change. 66 // It is not covered (yet) by the Go 1 compatibility guidelines. 67 func RegisterCover(c Cover) { 68 cover = c 69 } 70 71 // mustBeNil checks the error and, if present, reports it and exits. 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 // coverReport reports the coverage percentage and writes a coverage profile if requested. 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]) // For -mode=atomic. 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 }