diff options
| author | Marcel van Lohuizen <mpvl@golang.org> | 2016-01-20 15:47:54 +0100 |
|---|---|---|
| committer | Marcel van Lohuizen <mpvl@golang.org> | 2016-03-18 12:05:55 +0000 |
| commit | 1857bfca134261ab2e0fc1adcf6a974f550d430a (patch) | |
| tree | 9d554848630428f01735098d6afd63b3f557393d /src/testing/sub_test.go | |
| parent | 89cda2db007c8389ba39d292c6372ff0c6a7622f (diff) | |
| download | go-1857bfca134261ab2e0fc1adcf6a974f550d430a.tar.xz | |
testing: implementation of subbenchmarks
API is not exposed yet.
Change-Id: I729360ef2be1d8ea683ca93cdb1763897cc8657c
Reviewed-on: https://go-review.googlesource.com/18895
Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/testing/sub_test.go')
| -rw-r--r-- | src/testing/sub_test.go | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/testing/sub_test.go b/src/testing/sub_test.go index 8cb13ee101..c98ce58307 100644 --- a/src/testing/sub_test.go +++ b/src/testing/sub_test.go @@ -4,6 +4,10 @@ package testing +import ( + "time" +) + func TestTestContext(t *T) { const ( add1 = 0 @@ -99,3 +103,96 @@ func TestTestContext(t *T) { } } } + +// TODO: remove this stub when API is exposed +func (b *B) Run(name string, f func(b *B)) bool { return b.runBench(name, f) } + +func TestBRun(t *T) { + work := func(b *B) { + for i := 0; i < b.N; i++ { + time.Sleep(time.Nanosecond) + } + } + testCases := []struct { + desc string + failed bool + f func(*B) + }{{ + desc: "simulate sequential run of subbenchmarks.", + f: func(b *B) { + b.Run("", func(b *B) { work(b) }) + time1 := b.result.NsPerOp() + b.Run("", func(b *B) { work(b) }) + time2 := b.result.NsPerOp() + if time1 >= time2 { + t.Errorf("no time spent in benchmark t1 >= t2 (%d >= %d)", time1, time2) + } + }, + }, { + desc: "bytes set by all benchmarks", + f: func(b *B) { + b.Run("", func(b *B) { b.SetBytes(10); work(b) }) + b.Run("", func(b *B) { b.SetBytes(10); work(b) }) + if b.result.Bytes != 20 { + t.Errorf("bytes: got: %d; want 20", b.result.Bytes) + } + }, + }, { + desc: "bytes set by some benchmarks", + // In this case the bytes result is meaningless, so it must be 0. + f: func(b *B) { + b.Run("", func(b *B) { b.SetBytes(10); work(b) }) + b.Run("", func(b *B) { work(b) }) + b.Run("", func(b *B) { b.SetBytes(10); work(b) }) + if b.result.Bytes != 0 { + t.Errorf("bytes: got: %d; want 0", b.result.Bytes) + } + }, + }, { + desc: "failure carried over to root", + failed: true, + f: func(b *B) { b.Fail() }, + }, { + desc: "memory allocation", + f: func(b *B) { + const bufSize = 256 + alloc := func(b *B) { + var buf [bufSize]byte + for i := 0; i < b.N; i++ { + _ = append([]byte(nil), buf[:]...) + } + } + b.Run("", func(b *B) { alloc(b) }) + b.Run("", func(b *B) { alloc(b) }) + if got := b.result.MemAllocs; got != 2 { + t.Errorf("MemAllocs was %v; want 2", got) + } + if got := b.result.MemBytes; got != 2*bufSize { + t.Errorf("MemBytes was %v; want %v", got, 2*bufSize) + } + }, + }} + for _, tc := range testCases { + var ok bool + // 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), + }, + benchFunc: func(b *B) { ok = b.Run("test", tc.f) }, // Use Run to catch failure. + benchTime: time.Microsecond, + } + root.run() + if ok != !tc.failed { + t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, !tc.failed) + } + if !ok != root.Failed() { + t.Errorf("%s:root failed: got %v; want %v", tc.desc, !ok, root.Failed()) + } + // All tests are run as subtests + if root.result.N != 1 { + t.Errorf("%s: N for parent benchmark was %d; want 1", tc.desc, root.result.N) + } + } +} |
