Commit 6b742b2f authored by Quentin Smith's avatar Quentin Smith

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: default avatarRuss Cox <rsc@golang.org>
parent c0bd4f33
......@@ -3690,6 +3690,28 @@ func TestMatchesOnlyBenchmarkIsOK(t *testing.T) {
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) {
tg := testgo(t)
defer tg.cleanup()
......
......@@ -1373,6 +1373,19 @@ func (t *testFuncs) CoverEnabled() bool {
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.
// 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
......@@ -1503,6 +1516,10 @@ var examples = []testing.InternalExample{
{{end}}
}
func init() {
testdeps.ImportPath = {{.ImportPath | printf "%q"}}
}
{{if .CoverEnabled}}
// Only updated by init functions, so no need for atomicity.
......
package bench
import "testing"
func Benchmark(b *testing.B) {
}
......@@ -47,6 +47,7 @@ type InternalBenchmark struct {
// affecting benchmark results.
type B struct {
common
importPath string // import path of the package containing the benchmark
context *benchContext
N int
previousN int // number of iterations in the previous run
......@@ -233,9 +234,18 @@ func (b *B) run1() bool {
return true
}
var labelsOnce sync.Once
// run executes the benchmark in a separate goroutine, including all of its
// subbenchmarks. b must not have subbenchmarks.
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 {
// Running go test --test.bench
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
// of the "go test" command.
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 len(*matchBenchmarks) == 0 {
return true
......@@ -398,6 +408,7 @@ func runBenchmarks(matchString func(pat, str string) (bool, error), benchmarks [
w: os.Stdout,
chatty: *chatty,
},
importPath: importPath,
benchFunc: func(b *B) {
for _, Benchmark := range bs {
b.Run(Benchmark.Name, Benchmark.F)
......@@ -486,6 +497,7 @@ func (b *B) Run(name string, f func(b *B)) bool {
w: b.w,
chatty: b.chatty,
},
importPath: b.importPath,
benchFunc: f,
benchTime: b.benchTime,
context: b.context,
......
......@@ -49,3 +49,10 @@ func (TestDeps) WriteHeapProfile(w io.Writer) error {
func (TestDeps) WriteProfileTo(name string, w io.Writer, debug int) error {
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) WriteHeapProfile(w io.Writer) 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.
// It was exported because it is cross-package and predates "internal" packages.
......@@ -795,6 +796,7 @@ type testDeps interface {
StopCPUProfile()
WriteHeapProfile(io.Writer) error
WriteProfileTo(string, io.Writer, int) error
ImportPath() string
}
// MainStart is meant for use by tests generated by 'go test'.
......@@ -827,7 +829,7 @@ func (m *M) Run() int {
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 {
if !testOk || !exampleOk || !runBenchmarks(m.deps.ImportPath(), m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
fmt.Println("FAIL")
m.after()
return 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment