diff options
Diffstat (limited to 'src/testing/sub_test.go')
| -rw-r--r-- | src/testing/sub_test.go | 180 |
1 files changed, 127 insertions, 53 deletions
diff --git a/src/testing/sub_test.go b/src/testing/sub_test.go index 264d77c2cf..2804550737 100644 --- a/src/testing/sub_test.go +++ b/src/testing/sub_test.go @@ -5,8 +5,9 @@ package testing import ( - "io/ioutil" + "bytes" "regexp" + "strings" "sync/atomic" "time" ) @@ -113,11 +114,17 @@ func TestTRun(t *T) { desc string ok bool maxPar int + chatty bool + output string f func(*T) }{{ desc: "failnow skips future sequential and parallel tests at same level", ok: false, maxPar: 1, + output: ` +--- FAIL: failnow skips future sequential and parallel tests at same level (N.NNs) + --- FAIL: failnow skips future sequential and parallel tests at same level/#00 (N.NNs) + `, f: func(t *T) { ranSeq := false ranPar := false @@ -149,6 +156,11 @@ func TestTRun(t *T) { desc: "failure in parallel test propagates upwards", ok: false, maxPar: 1, + output: ` +--- FAIL: failure in parallel test propagates upwards (N.NNs) + --- FAIL: failure in parallel test propagates upwards/#00 (N.NNs) + --- FAIL: failure in parallel test propagates upwards/#00/par (N.NNs) + `, f: func(t *T) { t.Run("", func(t *T) { t.Parallel() @@ -159,6 +171,44 @@ func TestTRun(t *T) { }) }, }, { + desc: "skipping without message, chatty", + ok: true, + chatty: true, + output: ` +=== RUN skipping without message, chatty +--- SKIP: skipping without message, chatty (N.NNs)`, + f: func(t *T) { t.SkipNow() }, + }, { + desc: "chatty with recursion", + ok: true, + chatty: true, + output: ` +=== RUN chatty with recursion +=== RUN chatty with recursion/#00 +=== RUN chatty with recursion/#00/#00 +--- PASS: chatty with recursion (N.NNs) + --- PASS: chatty with recursion/#00 (N.NNs) + --- PASS: chatty with recursion/#00/#00 (N.NNs)`, + f: func(t *T) { + t.Run("", func(t *T) { + t.Run("", func(t *T) {}) + }) + }, + }, { + desc: "skipping without message, not chatty", + ok: true, + f: func(t *T) { t.SkipNow() }, + }, { + desc: "skipping after error", + output: ` +--- FAIL: skipping after error (N.NNs) + sub_test.go:NNN: an error + sub_test.go:NNN: skipped`, + f: func(t *T) { + t.Error("an error") + t.Skip("skipped") + }, + }, { desc: "use Run to locally synchronize parallelism", ok: true, maxPar: 1, @@ -177,57 +227,6 @@ func TestTRun(t *T) { } }, }, { - desc: "run no more than *parallel tests concurrently", - ok: true, - maxPar: 4, - f: func(t *T) { - max := 0 - in := make(chan int) - out := make(chan int) - ctx := t.context - t.Run("wait", func(t *T) { - t.Run("controller", func(t *T) { - // Verify sequential tests don't skew counts. - t.Run("seq1", func(t *T) {}) - t.Run("seq2", func(t *T) {}) - t.Run("seq3", func(t *T) {}) - t.Parallel() - for i := 0; i < 80; i++ { - ctx.mu.Lock() - if ctx.running > max { - max = ctx.running - } - ctx.mu.Unlock() - <-in - // force a minimum to avoid a race, although it works - // without it. - if i >= ctx.maxParallel-2 { // max - this - 1 - out <- i - } - } - close(out) - }) - // Ensure we don't exceed the maximum even with nested parallelism. - for i := 0; i < 2; i++ { - t.Run("", func(t *T) { - t.Parallel() - for j := 0; j < 40; j++ { - t.Run("", func(t *T) { - t.Run("seq1", func(t *T) {}) - t.Run("seq2", func(t *T) {}) - t.Parallel() - in <- j - <-out - }) - } - }) - } - }) - if max != ctx.maxParallel { - realTest.Errorf("max: got %d; want: %d", max, ctx.maxParallel) - } - }, - }, { desc: "alternate sequential and parallel", // Sequential tests should partake in the counting of running threads. // Otherwise, if one runs parallel subtests in sequential tests that are @@ -301,14 +300,23 @@ func TestTRun(t *T) { }) } }, + }, { + desc: "skip output", + ok: true, + maxPar: 4, + f: func(t *T) { + t.Skip() + }, }} for _, tc := range testCases { ctx := newTestContext(tc.maxPar, newMatcher(regexp.MatchString, "", "")) + buf := &bytes.Buffer{} root := &T{ common: common{ signal: make(chan bool), name: "Test", - w: ioutil.Discard, + w: buf, + chatty: tc.chatty, }, context: ctx, } @@ -324,6 +332,12 @@ func TestTRun(t *T) { if ctx.running != 0 || ctx.numWaiting != 0 { t.Errorf("%s:running and waiting non-zero: got %d and %d", tc.desc, ctx.running, ctx.numWaiting) } + got := strings.TrimSpace(buf.String()) + want := strings.TrimSpace(tc.output) + re := makeRegexp(want) + if ok, err := regexp.MatchString(re, got); !ok || err != nil { + t.Errorf("%s:ouput:\ngot:\n%s\nwant:\n%s", tc.desc, got, want) + } } } @@ -336,6 +350,8 @@ func TestBRun(t *T) { testCases := []struct { desc string failed bool + chatty bool + output string f func(*B) }{{ desc: "simulate sequential run of subbenchmarks.", @@ -371,8 +387,43 @@ func TestBRun(t *T) { }, { desc: "failure carried over to root", failed: true, + output: "--- FAIL: root", f: func(b *B) { b.Fail() }, }, { + desc: "skipping without message, chatty", + chatty: true, + output: "--- SKIP: root", + f: func(b *B) { b.SkipNow() }, + }, { + desc: "skipping with message, chatty", + chatty: true, + output: ` +--- SKIP: root + sub_test.go:NNN: skipping`, + f: func(b *B) { b.Skip("skipping") }, + }, { + desc: "chatty with recursion", + chatty: true, + f: func(b *B) { + b.Run("", func(b *B) { + b.Run("", func(b *B) {}) + }) + }, + }, { + desc: "skipping without message, not chatty", + f: func(b *B) { b.SkipNow() }, + }, { + desc: "skipping after error", + failed: true, + output: ` +--- FAIL: root + sub_test.go:NNN: an error + sub_test.go:NNN: skipped`, + f: func(b *B) { + b.Error("an error") + b.Skip("skipped") + }, + }, { desc: "memory allocation", f: func(b *B) { const bufSize = 256 @@ -398,11 +449,15 @@ func TestBRun(t *T) { }} for _, tc := range testCases { var ok bool + buf := &bytes.Buffer{} // This is almost like the Benchmark function, except that we override // the benchtime and catch the failure result of the subbenchmark. root := &B{ common: common{ signal: make(chan bool), + name: "root", + w: buf, + chatty: tc.chatty, }, benchFunc: func(b *B) { ok = b.Run("test", tc.f) }, // Use Run to catch failure. benchTime: time.Microsecond, @@ -418,5 +473,24 @@ func TestBRun(t *T) { if root.result.N != 1 { t.Errorf("%s: N for parent benchmark was %d; want 1", tc.desc, root.result.N) } + got := strings.TrimSpace(buf.String()) + want := strings.TrimSpace(tc.output) + re := makeRegexp(want) + if ok, err := regexp.MatchString(re, got); !ok || err != nil { + t.Errorf("%s:ouput:\ngot:\n%s\nwant:\n%s", tc.desc, got, want) + } } } + +func makeRegexp(s string) string { + s = strings.Replace(s, ":NNN:", `:\d\d\d:`, -1) + s = strings.Replace(s, "(N.NNs)", `\(\d*\.\d*s\)`, -1) + return s +} + +func TestBenchmarkOutput(t *T) { + // Ensure Benchmark initialized common.w by invoking it with an error and + // normal case. + Benchmark(func(b *B) { b.Error("do not print this output") }) + Benchmark(func(b *B) {}) +} |
