...
1
18
19 package retry
20
21 import (
22 "context"
23 "errors"
24 "testing"
25 "time"
26 )
27
28 var errTest error = errors.New("test error")
29
30 type constantBackoff struct{}
31
32 func (b constantBackoff) Pause() time.Duration { return 100 }
33
34 func TestS2ARetryer(t *testing.T) {
35 tests := []struct {
36 name string
37 err error
38 wantDelay time.Duration
39 wantShouldRetry bool
40 }{
41 {
42 name: "retry on err",
43 err: errTest,
44 wantDelay: 100,
45 wantShouldRetry: true,
46 },
47 {
48 name: "don't retry if err is nil",
49 err: nil,
50 wantDelay: 0,
51 wantShouldRetry: false,
52 },
53 }
54
55 for _, tc := range tests {
56 t.Run(tc.name, func(t *testing.T) {
57 retryer := S2ARetryer{bo: constantBackoff{}}
58 delay, shouldRetry := retryer.Retry(tc.err)
59 if delay != tc.wantDelay {
60 t.Fatalf("retryer.Retry(%v) = %v, want %v", tc.err, delay, tc.wantDelay)
61 }
62 if shouldRetry != tc.wantShouldRetry {
63 t.Fatalf("retryer.Retry(%v) = %v, want %v", tc.err, shouldRetry, tc.wantShouldRetry)
64 }
65 })
66 }
67 }
68
69 func TestS2ARetryerAttempts(t *testing.T) {
70 retryer := S2ARetryer{bo: constantBackoff{}}
71 for i := 1; i <= 5; i++ {
72 _, shouldRetry := retryer.Retry(errTest)
73 if !shouldRetry {
74 t.Fatalf("retryer.Retry(errTest) = false, want true")
75 }
76 }
77 _, shouldRetry := retryer.Retry(errTest)
78 if shouldRetry {
79 t.Fatal("an error should only be retried 5 times")
80 }
81 }
82
83 func TestDefaultBackoff(t *testing.T) {
84 bo := defaultBackoff{
85 cur: 100 * time.Millisecond,
86 max: 30 * time.Second,
87 mul: 2,
88 }
89 pauseOne := bo.Pause()
90 pauseTwo := bo.Pause()
91 if pauseOne > 100*time.Millisecond {
92 t.Fatal("first backoff should be less than 100 milli seconds")
93 }
94 if pauseTwo > 2*100*time.Millisecond {
95 t.Fatal("second backoff should be less than 200 milli seconds")
96 }
97 }
98
99 func TestSuccessAfterRetry(t *testing.T) {
100 oldRetry := NewRetryer
101 defer func() { NewRetryer = oldRetry }()
102 testRetryer := NewRetryer()
103 NewRetryer = func() *S2ARetryer {
104 return testRetryer
105 }
106
107 cnt := 1
108 f := func() error {
109 if cnt == 1 {
110 cnt++
111 return errTest
112 }
113 return nil
114 }
115 if testRetryer.Attempts() != 0 {
116 t.Fatal("before execution, retry attempt count should be 0")
117 }
118
119 Run(context.Background(), f)
120
121 if testRetryer.Attempts() != 1 {
122 t.Fatal("execution should've succeeded after 1 retry")
123 }
124 }
125
View as plain text