...
Run Format

Source file src/testing/cover.go

Documentation: testing

     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