123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- package core
- import (
- "fmt"
- "math"
- "testing"
- "time"
- )
- // If given New with 0's and no jitter, ensure that certain invariants are met:
- //
- // - the default max duration and interval should be used
- // - noJitter should be true
- // - the RNG should not be initialised
- // - the first duration should be equal to the default interval
- func TestDefaults(t *testing.T) {
- b := NewWithoutJitter(0, 0)
- if b.maxDuration != DefaultMaxDuration {
- t.Fatalf("expected new backoff to use the default max duration (%s), but have %s", DefaultMaxDuration, b.maxDuration)
- }
- if b.interval != DefaultInterval {
- t.Fatalf("exepcted new backoff to use the default interval (%s), but have %s", DefaultInterval, b.interval)
- }
- if b.noJitter != true {
- t.Fatal("backoff should have been initialised without jitter")
- }
- dur := b.Duration()
- if dur != DefaultInterval {
- t.Fatalf("expected first duration to be %s, have %s", DefaultInterval, dur)
- }
- }
- // Given a zero-value initialised Backoff, it should be transparently
- // setup.
- func TestSetup(t *testing.T) {
- b := new(Backoff)
- dur := b.Duration()
- if dur < 0 || dur > (5*time.Minute) {
- t.Fatalf("want duration between 0 and 5 minutes, have %s", dur)
- }
- }
- // Ensure that tries incremenets as expected.
- func TestTries(t *testing.T) {
- b := NewWithoutJitter(5, 1)
- for i := uint64(0); i < 3; i++ {
- if b.n != i {
- t.Fatalf("want tries=%d, have tries=%d", i, b.n)
- }
- pow := 1 << i
- expected := time.Duration(pow)
- dur := b.Duration()
- if dur != expected {
- t.Fatalf("want duration=%d, have duration=%d at i=%d", expected, dur, i)
- }
- }
- for i := uint(3); i < 5; i++ {
- dur := b.Duration()
- if dur != 5 {
- t.Fatalf("want duration=5, have %d at i=%d", dur, i)
- }
- }
- }
- // Ensure that a call to Reset will actually reset the Backoff.
- func TestReset(t *testing.T) {
- const iter = 10
- b := New(1000, 1)
- for i := 0; i < iter; i++ {
- _ = b.Duration()
- }
- if b.n != iter {
- t.Fatalf("expected tries=%d, have tries=%d", iter, b.n)
- }
- b.Reset()
- if b.n != 0 {
- t.Fatalf("expected tries=0 after reset, have tries=%d", b.n)
- }
- }
- const decay = 5 * time.Millisecond
- const max = 10 * time.Millisecond
- const interval = time.Millisecond
- func TestDecay(t *testing.T) {
- const iter = 10
- b := NewWithoutJitter(max, 1)
- b.SetDecay(decay)
- var backoff time.Duration
- for i := 0; i < iter; i++ {
- backoff = b.Duration()
- }
- if b.n != iter {
- t.Fatalf("expected tries=%d, have tries=%d", iter, b.n)
- }
- // Don't decay below backoff
- b.lastTry = time.Now().Add(-backoff + 1)
- backoff = b.Duration()
- if b.n != iter+1 {
- t.Fatalf("expected tries=%d, have tries=%d", iter+1, b.n)
- }
- // Reset after backoff + decay
- b.lastTry = time.Now().Add(-backoff - decay)
- b.Duration()
- if b.n != 1 {
- t.Fatalf("expected tries=%d, have tries=%d", 1, b.n)
- }
- }
- // Ensure that decay works even if the retry counter is saturated.
- func TestDecaySaturation(t *testing.T) {
- b := NewWithoutJitter(1<<2, 1)
- b.SetDecay(decay)
- var duration time.Duration
- for i := 0; i <= 2; i++ {
- duration = b.Duration()
- }
- if duration != 1<<2 {
- t.Fatalf("expected duration=%v, have duration=%v", 1<<2, duration)
- }
- b.lastTry = time.Now().Add(-duration - decay)
- b.n = math.MaxUint64
- duration = b.Duration()
- if duration != 1 {
- t.Errorf("expected duration=%v, have duration=%v", 1, duration)
- }
- }
- func ExampleBackoff_SetDecay() {
- b := NewWithoutJitter(max, interval)
- b.SetDecay(decay)
- // try 0
- fmt.Println(b.Duration())
- // try 1
- fmt.Println(b.Duration())
- // try 2
- duration := b.Duration()
- fmt.Println(duration)
- // try 3, below decay
- time.Sleep(duration)
- duration = b.Duration()
- fmt.Println(duration)
- // try 4, resets
- time.Sleep(duration + decay)
- fmt.Println(b.Duration())
- // Output: 1ms
- // 2ms
- // 4ms
- // 8ms
- // 1ms
- }
|