diff options
Diffstat (limited to 'libgo/go/testing/testing.go')
-rw-r--r-- | libgo/go/testing/testing.go | 87 |
1 files changed, 53 insertions, 34 deletions
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go index f59ce8e..e56b77c 100644 --- a/libgo/go/testing/testing.go +++ b/libgo/go/testing/testing.go @@ -79,6 +79,7 @@ package testing import ( + "bytes" "flag" "fmt" "os" @@ -86,6 +87,7 @@ import ( "runtime/pprof" "strconv" "strings" + "sync" "time" ) @@ -115,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. @@ -128,37 +132,42 @@ func Short() bool { return *short } -// decorate inserts the final newline if needed and indentation tabs for formatting. -// If addFileLine is true, it also prefixes the string with the file and line of the call site. -func decorate(s string, addFileLine bool) string { - if addFileLine { - _, file, line, ok := runtime.Caller(3) // decorate + log + public function. - if ok { - // Truncate file name at last file name separator. - if index := strings.LastIndex(file, "/"); index >= 0 { - file = file[index+1:] - } else if index = strings.LastIndex(file, "\\"); index >= 0 { - file = file[index+1:] - } - } else { - file = "???" - line = 1 +// decorate prefixes the string with the file and line of the call site +// and inserts the final newline if needed and indentation tabs for formatting. +func decorate(s string) string { + _, file, line, ok := runtime.Caller(3) // decorate + log + public function. + if ok { + // Truncate file name at last file name separator. + if index := strings.LastIndex(file, "/"); index >= 0 { + file = file[index+1:] + } else if index = strings.LastIndex(file, "\\"); index >= 0 { + file = file[index+1:] } - s = fmt.Sprintf("%s:%d: %s", file, line, s) - } - s = "\t" + s // Every line is indented at least one tab. - n := len(s) - if n > 0 && s[n-1] != '\n' { - s += "\n" - n++ + } else { + file = "???" + line = 1 } - for i := 0; i < n-1; i++ { // -1 to avoid final newline - if s[i] == '\n' { + buf := new(bytes.Buffer) + fmt.Fprintf(buf, "%s:%d: ", file, line) + + lines := strings.Split(s, "\n") + for i, line := range lines { + if i > 0 { + buf.WriteByte('\n') + } + // Every line is indented at least one tab. + buf.WriteByte('\t') + if i > 0 { // Second and subsequent lines are indented an extra tab. - return s[0:i+1] + "\t" + decorate(s[i+1:n], false) + buf.WriteByte('\t') } + buf.WriteString(line) + } + if l := len(s); l > 0 && s[len(s)-1] != '\n' { + // Add final new line if needed. + buf.WriteByte('\n') } - return s + return buf.String() } // T is a type passed to Test functions to manage test state and support formatted test logs. @@ -170,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. @@ -204,7 +221,9 @@ func (c *common) FailNow() { // log generates the output. It's always at the same stack depth. func (c *common) log(s string) { - c.output = append(c.output, decorate(s, true)...) + c.mu.Lock() + defer c.mu.Unlock() + c.output = append(c.output, decorate(s)...) } // Log formats its arguments using default formatting, analogous to Println(), @@ -297,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) @@ -356,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 @@ -369,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-- } } |