mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
testing: print extra labels on benchmarks
When running benchmarks, print "goos", "goarch", and "pkg" labels. This makes it easier to refer to benchmark logs and understand how they were generated. "pkg" is printed only for benchmarks located in GOPATH. Change-Id: I397cbdd57b9fe8cbabbb354ec7bfba59f5625c42 Reviewed-on: https://go-review.googlesource.com/36356 Run-TryBot: Quentin Smith <quentin@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
c0bd4f33cc
commit
6b742b2f84
6 changed files with 72 additions and 6 deletions
|
|
@ -3690,6 +3690,28 @@ func TestMatchesOnlyBenchmarkIsOK(t *testing.T) {
|
||||||
tg.grepBoth(okPattern, "go test did not say ok")
|
tg.grepBoth(okPattern, "go test did not say ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBenchmarkLabels(t *testing.T) {
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
// TODO: tg.parallel()
|
||||||
|
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||||
|
tg.run("test", "-run", "^$", "-bench", ".", "bench")
|
||||||
|
tg.grepStdout(`(?m)^goos: `+runtime.GOOS, "go test did not print goos")
|
||||||
|
tg.grepStdout(`(?m)^goarch: `+runtime.GOARCH, "go test did not print goarch")
|
||||||
|
tg.grepStdout(`(?m)^pkg: bench`, "go test did not say pkg: bench")
|
||||||
|
tg.grepBothNot(`(?s)pkg:.*pkg:`, "go test said pkg multiple times")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBenchmarkLabelsOutsideGOPATH(t *testing.T) {
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
// TODO: tg.parallel()
|
||||||
|
tg.run("test", "-run", "^$", "-bench", ".", "testdata/standalone_benchmark_test.go")
|
||||||
|
tg.grepStdout(`(?m)^goos: `+runtime.GOOS, "go test did not print goos")
|
||||||
|
tg.grepStdout(`(?m)^goarch: `+runtime.GOARCH, "go test did not print goarch")
|
||||||
|
tg.grepBothNot(`(?m)^pkg:`, "go test did say pkg:")
|
||||||
|
}
|
||||||
|
|
||||||
func TestMatchesOnlyTestIsOK(t *testing.T) {
|
func TestMatchesOnlyTestIsOK(t *testing.T) {
|
||||||
tg := testgo(t)
|
tg := testgo(t)
|
||||||
defer tg.cleanup()
|
defer tg.cleanup()
|
||||||
|
|
|
||||||
|
|
@ -1373,6 +1373,19 @@ func (t *testFuncs) CoverEnabled() bool {
|
||||||
return testCover
|
return testCover
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImportPath returns the import path of the package being tested, if it is within GOPATH.
|
||||||
|
// This is printed by the testing package when running benchmarks.
|
||||||
|
func (t *testFuncs) ImportPath() string {
|
||||||
|
pkg := t.Package.ImportPath
|
||||||
|
if strings.HasPrefix(pkg, "_/") {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if pkg == "command-line-arguments" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
|
||||||
// Covered returns a string describing which packages are being tested for coverage.
|
// Covered returns a string describing which packages are being tested for coverage.
|
||||||
// If the covered package is the same as the tested package, it returns the empty string.
|
// If the covered package is the same as the tested package, it returns the empty string.
|
||||||
// Otherwise it is a comma-separated human-readable list of packages beginning with
|
// Otherwise it is a comma-separated human-readable list of packages beginning with
|
||||||
|
|
@ -1503,6 +1516,10 @@ var examples = []testing.InternalExample{
|
||||||
{{end}}
|
{{end}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
testdeps.ImportPath = {{.ImportPath | printf "%q"}}
|
||||||
|
}
|
||||||
|
|
||||||
{{if .CoverEnabled}}
|
{{if .CoverEnabled}}
|
||||||
|
|
||||||
// Only updated by init functions, so no need for atomicity.
|
// Only updated by init functions, so no need for atomicity.
|
||||||
|
|
|
||||||
6
src/cmd/go/testdata/src/bench/x_test.go
vendored
Normal file
6
src/cmd/go/testdata/src/bench/x_test.go
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
package bench
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func Benchmark(b *testing.B) {
|
||||||
|
}
|
||||||
|
|
@ -47,6 +47,7 @@ type InternalBenchmark struct {
|
||||||
// affecting benchmark results.
|
// affecting benchmark results.
|
||||||
type B struct {
|
type B struct {
|
||||||
common
|
common
|
||||||
|
importPath string // import path of the package containing the benchmark
|
||||||
context *benchContext
|
context *benchContext
|
||||||
N int
|
N int
|
||||||
previousN int // number of iterations in the previous run
|
previousN int // number of iterations in the previous run
|
||||||
|
|
@ -233,9 +234,18 @@ func (b *B) run1() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var labelsOnce sync.Once
|
||||||
|
|
||||||
// run executes the benchmark in a separate goroutine, including all of its
|
// run executes the benchmark in a separate goroutine, including all of its
|
||||||
// subbenchmarks. b must not have subbenchmarks.
|
// subbenchmarks. b must not have subbenchmarks.
|
||||||
func (b *B) run() BenchmarkResult {
|
func (b *B) run() BenchmarkResult {
|
||||||
|
labelsOnce.Do(func() {
|
||||||
|
fmt.Fprintf(b.w, "goos: %s\n", runtime.GOOS)
|
||||||
|
fmt.Fprintf(b.w, "goarch: %s\n", runtime.GOARCH)
|
||||||
|
if b.importPath != "" {
|
||||||
|
fmt.Fprintf(b.w, "pkg: %s\n", b.importPath)
|
||||||
|
}
|
||||||
|
})
|
||||||
if b.context != nil {
|
if b.context != nil {
|
||||||
// Running go test --test.bench
|
// Running go test --test.bench
|
||||||
b.context.processBench(b) // Must call doBench.
|
b.context.processBench(b) // Must call doBench.
|
||||||
|
|
@ -363,10 +373,10 @@ type benchContext struct {
|
||||||
// An internal function but exported because it is cross-package; part of the implementation
|
// An internal function but exported because it is cross-package; part of the implementation
|
||||||
// of the "go test" command.
|
// of the "go test" command.
|
||||||
func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
|
func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
|
||||||
runBenchmarks(matchString, benchmarks)
|
runBenchmarks("", matchString, benchmarks)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) bool {
|
func runBenchmarks(importPath string, matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) bool {
|
||||||
// If no flag was specified, don't run benchmarks.
|
// If no flag was specified, don't run benchmarks.
|
||||||
if len(*matchBenchmarks) == 0 {
|
if len(*matchBenchmarks) == 0 {
|
||||||
return true
|
return true
|
||||||
|
|
@ -398,6 +408,7 @@ func runBenchmarks(matchString func(pat, str string) (bool, error), benchmarks [
|
||||||
w: os.Stdout,
|
w: os.Stdout,
|
||||||
chatty: *chatty,
|
chatty: *chatty,
|
||||||
},
|
},
|
||||||
|
importPath: importPath,
|
||||||
benchFunc: func(b *B) {
|
benchFunc: func(b *B) {
|
||||||
for _, Benchmark := range bs {
|
for _, Benchmark := range bs {
|
||||||
b.Run(Benchmark.Name, Benchmark.F)
|
b.Run(Benchmark.Name, Benchmark.F)
|
||||||
|
|
@ -486,9 +497,10 @@ func (b *B) Run(name string, f func(b *B)) bool {
|
||||||
w: b.w,
|
w: b.w,
|
||||||
chatty: b.chatty,
|
chatty: b.chatty,
|
||||||
},
|
},
|
||||||
benchFunc: f,
|
importPath: b.importPath,
|
||||||
benchTime: b.benchTime,
|
benchFunc: f,
|
||||||
context: b.context,
|
benchTime: b.benchTime,
|
||||||
|
context: b.context,
|
||||||
}
|
}
|
||||||
if sub.run1() {
|
if sub.run1() {
|
||||||
sub.run()
|
sub.run()
|
||||||
|
|
|
||||||
|
|
@ -49,3 +49,10 @@ func (TestDeps) WriteHeapProfile(w io.Writer) error {
|
||||||
func (TestDeps) WriteProfileTo(name string, w io.Writer, debug int) error {
|
func (TestDeps) WriteProfileTo(name string, w io.Writer, debug int) error {
|
||||||
return pprof.Lookup(name).WriteTo(w, debug)
|
return pprof.Lookup(name).WriteTo(w, debug)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImportPath is the import path of the testing binary, set by the generated main function.
|
||||||
|
var ImportPath string
|
||||||
|
|
||||||
|
func (TestDeps) ImportPath() string {
|
||||||
|
return ImportPath
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -766,6 +766,7 @@ func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return e
|
||||||
func (f matchStringOnly) StopCPUProfile() {}
|
func (f matchStringOnly) StopCPUProfile() {}
|
||||||
func (f matchStringOnly) WriteHeapProfile(w io.Writer) error { return errMain }
|
func (f matchStringOnly) WriteHeapProfile(w io.Writer) error { return errMain }
|
||||||
func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain }
|
func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain }
|
||||||
|
func (f matchStringOnly) ImportPath() string { return "" }
|
||||||
|
|
||||||
// Main is an internal function, part of the implementation of the "go test" command.
|
// 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 was exported because it is cross-package and predates "internal" packages.
|
||||||
|
|
@ -795,6 +796,7 @@ type testDeps interface {
|
||||||
StopCPUProfile()
|
StopCPUProfile()
|
||||||
WriteHeapProfile(io.Writer) error
|
WriteHeapProfile(io.Writer) error
|
||||||
WriteProfileTo(string, io.Writer, int) error
|
WriteProfileTo(string, io.Writer, int) error
|
||||||
|
ImportPath() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// MainStart is meant for use by tests generated by 'go test'.
|
// MainStart is meant for use by tests generated by 'go test'.
|
||||||
|
|
@ -827,7 +829,7 @@ func (m *M) Run() int {
|
||||||
if !testRan && !exampleRan && *matchBenchmarks == "" {
|
if !testRan && !exampleRan && *matchBenchmarks == "" {
|
||||||
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
|
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
|
||||||
}
|
}
|
||||||
if !testOk || !exampleOk || !runBenchmarks(m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
|
if !testOk || !exampleOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
|
||||||
fmt.Println("FAIL")
|
fmt.Println("FAIL")
|
||||||
m.after()
|
m.after()
|
||||||
return 1
|
return 1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue