| | |
| | |
| | |
| |
|
| | package testing |
| |
|
| | import ( |
| | "bytes" |
| | "strings" |
| | "time" |
| | ) |
| |
|
| | |
| |
|
| | func TestBenchmarkBLoop(t *T) { |
| | var initialStart highPrecisionTime |
| | var firstStart highPrecisionTime |
| | var scaledStart highPrecisionTime |
| | var runningEnd bool |
| | runs := 0 |
| | iters := 0 |
| | firstBN := 0 |
| | restBN := 0 |
| | finalBN := 0 |
| | bRet := Benchmark(func(b *B) { |
| | initialStart = b.start |
| | runs++ |
| | for b.Loop() { |
| | if iters == 0 { |
| | firstStart = b.start |
| | firstBN = b.N |
| | } else { |
| | restBN = max(restBN, b.N) |
| | } |
| | if iters == 1 { |
| | scaledStart = b.start |
| | } |
| | iters++ |
| | } |
| | finalBN = b.N |
| | runningEnd = b.timerOn |
| | }) |
| | |
| | if runs != 1 { |
| | t.Errorf("want runs == 1, got %d", runs) |
| | } |
| | |
| | if iters == 0 { |
| | t.Fatalf("no iterations ran") |
| | } |
| | |
| | if finalBN != iters || bRet.N != iters { |
| | t.Errorf("benchmark iterations mismatch: %d loop iterations, final b.N=%d, bRet.N=%d", iters, finalBN, bRet.N) |
| | } |
| | |
| | if firstBN != 0 { |
| | t.Errorf("want b.N == 0 on first iteration, got %d", firstBN) |
| | } |
| | if restBN != 0 { |
| | t.Errorf("want b.N == 0 on subsequent iterations, got %d", restBN) |
| | } |
| | |
| | if bRet.T < benchTime.d { |
| | t.Fatalf("benchmark ran for %s, want >= %s", bRet.T, benchTime.d) |
| | } |
| | |
| | if firstStart == initialStart { |
| | t.Errorf("b.Loop did not reset the timer") |
| | } |
| | if scaledStart != firstStart { |
| | t.Errorf("b.Loop stops and restarts the timer during iteration") |
| | } |
| | |
| | if runningEnd { |
| | t.Errorf("timer was still running after last iteration") |
| | } |
| | } |
| |
|
| | func TestBenchmarkBLoopCheapEarlyTerminate(t *T) { |
| | if Short() { |
| | t.Skip("B.Loop test needs to run for > 1s to saturate 1e9 iterations") |
| | } |
| | runCnt := 0 |
| | |
| | |
| | |
| | |
| | |
| | |
| | const maxBenchTime = time.Second * 30 |
| | res := Benchmark(func(b *B) { |
| | |
| | b.benchTime.d = maxBenchTime |
| | for b.Loop() { |
| | runCnt++ |
| | } |
| | }) |
| | if runCnt > maxBenchPredictIters { |
| | t.Errorf("loop body ran more than max (%d) times: %d", maxBenchPredictIters, runCnt) |
| | if res.T >= maxBenchTime { |
| | t.Logf("cheap benchmark exhausted time budget: %s; ran for %s", maxBenchTime, res.T) |
| | } |
| | } |
| |
|
| | if res.N != runCnt { |
| | t.Errorf("disagreeing loop counts: res.N reported %d, while b.Loop() iterated %d times", res.N, runCnt) |
| | } |
| |
|
| | if res.N > maxBenchPredictIters { |
| | t.Errorf("benchmark result claims more runs than max (%d) times: %d", maxBenchPredictIters, res.N) |
| | } |
| |
|
| | } |
| |
|
| | func TestBenchmarkBLoopBreak(t *T) { |
| | var bState *B |
| | var bLog bytes.Buffer |
| | bRet := Benchmark(func(b *B) { |
| | |
| | |
| | bState = b |
| | b.common.w = &bLog |
| |
|
| | for i := 0; b.Loop(); i++ { |
| | if i == 2 { |
| | break |
| | } |
| | } |
| | }) |
| | if !bState.failed { |
| | t.Errorf("benchmark should have failed") |
| | } |
| | const wantLog = "benchmark function returned without B.Loop" |
| | if log := bLog.String(); !strings.Contains(log, wantLog) { |
| | t.Errorf("missing error %q in output:\n%s", wantLog, log) |
| | } |
| | |
| | |
| | if bRet.N != 0 { |
| | t.Errorf("want N == 0, got %d", bRet.N) |
| | } |
| | } |
| |
|
| | func TestBenchmarkBLoopError(t *T) { |
| | |
| | |
| | var bState *B |
| | var bLog bytes.Buffer |
| | bRet := Benchmark(func(b *B) { |
| | bState = b |
| | b.common.w = &bLog |
| |
|
| | for i := 0; b.Loop(); i++ { |
| | b.Error("error") |
| | return |
| | } |
| | }) |
| | if !bState.failed { |
| | t.Errorf("benchmark should have failed") |
| | } |
| | const noWantLog = "benchmark function returned without B.Loop" |
| | if log := bLog.String(); strings.Contains(log, noWantLog) { |
| | t.Errorf("unexpected error %q in output:\n%s", noWantLog, log) |
| | } |
| | if bRet.N != 0 { |
| | t.Errorf("want N == 0, got %d", bRet.N) |
| | } |
| | } |
| |
|
| | func TestBenchmarkBLoopStop(t *T) { |
| | var bState *B |
| | var bLog bytes.Buffer |
| | bRet := Benchmark(func(b *B) { |
| | bState = b |
| | b.common.w = &bLog |
| |
|
| | for i := 0; b.Loop(); i++ { |
| | b.StopTimer() |
| | } |
| | }) |
| | if !bState.failed { |
| | t.Errorf("benchmark should have failed") |
| | } |
| | const wantLog = "B.Loop called with timer stopped" |
| | if log := bLog.String(); !strings.Contains(log, wantLog) { |
| | t.Errorf("missing error %q in output:\n%s", wantLog, log) |
| | } |
| | if bRet.N != 0 { |
| | t.Errorf("want N == 0, got %d", bRet.N) |
| | } |
| | } |
| |
|