]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1] testing: allow concurrent use of T and B
authorBrad Fitzpatrick <bradfitz@golang.org>
Fri, 21 Sep 2012 19:54:12 +0000 (05:54 +1000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 21 Sep 2012 19:54:12 +0000 (05:54 +1000)
««« backport 7a67d277c7e8
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

»»»

src/pkg/testing/testing.go

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