...
Run Format

Source file src/testing/cover.go

     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	// NOTE: This struct is internal to the testing infrastructure and may change.
    17	// It is not covered (yet) by the Go 1 compatibility guidelines.
    18	type CoverBlock struct {
    19		Line0 uint32
    20		Col0  uint16
    21		Line1 uint32
    22		Col1  uint16
    23		Stmts uint16
    24	}
    25	
    26	var cover Cover
    27	
    28	// Cover records information about test coverage checking.
    29	// NOTE: This struct is internal to the testing infrastructure and may change.
    30	// It is not covered (yet) by the Go 1 compatibility guidelines.
    31	type Cover struct {
    32		Mode            string
    33		Counters        map[string][]uint32
    34		Blocks          map[string][]CoverBlock
    35		CoveredPackages string
    36	}
    37	
    38	// 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'.
    45	func Coverage() float64 {
    46		var n, d int64
    47		for _, counters := range cover.Counters {
    48			for i := range counters {
    49				if atomic.LoadUint32(&counters[i]) > 0 {
    50					n++
    51				}
    52				d++
    53			}
    54		}
    55		if d == 0 {
    56			return 0
    57		}
    58		return float64(n) / float64(d)
    59	}
    60	
    61	// RegisterCover records the coverage data accumulators for the tests.
    62	// NOTE: This function is internal to the testing infrastructure and may change.
    63	// It is not covered (yet) by the Go 1 compatibility guidelines.
    64	func RegisterCover(c Cover) {
    65		cover = c
    66	}
    67	
    68	// mustBeNil checks the error and, if present, reports it and exits.
    69	func 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.
    77	func coverReport() {
    78		var f *os.File
    79		var err error
    80		if *coverProfile != "" {
    81			f, err = os.Create(toOutputDir(*coverProfile))
    82			mustBeNil(err)
    83			fmt.Fprintf(f, "mode: %s\n", cover.Mode)
    84			defer func() { mustBeNil(f.Close()) }()
    85		}
    86	
    87		var active, total int64
    88		var count uint32
    89		for name, counts := range cover.Counters {
    90			blocks := cover.Blocks[name]
    91			for i := range counts {
    92				stmts := int64(blocks[i].Stmts)
    93				total += stmts
    94				count = atomic.LoadUint32(&counts[i]) // For -mode=atomic.
    95				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		}
   111		fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
   112	}
   113	

View as plain text