summaryrefslogtreecommitdiff
path: root/libgo/go/testing
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2017-01-14 00:05:42 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2017-01-14 00:05:42 +0000
commitc2047754c300b68c05d65faa8dc2925fe67b71b4 (patch)
treee183ae81a1f48a02945cb6de463a70c5be1b06f6 /libgo/go/testing
parent829afb8f05602bb31c9c597b24df7377fed4f059 (diff)
libgo: update to Go 1.8 release candidate 1
Compiler changes: * Change map assignment to use mapassign and assign value directly. * Change string iteration to use decoderune, faster for ASCII strings. * Change makeslice to take int, and use makeslice64 for larger values. * Add new noverflow field to hmap struct used for maps. Unresolved problems, to be fixed later: * Commented out test in go/types/sizes_test.go that doesn't compile. * Commented out reflect.TestStructOf test for padding after zero-sized field. Reviewed-on: https://go-review.googlesource.com/35231 gotools/: Updates for Go 1.8rc1. * Makefile.am (go_cmd_go_files): Add bug.go. (s-zdefaultcc): Write defaultPkgConfig. * Makefile.in: Rebuild. From-SVN: r244456
Diffstat (limited to 'libgo/go/testing')
-rw-r--r--libgo/go/testing/benchmark.go22
-rw-r--r--libgo/go/testing/example.go10
-rw-r--r--libgo/go/testing/internal/testdeps/deps.go51
-rw-r--r--libgo/go/testing/quick/quick.go2
-rw-r--r--libgo/go/testing/sub_test.go4
-rw-r--r--libgo/go/testing/testing.go250
6 files changed, 250 insertions, 89 deletions
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 5d58b85e78a..c033ce5fecb 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -7,6 +7,7 @@ package testing
import (
"flag"
"fmt"
+ "internal/race"
"os"
"runtime"
"sync"
@@ -14,8 +15,8 @@ import (
"time"
)
-var matchBenchmarks = flag.String("test.bench", "", "regular expression per path component to select benchmarks to run")
-var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
+var matchBenchmarks = flag.String("test.bench", "", "run only benchmarks matching `regexp`")
+var benchTime = flag.Duration("test.benchtime", 1*time.Second, "run each benchmark for duration `d`")
var benchmarkMemory = flag.Bool("test.benchmem", false, "print memory allocations for benchmarks")
// Global lock to ensure only one benchmark runs at a time.
@@ -56,7 +57,6 @@ type B struct {
missingBytes bool // one of the subbenchmarks does not have bytes set.
timerOn bool
showAllocResult bool
- hasSub bool
result BenchmarkResult
parallelism int // RunParallel creates parallelism*GOMAXPROCS goroutines
// The initial states of memStats.Mallocs and memStats.TotalAlloc.
@@ -132,6 +132,7 @@ func (b *B) runN(n int) {
// Try to get a comparable environment for each run
// by clearing garbage from previous runs.
runtime.GC()
+ b.raceErrors = -race.Errors()
b.N = n
b.parallelism = 1
b.ResetTimer()
@@ -140,6 +141,10 @@ func (b *B) runN(n int) {
b.StopTimer()
b.previousN = n
b.previousDuration = b.duration
+ b.raceErrors += race.Errors()
+ if b.raceErrors > 0 {
+ b.Errorf("race detected during execution of benchmark")
+ }
}
func min(x, y int) int {
@@ -263,10 +268,9 @@ func (b *B) launch() {
for n := 1; !b.failed && b.duration < d && n < 1e9; {
last := n
// Predict required iterations.
- if b.nsPerOp() == 0 {
- n = 1e9
- } else {
- n = int(d.Nanoseconds() / b.nsPerOp())
+ n = int(d.Nanoseconds())
+ if nsop := b.nsPerOp(); nsop != 0 {
+ n /= int(nsop)
}
// Run more iterations than we think we'll need (1.2x).
// Don't grow too fast in case we had timing errors previously.
@@ -359,10 +363,10 @@ type benchContext struct {
// An internal function but exported because it is cross-package; part of the implementation
// of the "go test" command.
func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
- runBenchmarksInternal(matchString, benchmarks)
+ runBenchmarks(matchString, benchmarks)
}
-func runBenchmarksInternal(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) bool {
+func runBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) bool {
// If no flag was specified, don't run benchmarks.
if len(*matchBenchmarks) == 0 {
return true
diff --git a/libgo/go/testing/example.go b/libgo/go/testing/example.go
index fd8343f3bfc..e5bce7af4e7 100644
--- a/libgo/go/testing/example.go
+++ b/libgo/go/testing/example.go
@@ -21,7 +21,14 @@ type InternalExample struct {
Unordered bool
}
+// An internal function but exported because it is cross-package; part of the implementation
+// of the "go test" command.
func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool) {
+ _, ok = runExamples(matchString, examples)
+ return ok
+}
+
+func runExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ran, ok bool) {
ok = true
var eg InternalExample
@@ -35,12 +42,13 @@ func RunExamples(matchString func(pat, str string) (bool, error), examples []Int
if !matched {
continue
}
+ ran = true
if !runExample(eg) {
ok = false
}
}
- return
+ return ran, ok
}
func sortLines(output string) string {
diff --git a/libgo/go/testing/internal/testdeps/deps.go b/libgo/go/testing/internal/testdeps/deps.go
new file mode 100644
index 00000000000..b08300b5d60
--- /dev/null
+++ b/libgo/go/testing/internal/testdeps/deps.go
@@ -0,0 +1,51 @@
+// Copyright 2016 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.
+
+// Package testdeps provides access to dependencies needed by test execution.
+//
+// This package is imported by the generated main package, which passes
+// TestDeps into testing.Main. This allows tests to use packages at run time
+// without making those packages direct dependencies of package testing.
+// Direct dependencies of package testing are harder to write tests for.
+package testdeps
+
+import (
+ "io"
+ "regexp"
+ "runtime/pprof"
+)
+
+// TestDeps is an implementation of the testing.testDeps interface,
+// suitable for passing to testing.MainStart.
+type TestDeps struct{}
+
+var matchPat string
+var matchRe *regexp.Regexp
+
+func (TestDeps) MatchString(pat, str string) (result bool, err error) {
+ if matchRe == nil || matchPat != pat {
+ matchPat = pat
+ matchRe, err = regexp.Compile(matchPat)
+ if err != nil {
+ return
+ }
+ }
+ return matchRe.MatchString(str), nil
+}
+
+func (TestDeps) StartCPUProfile(w io.Writer) error {
+ return pprof.StartCPUProfile(w)
+}
+
+func (TestDeps) StopCPUProfile() {
+ pprof.StopCPUProfile()
+}
+
+func (TestDeps) WriteHeapProfile(w io.Writer) error {
+ return pprof.WriteHeapProfile(w)
+}
+
+func (TestDeps) WriteProfileTo(name string, w io.Writer, debug int) error {
+ return pprof.Lookup(name).WriteTo(w, debug)
+}
diff --git a/libgo/go/testing/quick/quick.go b/libgo/go/testing/quick/quick.go
index 798d41aa7d1..95860fda0fb 100644
--- a/libgo/go/testing/quick/quick.go
+++ b/libgo/go/testing/quick/quick.go
@@ -3,6 +3,8 @@
// license that can be found in the LICENSE file.
// Package quick implements utility functions to help with black box testing.
+//
+// The testing/quick package is frozen and is not accepting new features.
package quick
import (
diff --git a/libgo/go/testing/sub_test.go b/libgo/go/testing/sub_test.go
index 2a24aaacfd7..8d5d9206f03 100644
--- a/libgo/go/testing/sub_test.go
+++ b/libgo/go/testing/sub_test.go
@@ -357,7 +357,7 @@ func TestTRun(t *T) {
want := strings.TrimSpace(tc.output)
re := makeRegexp(want)
if ok, err := regexp.MatchString(re, got); !ok || err != nil {
- t.Errorf("%s:ouput:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
+ t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
}
}
}
@@ -498,7 +498,7 @@ func TestBRun(t *T) {
want := strings.TrimSpace(tc.output)
re := makeRegexp(want)
if ok, err := regexp.MatchString(re, got); !ok || err != nil {
- t.Errorf("%s:ouput:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
+ t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
}
}
}
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index 5a3a9aba218..8364c8e4144 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -137,13 +137,17 @@
// of the top-level test and the sequence of names passed to Run, separated by
// slashes, with an optional trailing sequence number for disambiguation.
//
-// The argument to the -run and -bench command-line flags is a slash-separated
-// list of regular expressions that match each name element in turn.
-// For example:
+// The argument to the -run and -bench command-line flags is an unanchored regular
+// expression that matches the test's name. For tests with multiple slash-separated
+// elements, such as subtests, the argument is itself slash-separated, with
+// expressions matching each name element in turn. Because it is unanchored, an
+// empty expression matches any string.
+// For example, using "matching" to mean "whose name contains":
//
-// go test -run Foo # Run top-level tests matching "Foo".
-// go test -run Foo/A= # Run subtests of Foo matching "A=".
-// go test -run /A=1 # Run all subtests of a top-level test matching "A=1".
+// go test -run '' # Run all tests.
+// go test -run Foo # Run top-level tests matching "Foo", such as "TestFooBar".
+// go test -run Foo/A= # For top-level tests matching "Foo", run subtests matching "A=".
+// go test -run /A=1 # For all top-level tests, run subtests matching "A=1".
//
// Subtests can also be used to control parallelism. A parent test will only
// complete once all of its subtests complete. In this example, all tests are
@@ -192,7 +196,7 @@
// A simple implementation of TestMain is:
//
// func TestMain(m *testing.M) {
-// flag.Parse()
+// // call flag.Parse() here if TestMain uses flags
// os.Exit(m.Run())
// }
//
@@ -200,13 +204,15 @@ package testing
import (
"bytes"
+ "errors"
"flag"
"fmt"
+ "internal/race"
"io"
"os"
"runtime"
"runtime/debug"
- "runtime/pprof"
+ "runtime/trace"
"strconv"
"strings"
"sync"
@@ -225,22 +231,24 @@ var (
// "go test", the binary always runs in the source directory for the package;
// this flag lets "go test" tell the binary to write the files in the directory where
// the "go test" command is run.
- outputDir = flag.String("test.outputdir", "", "directory in which to write profiles")
+ outputDir = flag.String("test.outputdir", "", "write profiles to `dir`")
// Report as tests are run; default is silent for success.
- chatty = flag.Bool("test.v", false, "verbose: print additional output")
- count = flag.Uint("test.count", 1, "run tests and benchmarks `n` times")
- coverProfile = flag.String("test.coverprofile", "", "write a coverage profile to the named file after execution")
- match = flag.String("test.run", "", "regular expression to select tests and examples to run")
- memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
- memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
- cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
- blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to the named file after execution")
- blockProfileRate = flag.Int("test.blockprofilerate", 1, "if >= 0, calls runtime.SetBlockProfileRate()")
- traceFile = flag.String("test.trace", "", "write an execution trace to the named file after execution")
- timeout = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
- cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
- parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+ chatty = flag.Bool("test.v", false, "verbose: print additional output")
+ count = flag.Uint("test.count", 1, "run tests and benchmarks `n` times")
+ coverProfile = flag.String("test.coverprofile", "", "write a coverage profile to `file`")
+ match = flag.String("test.run", "", "run only tests and examples matching `regexp`")
+ memProfile = flag.String("test.memprofile", "", "write a memory profile to `file`")
+ memProfileRate = flag.Int("test.memprofilerate", 0, "set memory profiling `rate` (see runtime.MemProfileRate)")
+ cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to `file`")
+ blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to `file`")
+ blockProfileRate = flag.Int("test.blockprofilerate", 1, "set blocking profile `rate` (see runtime.SetBlockProfileRate)")
+ mutexProfile = flag.String("test.mutexprofile", "", "write a mutex contention profile to the named file after execution")
+ mutexProfileFraction = flag.Int("test.mutexprofilefraction", 1, "if >= 0, calls runtime.SetMutexProfileFraction()")
+ traceFile = flag.String("test.trace", "", "write an execution trace to `file`")
+ timeout = flag.Duration("test.timeout", 0, "fail test binary execution after duration `d` (0 means unlimited)")
+ cpuListStr = flag.String("test.cpu", "", "comma-separated `list` of cpu counts to run each test with")
+ parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "run at most `n` tests in parallel")
haveExamples bool // are there examples?
@@ -250,14 +258,17 @@ var (
// common holds the elements common between T and B and
// captures common methods such as Errorf.
type common struct {
- mu sync.RWMutex // guards output, failed, and done.
- output []byte // Output generated by test or benchmark.
- w io.Writer // For flushToParent.
- chatty bool // A copy of the chatty flag.
- failed bool // Test or benchmark has failed.
- skipped bool // Test of benchmark has been skipped.
- finished bool // Test function has completed.
- done bool // Test is finished and all subtests have completed.
+ mu sync.RWMutex // guards output, failed, and done.
+ output []byte // Output generated by test or benchmark.
+ w io.Writer // For flushToParent.
+ chatty bool // A copy of the chatty flag.
+ ran bool // Test or benchmark (or one of its subtests) was executed.
+ failed bool // Test or benchmark has failed.
+ skipped bool // Test of benchmark has been skipped.
+ finished bool // Test function has completed.
+ done bool // Test is finished and all subtests have completed.
+ hasSub bool
+ raceErrors int // number of races detected during test
parent *common
level int // Nesting depth of test or benchmark.
@@ -274,6 +285,13 @@ func Short() bool {
return *short
}
+// CoverMode reports what the test coverage mode is set to. The
+// values are "set", "count", or "atomic". The return value will be
+// empty if test coverage is not enabled.
+func CoverMode() string {
+ return cover.Mode
+}
+
// Verbose reports whether the -test.v flag is set.
func Verbose() bool {
return *chatty
@@ -367,6 +385,7 @@ type TB interface {
Fatalf(format string, args ...interface{})
Log(args ...interface{})
Logf(format string, args ...interface{})
+ Name() string
Skip(args ...interface{})
SkipNow()
Skipf(format string, args ...interface{})
@@ -399,6 +418,20 @@ type T struct {
func (c *common) private() {}
+// Name returns the name of the running test or benchmark.
+func (c *common) Name() string {
+ return c.name
+}
+
+func (c *common) setRan() {
+ if c.parent != nil {
+ c.parent.setRan()
+ }
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ c.ran = true
+}
+
// Fail marks the function as having failed but continues execution.
func (c *common) Fail() {
if c.parent != nil {
@@ -465,10 +498,11 @@ func (c *common) log(s string) {
// printed to avoid having performance depend on the value of the -test.v flag.
func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
-// Logf formats its arguments according to the format, analogous to Printf,
-// and records the text in the error log. For tests, the text will be printed only if
-// the test fails or the -test.v flag is set. For benchmarks, the text is always
-// printed to avoid having performance depend on the value of the -test.v flag.
+// Logf formats its arguments according to the format, analogous to Printf, and
+// records the text in the error log. A final newline is added if not provided. For
+// tests, the text will be printed only if the test fails or the -test.v flag is
+// set. For benchmarks, the text is always printed to avoid having performance
+// depend on the value of the -test.v flag.
func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
// Error is equivalent to Log followed by Fail.
@@ -508,6 +542,8 @@ func (c *common) Skipf(format string, args ...interface{}) {
}
// SkipNow marks the test as having been skipped and stops its execution.
+// If a test fails (see Error, Errorf, Fail) and is then skipped,
+// it is still considered to have failed.
// Execution will continue at the next test or benchmark. See also FailNow.
// SkipNow must be called from the goroutine running the test, not from
// other goroutines created during the test. Calling SkipNow does not stop
@@ -546,11 +582,13 @@ func (t *T) Parallel() {
// Add to the list of tests to be released by the parent.
t.parent.sub = append(t.parent.sub, t)
+ t.raceErrors += race.Errors()
t.signal <- true // Release calling test.
<-t.parent.barrier // Wait for the parent test to complete.
t.context.waitParallel()
t.start = time.Now()
+ t.raceErrors += -race.Errors()
}
// An internal type but exported because it is cross-package; part of the implementation
@@ -566,6 +604,11 @@ func tRunner(t *T, fn func(t *T)) {
// a call to runtime.Goexit, record the duration and send
// a signal saying that the test is done.
defer func() {
+ t.raceErrors += race.Errors()
+ if t.raceErrors > 0 {
+ t.Errorf("race detected during execution of test")
+ }
+
t.duration += time.Now().Sub(t.start)
// If the test panicked, print any test output before dying.
err := recover()
@@ -602,10 +645,14 @@ func tRunner(t *T, fn func(t *T)) {
// Do not lock t.done to allow race detector to detect race in case
// the user does not appropriately synchronizes a goroutine.
t.done = true
+ if t.parent != nil && !t.hasSub {
+ t.setRan()
+ }
t.signal <- true
}()
t.start = time.Now()
+ t.raceErrors = -race.Errors()
fn(t)
t.finished = true
}
@@ -613,6 +660,7 @@ func tRunner(t *T, fn func(t *T)) {
// Run runs f as a subtest of t called name. It reports whether f succeeded.
// Run will block until all its parallel subtests have completed.
func (t *T) Run(name string, f func(t *T)) bool {
+ t.hasSub = true
testName, ok := t.context.match.fullName(&t.common, name)
if !ok {
return true
@@ -701,29 +749,57 @@ func (c *testContext) release() {
c.startParallel <- true // Pick a waiting test to be run.
}
-// An internal function but exported because it is cross-package; part of the implementation
-// of the "go test" command.
+// No one should be using func Main anymore.
+// See the doc comment on func Main and use MainStart instead.
+var errMain = errors.New("testing: unexpected use of func Main")
+
+type matchStringOnly func(pat, str string) (bool, error)
+
+func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) }
+func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain }
+func (f matchStringOnly) StopCPUProfile() {}
+func (f matchStringOnly) WriteHeapProfile(w io.Writer) error { return errMain }
+func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain }
+
+// Main is an internal function, part of the implementation of the "go test" command.
+// It was exported because it is cross-package and predates "internal" packages.
+// It is no longer used by "go test" but preserved, as much as possible, for other
+// systems that simulate "go test" using Main, but Main sometimes cannot be updated as
+// new functionality is added to the testing package.
+// Systems simulating "go test" should be updated to use MainStart.
func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
- os.Exit(MainStart(matchString, tests, benchmarks, examples).Run())
+ os.Exit(MainStart(matchStringOnly(matchString), tests, benchmarks, examples).Run())
}
// M is a type passed to a TestMain function to run the actual tests.
type M struct {
- matchString func(pat, str string) (bool, error)
- tests []InternalTest
- benchmarks []InternalBenchmark
- examples []InternalExample
+ deps testDeps
+ tests []InternalTest
+ benchmarks []InternalBenchmark
+ examples []InternalExample
+}
+
+// testDeps is an internal interface of functionality that is
+// passed into this package by a test's generated main package.
+// The canonical implementation of this interface is
+// testing/internal/testdeps's TestDeps.
+type testDeps interface {
+ MatchString(pat, str string) (bool, error)
+ StartCPUProfile(io.Writer) error
+ StopCPUProfile()
+ WriteHeapProfile(io.Writer) error
+ WriteProfileTo(string, io.Writer, int) error
}
// MainStart is meant for use by tests generated by 'go test'.
// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
// It may change signature from release to release.
-func MainStart(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
+func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
return &M{
- matchString: matchString,
- tests: tests,
- benchmarks: benchmarks,
- examples: examples,
+ deps: deps,
+ tests: tests,
+ benchmarks: benchmarks,
+ examples: examples,
}
}
@@ -736,19 +812,22 @@ func (m *M) Run() int {
parseCpuList()
- before()
+ m.before()
startAlarm()
haveExamples = len(m.examples) > 0
- testOk := RunTests(m.matchString, m.tests)
- exampleOk := RunExamples(m.matchString, m.examples)
- stopAlarm()
- if !testOk || !exampleOk || !runBenchmarksInternal(m.matchString, m.benchmarks) {
+ testRan, testOk := runTests(m.deps.MatchString, m.tests)
+ exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples)
+ if !testRan && !exampleRan && *matchBenchmarks == "" {
+ fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
+ }
+ if !testOk || !exampleOk || !runBenchmarks(m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
fmt.Println("FAIL")
- after()
+ m.after()
return 1
}
+
fmt.Println("PASS")
- after()
+ m.after()
return 0
}
@@ -769,12 +848,18 @@ func (t *T) report() {
}
}
+// An internal function but exported because it is cross-package; part of the implementation
+// of the "go test" command.
func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
- ok = true
- if len(tests) == 0 && !haveExamples {
+ ran, ok := runTests(matchString, tests)
+ if !ran && !haveExamples {
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
- return
}
+ return ok
+}
+
+func runTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ran, ok bool) {
+ ok = true
for _, procs := range cpuList {
runtime.GOMAXPROCS(procs)
ctx := newTestContext(*parallel, newMatcher(matchString, *match, "-test.run"))
@@ -797,23 +882,24 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
go func() { <-t.signal }()
})
ok = ok && !t.Failed()
+ ran = ran || t.ran
}
- return
+ return ran, ok
}
// before runs before all testing.
-func before() {
+func (m *M) before() {
if *memProfileRate > 0 {
runtime.MemProfileRate = *memProfileRate
}
if *cpuProfile != "" {
f, err := os.Create(toOutputDir(*cpuProfile))
if err != nil {
- fmt.Fprintf(os.Stderr, "testing: %s", err)
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
return
}
- if err := pprof.StartCPUProfile(f); err != nil {
- fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err)
+ if err := m.deps.StartCPUProfile(f); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s\n", err)
f.Close()
return
}
@@ -822,22 +908,22 @@ func before() {
if *traceFile != "" {
f, err := os.Create(toOutputDir(*traceFile))
if err != nil {
- fmt.Fprintf(os.Stderr, "testing: %s", err)
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+ return
+ }
+ if err := trace.Start(f); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s\n", err)
+ f.Close()
return
}
- /*
- if err := trace.Start(f); err != nil {
- fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s", err)
- f.Close()
- return
- }
- */
- _ = f
// Could save f so after can call f.Close; not worth the effort.
}
if *blockProfile != "" && *blockProfileRate >= 0 {
runtime.SetBlockProfileRate(*blockProfileRate)
}
+ if *mutexProfile != "" && *mutexProfileFraction >= 0 {
+ runtime.SetMutexProfileFraction(*mutexProfileFraction)
+ }
if *coverProfile != "" && cover.Mode == "" {
fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
os.Exit(2)
@@ -845,14 +931,12 @@ func before() {
}
// after runs after all testing.
-func after() {
+func (m *M) after() {
if *cpuProfile != "" {
- pprof.StopCPUProfile() // flushes profile to disk
+ m.deps.StopCPUProfile() // flushes profile to disk
}
if *traceFile != "" {
- /*
- trace.Stop() // flushes trace to disk
- */
+ // trace.Stop() // flushes trace to disk
}
if *memProfile != "" {
f, err := os.Create(toOutputDir(*memProfile))
@@ -861,7 +945,7 @@ func after() {
os.Exit(2)
}
runtime.GC() // materialize all statistics
- if err = pprof.WriteHeapProfile(f); err != nil {
+ if err = m.deps.WriteHeapProfile(f); err != nil {
fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *memProfile, err)
os.Exit(2)
}
@@ -873,7 +957,19 @@ func after() {
fmt.Fprintf(os.Stderr, "testing: %s\n", err)
os.Exit(2)
}
- if err = pprof.Lookup("block").WriteTo(f, 0); err != nil {
+ if err = m.deps.WriteProfileTo("block", f, 0); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
+ os.Exit(2)
+ }
+ f.Close()
+ }
+ if *mutexProfile != "" && *mutexProfileFraction >= 0 {
+ f, err := os.Create(toOutputDir(*mutexProfile))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+ os.Exit(2)
+ }
+ if err = m.deps.WriteProfileTo("mutex", f, 0); err != nil {
fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
os.Exit(2)
}