|  | // Copyright 2013 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // Support for test coverage. | 
|  |  | 
|  | package testing | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "os" | 
|  | "sync/atomic" | 
|  | ) | 
|  |  | 
|  | // CoverBlock records the coverage data for a single basic block. | 
|  | // The fields are 1-indexed, as in an editor: The opening line of | 
|  | // the file is number 1, for example. Columns are measured | 
|  | // in bytes. | 
|  | // NOTE: This struct is internal to the testing infrastructure and may change. | 
|  | // It is not covered (yet) by the Go 1 compatibility guidelines. | 
|  | type CoverBlock struct { | 
|  | Line0 uint32 // Line number for block start. | 
|  | Col0  uint16 // Column number for block start. | 
|  | Line1 uint32 // Line number for block end. | 
|  | Col1  uint16 // Column number for block end. | 
|  | Stmts uint16 // Number of statements included in this block. | 
|  | } | 
|  |  | 
|  | var cover Cover | 
|  |  | 
|  | // Cover records information about test coverage checking. | 
|  | // NOTE: This struct is internal to the testing infrastructure and may change. | 
|  | // It is not covered (yet) by the Go 1 compatibility guidelines. | 
|  | type Cover struct { | 
|  | Mode            string | 
|  | Counters        map[string][]uint32 | 
|  | Blocks          map[string][]CoverBlock | 
|  | CoveredPackages string | 
|  | } | 
|  |  | 
|  | // Coverage reports the current code coverage as a fraction in the range [0, 1]. | 
|  | // If coverage is not enabled, Coverage returns 0. | 
|  | // | 
|  | // When running a large set of sequential test cases, checking Coverage after each one | 
|  | // can be useful for identifying which test cases exercise new code paths. | 
|  | // It is not a replacement for the reports generated by 'go test -cover' and | 
|  | // 'go tool cover'. | 
|  | func Coverage() float64 { | 
|  | var n, d int64 | 
|  | for _, counters := range cover.Counters { | 
|  | for i := range counters { | 
|  | if atomic.LoadUint32(&counters[i]) > 0 { | 
|  | n++ | 
|  | } | 
|  | d++ | 
|  | } | 
|  | } | 
|  | if d == 0 { | 
|  | return 0 | 
|  | } | 
|  | return float64(n) / float64(d) | 
|  | } | 
|  |  | 
|  | // RegisterCover records the coverage data accumulators for the tests. | 
|  | // NOTE: This function is internal to the testing infrastructure and may change. | 
|  | // It is not covered (yet) by the Go 1 compatibility guidelines. | 
|  | func RegisterCover(c Cover) { | 
|  | cover = c | 
|  | } | 
|  |  | 
|  | // mustBeNil checks the error and, if present, reports it and exits. | 
|  | func mustBeNil(err error) { | 
|  | if err != nil { | 
|  | fmt.Fprintf(os.Stderr, "testing: %s\n", err) | 
|  | os.Exit(2) | 
|  | } | 
|  | } | 
|  |  | 
|  | // coverReport reports the coverage percentage and writes a coverage profile if requested. | 
|  | func coverReport() { | 
|  | var f *os.File | 
|  | var err error | 
|  | if *coverProfile != "" { | 
|  | f, err = os.Create(toOutputDir(*coverProfile)) | 
|  | mustBeNil(err) | 
|  | fmt.Fprintf(f, "mode: %s\n", cover.Mode) | 
|  | defer func() { mustBeNil(f.Close()) }() | 
|  | } | 
|  |  | 
|  | var active, total int64 | 
|  | var count uint32 | 
|  | for name, counts := range cover.Counters { | 
|  | blocks := cover.Blocks[name] | 
|  | for i := range counts { | 
|  | stmts := int64(blocks[i].Stmts) | 
|  | total += stmts | 
|  | count = atomic.LoadUint32(&counts[i]) // For -mode=atomic. | 
|  | if count > 0 { | 
|  | active += stmts | 
|  | } | 
|  | if f != nil { | 
|  | _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n", name, | 
|  | blocks[i].Line0, blocks[i].Col0, | 
|  | blocks[i].Line1, blocks[i].Col1, | 
|  | stmts, | 
|  | count) | 
|  | mustBeNil(err) | 
|  | } | 
|  | } | 
|  | } | 
|  | if total == 0 { | 
|  | fmt.Println("coverage: [no statements]") | 
|  | return | 
|  | } | 
|  | fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages) | 
|  | } |