// 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" ) // CoverBlock records the coverage data for a single basic block. // 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 Col0 uint16 Line1 uint32 Col1 uint16 Stmts uint16 } var ( coverCounters map[string][]uint32 coverBlocks map[string][]CoverBlock ) // RegisterCover records the coverage data accumulators for the tests. // NOTE: This struct is internal to the testing infrastructure and may change. // It is not covered (yet) by the Go 1 compatibility guidelines. func RegisterCover(c map[string][]uint32, b map[string][]CoverBlock) { coverCounters = c coverBlocks = b } // 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", *coverMode) defer func() { mustBeNil(f.Close()) }() } var active, total int64 packageName := "" for name, counts := range coverCounters { if packageName == "" { // Package name ends at last slash. for i, c := range name { if c == '/' { packageName = name[:i] } } } blocks := coverBlocks[name] for i, count := range counts { stmts := int64(blocks[i].Stmts) total += stmts 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 { total = 1 } if packageName == "" { packageName = "package" } fmt.Printf("test coverage for %s: %.1f%% of statements\n", packageName, 100*float64(active)/float64(total)) }