-
Notifications
You must be signed in to change notification settings - Fork 1
/
retry_test.go
119 lines (97 loc) · 2.71 KB
/
retry_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package retry
import (
"errors"
"reflect"
"sync"
"testing"
"time"
)
type MyError struct{}
func (e *MyError) Error() string {
return "Error"
}
type Counter struct {
sync.Mutex
count int
}
func (c *Counter) Incr() {
c.Lock()
defer c.Unlock()
c.count++
}
func (c *Counter) Count() int {
return c.count
}
func createRetrier(shouldRetry func(error) bool) (*Retrier, *Counter) {
backOffOpts := &BackOffOpts{
InitialInterval: 1 * time.Nanosecond,
MaxInterval: 5 * time.Nanosecond,
MaxElapsedTime: 250 * time.Millisecond}
counter := &Counter{}
return NewRetrier("Retrier", backOffOpts, shouldRetry), counter
}
func TestRetriesUntilMaxElapsedTimeAndCallsNotifyGaveUp(t *testing.T) {
retrier, counter := createRetrier(RetryOnAnyError)
notifyGaveUpCalled := 0
retrier.AddNotifyGaveUp(func(*RetryEvent) { notifyGaveUpCalled++ })
_, err := retrier.Retry(func() (interface{}, error) {
counter.Incr()
return 0, &MyError{}
})
want := &MyError{}
if err != want {
t.Fatalf("Expected %v, got %v", err, want)
}
if counter.Count() < 2 {
t.Fatalf("Expected %v >= 2", counter.Count())
}
if notifyGaveUpCalled != 1 {
t.Fatalf("Expected notifygaveup to have been called")
}
}
func TestRetriesUntilSuccessfulCallingNotifyRetryOnEachRetry(t *testing.T) {
retrier, counter := createRetrier(RetryOnAnyError)
notifyRetryCalled := 0
retrier.AddNotifyRetry(func(*RetryEvent) { notifyRetryCalled++ })
iVal, err := retrier.Retry(func() (interface{}, error) {
counter.Incr()
if counter.Count() < 5 {
return 0, &MyError{}
} else {
return 123, nil
}
})
if err != nil {
t.Fatalf("Expected no error, got: %v", err)
}
val := iVal.(int)
// We retried 4 times, for a total of 5 tries.
if counter.Count() != 5 && val != 123 && notifyRetryCalled != 4 {
t.Fatalf("Unexpected Counter: %v, val %v, notifyRetryCalled: %v", counter.Count(), val, notifyRetryCalled)
}
}
func TestReturnsResultAndErrorForNonRetryableErrors(t *testing.T) {
var neverRetry = func(error) bool { return false }
retrier, _ := createRetrier(neverRetry)
myError := errors.New("myError")
myVal := "my value so far"
got, err := retrier.Retry(func() (interface{}, error) {
return myVal, myError
})
if got, ok := got.(string); !ok || got != myVal {
t.Fatalf("Expected to receive %#v, got %#v", myVal, got)
}
if err != myError {
t.Fatalf("Expected to receive: %v, got %v", myError, err)
}
}
func TestRetryWhenErrorTypeMatches(t *testing.T) {
var MyErrorType = reflect.TypeOf(&MyError{})
shouldRetryFunc := RetryWhenErrorTypeMatches([]reflect.Type{MyErrorType})
if got := shouldRetryFunc(&MyError{}); got != true {
t.Fatalf("Expected true")
}
if got := shouldRetryFunc(errors.New("hi")); got != false {
t.Fatalf("Expected false")
}
}