diff options
Diffstat (limited to 'libgo/go/testing')
-rw-r--r-- | libgo/go/testing/benchmark.go | 20 | ||||
-rw-r--r-- | libgo/go/testing/example.go | 78 | ||||
-rw-r--r-- | libgo/go/testing/testing.go | 53 |
3 files changed, 111 insertions, 40 deletions
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go index cb92fab50ad..25fb2d61918 100644 --- a/libgo/go/testing/benchmark.go +++ b/libgo/go/testing/benchmark.go @@ -34,11 +34,12 @@ type InternalBenchmark struct { // timing and to specify the number of iterations to run. type B struct { common - N int - benchmark InternalBenchmark - bytes int64 - timerOn bool - result BenchmarkResult + N int + benchmark InternalBenchmark + bytes int64 + timerOn bool + showAllocResult bool + result BenchmarkResult // The initial states of memStats.Mallocs and memStats.TotalAlloc. startAllocs uint64 startBytes uint64 @@ -91,6 +92,13 @@ func (b *B) ResetTimer() { // If this is called, the benchmark will report ns/op and MB/s. func (b *B) SetBytes(n int64) { b.bytes = n } +// ReportAllocs enables malloc statistics for this benchmark. +// It is equivalent to setting -test.benchmem, but it only affects the +// benchmark function that calls ReportAllocs. +func (b *B) ReportAllocs() { + b.showAllocResult = true +} + func (b *B) nsPerOp() int64 { if b.N <= 0 { return 0 @@ -298,7 +306,7 @@ func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks [ continue } results := r.String() - if *benchmarkMemory { + if *benchmarkMemory || b.showAllocResult { results += "\t" + r.MemString() } fmt.Println(results) diff --git a/libgo/go/testing/example.go b/libgo/go/testing/example.go index dc97255965e..828c2d3eda8 100644 --- a/libgo/go/testing/example.go +++ b/libgo/go/testing/example.go @@ -24,8 +24,6 @@ func RunExamples(matchString func(pat, str string) (bool, error), examples []Int var eg InternalExample - stdout := os.Stdout - for _, eg = range examples { matched, err := matchString(*match, eg.Name) if err != nil { @@ -35,48 +33,68 @@ func RunExamples(matchString func(pat, str string) (bool, error), examples []Int if !matched { continue } - if *chatty { - fmt.Printf("=== RUN: %s\n", eg.Name) + if !runExample(eg) { + ok = false } + } + + return +} + +func runExample(eg InternalExample) (ok bool) { + if *chatty { + fmt.Printf("=== RUN: %s\n", eg.Name) + } - // capture stdout - r, w, err := os.Pipe() + // Capture stdout. + stdout := os.Stdout + r, w, err := os.Pipe() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + os.Stdout = w + outC := make(chan string) + go func() { + buf := new(bytes.Buffer) + _, err := io.Copy(buf, r) + r.Close() if err != nil { - fmt.Fprintln(os.Stderr, err) + fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err) os.Exit(1) } - os.Stdout = w - outC := make(chan string) - go func() { - buf := new(bytes.Buffer) - _, err := io.Copy(buf, r) - if err != nil { - fmt.Fprintf(os.Stderr, "testing: copying pipe: %v\n", err) - os.Exit(1) - } - outC <- buf.String() - }() + outC <- buf.String() + }() + + start := time.Now() + ok = true - // run example - t0 := time.Now() - eg.F() - dt := time.Now().Sub(t0) + // Clean up in a deferred call so we can recover if the example panics. + defer func() { + d := time.Now().Sub(start) - // close pipe, restore stdout, get output + // Close pipe, restore stdout, get output. w.Close() os.Stdout = stdout out := <-outC - // report any errors - tstr := fmt.Sprintf("(%.2f seconds)", dt.Seconds()) - if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e { - fmt.Printf("--- FAIL: %s %s\ngot:\n%s\nwant:\n%s\n", - eg.Name, tstr, g, e) + var fail string + err := recover() + if g, e := strings.TrimSpace(out), strings.TrimSpace(eg.Output); g != e && err == nil { + fail = fmt.Sprintf("got:\n%s\nwant:\n%s\n", g, e) + } + if fail != "" || err != nil { + fmt.Printf("--- FAIL: %s (%v)\n%s", eg.Name, d, fail) ok = false } else if *chatty { - fmt.Printf("--- PASS: %s %s\n", eg.Name, tstr) + fmt.Printf("--- PASS: %s (%v)\n", eg.Name, d) } - } + if err != nil { + panic(err) + } + }() + // Run example. + eg.F() return } diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go index 66b41a50fa7..c1917f8fe03 100644 --- a/libgo/go/testing/testing.go +++ b/libgo/go/testing/testing.go @@ -10,6 +10,14 @@ // [a-z]) and serves to identify the test routine. // These TestXxx routines should be declared within the package they are testing. // +// Tests may be skipped if not applicable like this: +// func TestTimeConsuming(t *testing.T) { +// if testing.Short() { +// t.Skip("skipping test in short mode.") +// } +// ... +// } +// // Functions of the form // func BenchmarkXxx(*testing.B) // are considered benchmarks, and are executed by the "go test" command when @@ -42,8 +50,8 @@ // // The package also runs and verifies example code. Example functions may // include a concluding comment that begins with "Output:" and is compared with -// the standard output of the function when the tests are run, as in these -// examples of an example: +// the standard output of the function when the tests are run. (The comparison +// ignores leading and trailing space.) These are examples of an example: // // func ExampleHello() { // fmt.Println("hello") @@ -185,6 +193,7 @@ type T struct { common name string // Name of test. startParallel chan bool // Parallel tests will wait on this. + skipped bool // Test has been skipped. } // Fail marks the function as having failed but continues execution. @@ -194,7 +203,7 @@ func (c *common) Fail() { c.failed = true } -// Failed returns whether the function has failed. +// Failed reports whether the function has failed. func (c *common) Failed() bool { c.mu.RLock() defer c.mu.RUnlock() @@ -328,10 +337,46 @@ func (t *T) report() { if t.Failed() { fmt.Printf(format, "FAIL", t.name, tstr, t.output) } else if *chatty { - fmt.Printf(format, "PASS", t.name, tstr, t.output) + if t.Skipped() { + fmt.Printf(format, "SKIP", t.name, tstr, t.output) + } else { + fmt.Printf(format, "PASS", t.name, tstr, t.output) + } } } +// Skip is equivalent to Log() followed by SkipNow(). +func (t *T) Skip(args ...interface{}) { + t.log(fmt.Sprintln(args...)) + t.SkipNow() +} + +// Skipf is equivalent to Logf() followed by SkipNow(). +func (t *T) Skipf(format string, args ...interface{}) { + t.log(fmt.Sprintf(format, args...)) + t.SkipNow() +} + +// SkipNow marks the function as having been skipped and stops its execution. +// Execution will continue at the next test or benchmark. See also, t.FailNow. +func (t *T) SkipNow() { + t.skip() + runtime.Goexit() +} + +func (t *T) skip() { + t.mu.Lock() + defer t.mu.Unlock() + t.skipped = true +} + +// Skipped reports whether the function was skipped. +func (t *T) Skipped() bool { + t.mu.RLock() + defer t.mu.RUnlock() + return t.skipped +} + func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) { ok = true if len(tests) == 0 && !haveExamples { |