1 package ratelimits
2
3 import (
4 "testing"
5 "time"
6
7 "github.com/jmhodges/clock"
8 "github.com/letsencrypt/boulder/config"
9 "github.com/letsencrypt/boulder/test"
10 )
11
12 func Test_decide(t *testing.T) {
13 clk := clock.NewFake()
14 limit := precomputeLimit(
15 limit{Burst: 10, Count: 1, Period: config.Duration{Duration: time.Second}},
16 )
17
18
19 d := maybeSpend(clk, limit, clk.Now(), 1)
20 test.Assert(t, d.Allowed, "should be allowed")
21 test.AssertEquals(t, d.Remaining, int64(9))
22 test.AssertEquals(t, d.RetryIn, time.Duration(0))
23 test.AssertEquals(t, d.ResetIn, time.Second)
24
25
26 d = maybeSpend(clk, limit, d.newTAT, 9)
27 test.Assert(t, d.Allowed, "should be allowed")
28 test.AssertEquals(t, d.Remaining, int64(0))
29
30
31 test.AssertEquals(t, d.RetryIn, time.Second*9)
32 test.AssertEquals(t, d.ResetIn, time.Second*10)
33
34
35 test.AssertEquals(t, d.newTAT, clk.Now().Add(time.Second*10))
36
37
38 d = maybeSpend(clk, limit, d.newTAT, 1)
39 test.Assert(t, !d.Allowed, "should not be allowed")
40 test.AssertEquals(t, d.Remaining, int64(0))
41 test.AssertEquals(t, d.RetryIn, time.Second)
42 test.AssertEquals(t, d.ResetIn, time.Second*10)
43
44
45 clk.Add(d.RetryIn)
46 d = maybeSpend(clk, limit, d.newTAT, 0)
47 test.AssertEquals(t, d.Remaining, int64(1))
48
49
50 d = maybeSpend(clk, limit, d.newTAT, 1)
51 test.Assert(t, d.Allowed, "should be allowed")
52 test.AssertEquals(t, d.Remaining, int64(0))
53 test.AssertEquals(t, d.RetryIn, time.Second)
54 test.AssertEquals(t, d.ResetIn, time.Second*10)
55
56
57 clk.Add(d.ResetIn)
58
59
60 d = maybeSpend(clk, limit, d.newTAT, 1)
61 test.Assert(t, d.Allowed, "should be allowed")
62 test.AssertEquals(t, d.Remaining, int64(9))
63 test.AssertEquals(t, d.RetryIn, time.Duration(0))
64 test.AssertEquals(t, d.ResetIn, time.Second)
65
66
67 clk.Add(d.ResetIn - time.Millisecond)
68
69
70
71 d = maybeSpend(clk, limit, d.newTAT, 0)
72 test.Assert(t, d.Allowed, "should be allowed")
73 test.AssertEquals(t, d.Remaining, int64(9))
74 test.AssertEquals(t, d.RetryIn, time.Duration(0))
75 test.AssertEquals(t, d.ResetIn, time.Millisecond)
76
77
78
79 clk.Add(20 * time.Hour)
80
81
82 d = maybeSpend(clk, limit, d.newTAT, 0)
83 test.Assert(t, d.Allowed, "should be allowed")
84 test.AssertEquals(t, d.Remaining, int64(10))
85 test.AssertEquals(t, d.RetryIn, time.Duration(0))
86 test.AssertEquals(t, d.ResetIn, time.Duration(0))
87
88
89
90 d = maybeSpend(clk, limit, d.newTAT, 10)
91 test.Assert(t, d.Allowed, "should be allowed")
92 test.AssertEquals(t, d.Remaining, int64(0))
93
94
95
96 test.AssertEquals(t, d.RetryIn, time.Second*10)
97 test.AssertEquals(t, d.ResetIn, time.Second*10)
98
99
100 d = maybeSpend(clk, limit, d.newTAT, 0)
101 test.Assert(t, d.Allowed, "should be allowed")
102 test.AssertEquals(t, d.Remaining, int64(0))
103 test.AssertEquals(t, d.RetryIn, time.Duration(0))
104 test.AssertEquals(t, d.ResetIn, time.Second*10)
105
106
107 d = maybeSpend(clk, limit, d.newTAT, 1)
108 test.Assert(t, !d.Allowed, "should not be allowed")
109 test.AssertEquals(t, d.Remaining, int64(0))
110 test.AssertEquals(t, d.RetryIn, time.Second)
111 test.AssertEquals(t, d.ResetIn, time.Second*10)
112
113
114 clk.Add(d.RetryIn)
115
116
117 d = maybeSpend(clk, limit, d.newTAT, 1)
118 test.Assert(t, d.Allowed, "should be allowed")
119 test.AssertEquals(t, d.Remaining, int64(0))
120 test.AssertEquals(t, d.RetryIn, time.Second)
121 test.AssertEquals(t, d.ResetIn, time.Second*10)
122
123
124 clk.Add(d.ResetIn / 2)
125
126
127
128
129 d = maybeSpend(clk, limit, d.newTAT, 7)
130 test.Assert(t, !d.Allowed, "should not be allowed")
131 test.AssertEquals(t, d.Remaining, int64(5))
132 test.AssertEquals(t, d.RetryIn, time.Second*2)
133 test.AssertEquals(t, d.ResetIn, time.Second*5)
134 }
135
136 func Test_maybeRefund(t *testing.T) {
137 clk := clock.NewFake()
138 limit := precomputeLimit(
139 limit{Burst: 10, Count: 1, Period: config.Duration{Duration: time.Second}},
140 )
141
142
143 d := maybeSpend(clk, limit, clk.Now(), 1)
144 test.Assert(t, d.Allowed, "should be allowed")
145 test.AssertEquals(t, d.Remaining, int64(9))
146 test.AssertEquals(t, d.RetryIn, time.Duration(0))
147 test.AssertEquals(t, d.ResetIn, time.Second)
148
149
150 d = maybeRefund(clk, limit, d.newTAT, 1)
151 test.AssertEquals(t, d.Remaining, int64(10))
152 test.AssertEquals(t, d.RetryIn, time.Duration(0))
153 test.AssertEquals(t, d.ResetIn, time.Duration(0))
154
155
156 d = maybeSpend(clk, limit, d.newTAT, 1)
157 test.Assert(t, d.Allowed, "should be allowed")
158 test.AssertEquals(t, d.Remaining, int64(9))
159 test.AssertEquals(t, d.RetryIn, time.Duration(0))
160 test.AssertEquals(t, d.ResetIn, time.Second)
161
162
163 clk.Add(d.ResetIn)
164
165
166 d = maybeRefund(clk, limit, d.newTAT, 1)
167 test.Assert(t, !d.Allowed, "should not be allowed")
168 test.AssertEquals(t, d.Remaining, int64(10))
169 test.AssertEquals(t, d.RetryIn, time.Duration(0))
170 test.AssertEquals(t, d.ResetIn, time.Duration(0))
171
172
173 d = maybeSpend(clk, limit, d.newTAT, 10)
174 test.Assert(t, d.Allowed, "should be allowed")
175 test.AssertEquals(t, d.Remaining, int64(0))
176
177
178
179 test.AssertEquals(t, d.RetryIn, time.Second*10)
180 test.AssertEquals(t, d.ResetIn, time.Second*10)
181
182
183 d = maybeRefund(clk, limit, d.newTAT, 10)
184 test.AssertEquals(t, d.Remaining, int64(10))
185 test.AssertEquals(t, d.RetryIn, time.Duration(0))
186 test.AssertEquals(t, d.ResetIn, time.Duration(0))
187
188
189 clk.Add(11 * time.Second)
190
191
192 d = maybeRefund(clk, limit, d.newTAT, 1)
193 test.Assert(t, !d.Allowed, "should be allowed")
194 test.AssertEquals(t, d.Remaining, int64(10))
195 test.AssertEquals(t, d.RetryIn, time.Duration(0))
196 test.AssertEquals(t, d.ResetIn, time.Duration(0))
197
198
199 d = maybeSpend(clk, limit, d.newTAT, 5)
200 d = maybeRefund(clk, limit, d.newTAT, 1)
201 test.Assert(t, d.Allowed, "should be allowed")
202 test.AssertEquals(t, d.Remaining, int64(6))
203 test.AssertEquals(t, d.RetryIn, time.Duration(0))
204
205
206 clk.Add(time.Millisecond * 2500)
207
208
209 d = maybeSpend(clk, limit, d.newTAT, 0)
210 test.Assert(t, d.Allowed, "should be allowed")
211 test.AssertEquals(t, d.Remaining, int64(8))
212 test.AssertEquals(t, d.RetryIn, time.Duration(0))
213
214 test.AssertEquals(t, d.ResetIn, time.Millisecond*1500)
215
216
217 d = maybeRefund(clk, limit, d.newTAT, 2)
218 test.AssertEquals(t, d.Remaining, int64(10))
219 test.AssertEquals(t, d.RetryIn, time.Duration(0))
220 test.AssertEquals(t, d.ResetIn, time.Duration(0))
221 }
222
View as plain text