cover.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. // Support for test coverage.
  5. package testing
  6. import (
  7. "fmt"
  8. "os"
  9. "sync/atomic"
  10. )
  11. // CoverBlock records the coverage data for a single basic block.
  12. // NOTE: This struct is internal to the testing infrastructure and may change.
  13. // It is not covered (yet) by the Go 1 compatibility guidelines.
  14. type CoverBlock struct {
  15. Line0 uint32
  16. Col0 uint16
  17. Line1 uint32
  18. Col1 uint16
  19. Stmts uint16
  20. }
  21. var cover Cover
  22. // Cover records information about test coverage checking.
  23. // NOTE: This struct is internal to the testing infrastructure and may change.
  24. // It is not covered (yet) by the Go 1 compatibility guidelines.
  25. type Cover struct {
  26. Mode string
  27. Counters map[string][]uint32
  28. Blocks map[string][]CoverBlock
  29. CoveredPackages string
  30. }
  31. // Coverage reports the current code coverage as a fraction in the range [0, 1].
  32. // If coverage is not enabled, Coverage returns 0.
  33. //
  34. // When running a large set of sequential test cases, checking Coverage after each one
  35. // can be useful for identifying which test cases exercise new code paths.
  36. // It is not a replacement for the reports generated by 'go test -cover' and
  37. // 'go tool cover'.
  38. func Coverage() float64 {
  39. var n, d int64
  40. for _, counters := range cover.Counters {
  41. for i := range counters {
  42. if atomic.LoadUint32(&counters[i]) > 0 {
  43. n++
  44. }
  45. d++
  46. }
  47. }
  48. if d == 0 {
  49. return 0
  50. }
  51. return float64(n) / float64(d)
  52. }
  53. // RegisterCover records the coverage data accumulators for the tests.
  54. // NOTE: This function is internal to the testing infrastructure and may change.
  55. // It is not covered (yet) by the Go 1 compatibility guidelines.
  56. func RegisterCover(c Cover) {
  57. cover = c
  58. }
  59. // mustBeNil checks the error and, if present, reports it and exits.
  60. func mustBeNil(err error) {
  61. if err != nil {
  62. fmt.Fprintf(os.Stderr, "testing: %s\n", err)
  63. os.Exit(2)
  64. }
  65. }
  66. // coverReport reports the coverage percentage and writes a coverage profile if requested.
  67. func coverReport() {
  68. var f *os.File
  69. var err error
  70. if *coverProfile != "" {
  71. f, err = os.Create(toOutputDir(*coverProfile))
  72. mustBeNil(err)
  73. fmt.Fprintf(f, "mode: %s\n", cover.Mode)
  74. defer func() { mustBeNil(f.Close()) }()
  75. }
  76. var active, total int64
  77. var count uint32
  78. for name, counts := range cover.Counters {
  79. blocks := cover.Blocks[name]
  80. for i := range counts {
  81. stmts := int64(blocks[i].Stmts)
  82. total += stmts
  83. count = atomic.LoadUint32(&counts[i]) // For -mode=atomic.
  84. if count > 0 {
  85. active += stmts
  86. }
  87. if f != nil {
  88. _, err := fmt.Fprintf(f, "%s:%d.%d,%d.%d %d %d\n", name,
  89. blocks[i].Line0, blocks[i].Col0,
  90. blocks[i].Line1, blocks[i].Col1,
  91. stmts,
  92. count)
  93. mustBeNil(err)
  94. }
  95. }
  96. }
  97. if total == 0 {
  98. total = 1
  99. }
  100. fmt.Printf("coverage: %.1f%% of statements%s\n", 100*float64(active)/float64(total), cover.CoveredPackages)
  101. }