Commit 9b141270 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick

testing: allow concurrent use of T and B

Notably, allow concurrent logging and failing.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/6453045
parent 4d225196
...@@ -87,6 +87,7 @@ import ( ...@@ -87,6 +87,7 @@ import (
"runtime/pprof" "runtime/pprof"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
) )
...@@ -116,8 +117,10 @@ var ( ...@@ -116,8 +117,10 @@ var (
// common holds the elements common between T and B and // common holds the elements common between T and B and
// captures common methods such as Errorf. // captures common methods such as Errorf.
type common struct { type common struct {
mu sync.RWMutex // guards output and failed
output []byte // Output generated by test or benchmark. output []byte // Output generated by test or benchmark.
failed bool // Test or benchmark has failed. failed bool // Test or benchmark has failed.
start time.Time // Time test or benchmark started start time.Time // Time test or benchmark started
duration time.Duration duration time.Duration
self interface{} // To be sent on signal channel when done. self interface{} // To be sent on signal channel when done.
...@@ -176,10 +179,18 @@ type T struct { ...@@ -176,10 +179,18 @@ type T struct {
} }
// Fail marks the function as having failed but continues execution. // Fail marks the function as having failed but continues execution.
func (c *common) Fail() { c.failed = true } func (c *common) Fail() {
c.mu.Lock()
defer c.mu.Unlock()
c.failed = true
}
// Failed returns whether the function has failed. // Failed returns whether the function has failed.
func (c *common) Failed() bool { return c.failed } func (c *common) Failed() bool {
c.mu.RLock()
defer c.mu.RUnlock()
return c.failed
}
// FailNow marks the function as having failed and stops its execution. // FailNow marks the function as having failed and stops its execution.
// Execution will continue at the next test or benchmark. // Execution will continue at the next test or benchmark.
...@@ -210,6 +221,8 @@ func (c *common) FailNow() { ...@@ -210,6 +221,8 @@ func (c *common) FailNow() {
// log generates the output. It's always at the same stack depth. // log generates the output. It's always at the same stack depth.
func (c *common) log(s string) { func (c *common) log(s string) {
c.mu.Lock()
defer c.mu.Unlock()
c.output = append(c.output, decorate(s)...) c.output = append(c.output, decorate(s)...)
} }
...@@ -303,7 +316,7 @@ func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, ...@@ -303,7 +316,7 @@ func Main(matchString func(pat, str string) (bool, error), tests []InternalTest,
func (t *T) report() { func (t *T) report() {
tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds()) tstr := fmt.Sprintf("(%.2f seconds)", t.duration.Seconds())
format := "--- %s: %s %s\n%s" format := "--- %s: %s %s\n%s"
if t.failed { if t.Failed() {
fmt.Printf(format, "FAIL", t.name, tstr, t.output) fmt.Printf(format, "FAIL", t.name, tstr, t.output)
} else if *chatty { } else if *chatty {
fmt.Printf(format, "PASS", t.name, tstr, t.output) fmt.Printf(format, "PASS", t.name, tstr, t.output)
...@@ -362,7 +375,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT ...@@ -362,7 +375,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
continue continue
} }
t.report() t.report()
ok = ok && !out.failed ok = ok && !out.Failed()
} }
running := 0 running := 0
...@@ -375,7 +388,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT ...@@ -375,7 +388,7 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
} }
t := (<-collector).(*T) t := (<-collector).(*T)
t.report() t.report()
ok = ok && !t.failed ok = ok && !t.Failed()
running-- running--
} }
} }
......
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