aboutsummaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing')
-rw-r--r--src/testing/internal/testdeps/deps.go62
-rw-r--r--src/testing/testing.go31
2 files changed, 91 insertions, 2 deletions
diff --git a/src/testing/internal/testdeps/deps.go b/src/testing/internal/testdeps/deps.go
index 042f69614e..8c0b3fded1 100644
--- a/src/testing/internal/testdeps/deps.go
+++ b/src/testing/internal/testdeps/deps.go
@@ -11,9 +11,13 @@
package testdeps
import (
+ "bufio"
+ "internal/testlog"
"io"
"regexp"
"runtime/pprof"
+ "strings"
+ "sync"
)
// TestDeps is an implementation of the testing.testDeps interface,
@@ -56,3 +60,61 @@ var ImportPath string
func (TestDeps) ImportPath() string {
return ImportPath
}
+
+// testLog implements testlog.Interface, logging actions by package os.
+type testLog struct {
+ mu sync.Mutex
+ w *bufio.Writer
+}
+
+func (l *testLog) Getenv(key string) {
+ l.add("getenv", key)
+}
+
+func (l *testLog) Open(name string) {
+ l.add("open", name)
+}
+
+func (l *testLog) Stat(name string) {
+ l.add("stat", name)
+}
+
+func (l *testLog) Chdir(name string) {
+ l.add("chdir", name)
+}
+
+// add adds the (op, name) pair to the test log.
+func (l *testLog) add(op, name string) {
+ if strings.Contains(name, "\n") || name == "" {
+ return
+ }
+
+ l.mu.Lock()
+ defer l.mu.Unlock()
+ if l.w == nil {
+ return
+ }
+ l.w.WriteString(op)
+ l.w.WriteByte(' ')
+ l.w.WriteString(name)
+ l.w.WriteByte('\n')
+}
+
+var log testLog
+
+func (TestDeps) StartTestLog(w io.Writer) {
+ log.mu.Lock()
+ log.w = bufio.NewWriter(w)
+ log.w.WriteString("# test log\n") // known to cmd/go/internal/test/test.go
+ log.mu.Unlock()
+
+ testlog.SetLogger(&log)
+}
+
+func (TestDeps) StopTestLog() error {
+ log.mu.Lock()
+ defer log.mu.Unlock()
+ err := log.w.Flush()
+ log.w = nil
+ return err
+}
diff --git a/src/testing/testing.go b/src/testing/testing.go
index cddd475fd7..402780ad64 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -268,10 +268,12 @@ var (
timeout = flag.Duration("test.timeout", 0, "panic test binary after duration `d` (default 0, timeout disabled)")
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")
+ testlog = flag.String("test.testlogfile", "", "write test action log to `file` (for use only by cmd/go)")
haveExamples bool // are there examples?
- cpuList []int
+ cpuList []int
+ testlogFile *os.File
numFailed uint32 // number of test failures
)
@@ -889,6 +891,8 @@ 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 "" }
+func (f matchStringOnly) StartTestLog(io.Writer) {}
+func (f matchStringOnly) StopTestLog() 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.
@@ -916,12 +920,14 @@ type M struct {
// The canonical implementation of this interface is
// testing/internal/testdeps's TestDeps.
type testDeps interface {
+ ImportPath() string
MatchString(pat, str string) (bool, error)
StartCPUProfile(io.Writer) error
StopCPUProfile()
+ StartTestLog(io.Writer)
+ StopTestLog() error
WriteHeapProfile(io.Writer) error
WriteProfileTo(string, io.Writer, int) error
- ImportPath() string
}
// MainStart is meant for use by tests generated by 'go test'.
@@ -1100,6 +1106,17 @@ func (m *M) before() {
fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
os.Exit(2)
}
+ if *testlog != "" {
+ // Note: Not using toOutputDir.
+ // This file is for use by cmd/go, not users.
+ f, err := os.Create(*testlog)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+ os.Exit(2)
+ }
+ m.deps.StartTestLog(f)
+ testlogFile = f
+ }
}
// after runs after all testing.
@@ -1110,6 +1127,16 @@ func (m *M) after() {
}
func (m *M) writeProfiles() {
+ if *testlog != "" {
+ if err := m.deps.StopTestLog(); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *testlog, err)
+ os.Exit(2)
+ }
+ if err := testlogFile.Close(); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *testlog, err)
+ os.Exit(2)
+ }
+ }
if *cpuProfile != "" {
m.deps.StopCPUProfile() // flushes profile to disk
}