-
Notifications
You must be signed in to change notification settings - Fork 183
/
exponential_test.go
161 lines (137 loc) · 4.68 KB
/
exponential_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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package backoff
import (
"math"
"testing"
"time"
)
func TestBackOff(t *testing.T) {
var (
testInitialInterval = 500 * time.Millisecond
testRandomizationFactor = 0.1
testMultiplier = 2.0
testMaxInterval = 5 * time.Second
testMaxElapsedTime = 15 * time.Minute
)
exp := NewExponentialBackOff()
exp.InitialInterval = testInitialInterval
exp.RandomizationFactor = testRandomizationFactor
exp.Multiplier = testMultiplier
exp.MaxInterval = testMaxInterval
exp.MaxElapsedTime = testMaxElapsedTime
exp.Reset()
var expectedResults = []time.Duration{500, 1000, 2000, 4000, 5000, 5000, 5000, 5000, 5000, 5000}
for i, d := range expectedResults {
expectedResults[i] = d * time.Millisecond
}
for _, expected := range expectedResults {
assertEquals(t, expected, exp.currentInterval)
// Assert that the next backoff falls in the expected range.
var minInterval = expected - time.Duration(testRandomizationFactor*float64(expected))
var maxInterval = expected + time.Duration(testRandomizationFactor*float64(expected))
var actualInterval = exp.NextBackOff()
if !(minInterval <= actualInterval && actualInterval <= maxInterval) {
t.Error("error")
}
}
}
func TestGetRandomizedInterval(t *testing.T) {
// 33% chance of being 1.
assertEquals(t, 1, getRandomValueFromInterval(0.5, 0, 2))
assertEquals(t, 1, getRandomValueFromInterval(0.5, 0.33, 2))
// 33% chance of being 2.
assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.34, 2))
assertEquals(t, 2, getRandomValueFromInterval(0.5, 0.66, 2))
// 33% chance of being 3.
assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.67, 2))
assertEquals(t, 3, getRandomValueFromInterval(0.5, 0.99, 2))
}
type TestClock struct {
i time.Duration
start time.Time
}
func (c *TestClock) Now() time.Time {
t := c.start.Add(c.i)
c.i += time.Second
return t
}
func TestGetElapsedTime(t *testing.T) {
var exp = NewExponentialBackOff()
exp.Clock = &TestClock{}
exp.Reset()
var elapsedTime = exp.GetElapsedTime()
if elapsedTime != time.Second {
t.Errorf("elapsedTime=%d", elapsedTime)
}
}
func TestMaxElapsedTime(t *testing.T) {
var exp = NewExponentialBackOff()
exp.Clock = &TestClock{start: time.Time{}.Add(10000 * time.Second)}
// Change the currentElapsedTime to be 0 ensuring that the elapsed time will be greater
// than the max elapsed time.
exp.startTime = time.Time{}
assertEquals(t, Stop, exp.NextBackOff())
}
func TestCustomStop(t *testing.T) {
var exp = NewExponentialBackOff()
customStop := time.Minute
exp.Stop = customStop
exp.Clock = &TestClock{start: time.Time{}.Add(10000 * time.Second)}
// Change the currentElapsedTime to be 0 ensuring that the elapsed time will be greater
// than the max elapsed time.
exp.startTime = time.Time{}
assertEquals(t, customStop, exp.NextBackOff())
}
func TestBackOffOverflow(t *testing.T) {
var (
testInitialInterval time.Duration = math.MaxInt64 / 2
testMaxInterval time.Duration = math.MaxInt64
testMultiplier = 2.1
)
exp := NewExponentialBackOff()
exp.InitialInterval = testInitialInterval
exp.Multiplier = testMultiplier
exp.MaxInterval = testMaxInterval
exp.Reset()
exp.NextBackOff()
// Assert that when an overflow is possible, the current interval time.Duration is set to the max interval time.Duration.
assertEquals(t, testMaxInterval, exp.currentInterval)
}
func assertEquals(t *testing.T, expected, value time.Duration) {
if expected != value {
t.Errorf("got: %d, expected: %d", value, expected)
}
}
func TestNewExponentialBackOff(t *testing.T) {
// Create a new ExponentialBackOff with custom options
backOff := NewExponentialBackOff(
WithInitialInterval(1*time.Second),
WithMultiplier(2.0),
WithMaxInterval(10*time.Second),
WithMaxElapsedTime(30*time.Second),
WithRetryStopDuration(0),
WithClockProvider(SystemClock),
)
// Check that the backOff object is not nil
if backOff == nil {
t.Error("Expected a non-nil ExponentialBackOff object, got nil")
}
// Check that the custom options were applied correctly
if backOff.InitialInterval != 1*time.Second {
t.Errorf("Expected InitialInterval to be 1 second, got %v", backOff.InitialInterval)
}
if backOff.Multiplier != 2.0 {
t.Errorf("Expected Multiplier to be 2.0, got %v", backOff.Multiplier)
}
if backOff.MaxInterval != 10*time.Second {
t.Errorf("Expected MaxInterval to be 10 seconds, got %v", backOff.MaxInterval)
}
if backOff.MaxElapsedTime != 30*time.Second {
t.Errorf("Expected MaxElapsedTime to be 30 seconds, got %v", backOff.MaxElapsedTime)
}
if backOff.Stop != 0 {
t.Errorf("Expected Stop to be 0 (no stop), got %v", backOff.Stop)
}
if backOff.Clock != SystemClock {
t.Errorf("Expected Clock to be SystemClock, got %v", backOff.Clock)
}
}