diff options
author | Ian Lance Taylor <iant@golang.org> | 2017-01-14 00:05:42 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-01-14 00:05:42 +0000 |
commit | c2047754c300b68c05d65faa8dc2925fe67b71b4 (patch) | |
tree | e183ae81a1f48a02945cb6de463a70c5be1b06f6 /libgo/go/testing | |
parent | 829afb8f05602bb31c9c597b24df7377fed4f059 (diff) | |
download | gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.zip gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.tar.gz gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.tar.bz2 |
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.go | 22 | ||||
-rw-r--r-- | libgo/go/testing/example.go | 10 | ||||
-rw-r--r-- | libgo/go/testing/internal/testdeps/deps.go | 51 | ||||
-rw-r--r-- | libgo/go/testing/quick/quick.go | 2 | ||||
-rw-r--r-- | libgo/go/testing/sub_test.go | 4 | ||||
-rw-r--r-- | libgo/go/testing/testing.go | 250 |
6 files changed, 250 insertions, 89 deletions
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go index 5d58b85..c033ce5 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 fd8343f..e5bce7a 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 0000000..b08300b --- /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 798d41a..95860fd 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 2a24aaa..8d5d920 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 5a3a9ab..8364c8e 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) } |