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()
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
{{end}}
}
+func init() {
+ testdeps.ImportPath = {{.ImportPath | printf "%q"}}
+}
+
{{if .CoverEnabled}}
// Only updated by init functions, so no need for atomicity.
--- /dev/null
+package bench
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+}
// 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
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.
// 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
w: os.Stdout,
chatty: *chatty,
},
+ importPath: importPath,
benchFunc: func(b *B) {
for _, Benchmark := range bs {
b.Run(Benchmark.Name, Benchmark.F)
w: b.w,
chatty: b.chatty,
},
- benchFunc: f,
- benchTime: b.benchTime,
- context: b.context,
+ importPath: b.importPath,
+ benchFunc: f,
+ benchTime: b.benchTime,
+ context: b.context,
}
if sub.run1() {
sub.run()
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
+}
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.
StopCPUProfile()
WriteHeapProfile(io.Writer) error
WriteProfileTo(string, io.Writer, int) error
+ ImportPath() string
}
// MainStart is meant for use by tests generated by 'go test'.
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