Skip to content

Commit 9040e95

Browse files
fix/608 - Fix flaky Throttle middleware test by synchronizing token usage (#1016)
* chore: remove comment from TestThrottleRetryAfter test * test: fix flaky TestThrottleRetryAfter by synchronizing token usage
1 parent d12cc49 commit 9040e95

File tree

1 file changed

+41
-29
lines changed

1 file changed

+41
-29
lines changed

middleware/throttle_test.go

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -199,55 +199,67 @@ func TestThrottleMaximum(t *testing.T) {
199199
wg.Wait()
200200
}
201201

202-
// NOTE: test is disabled as it requires some refactoring. It is prone to intermittent failure.
203-
/*func TestThrottleRetryAfter(t *testing.T) {
202+
func TestThrottleRetryAfter(t *testing.T) {
204203
r := chi.NewRouter()
204+
retryAfterFn := func(ctxDone bool) time.Duration { return time.Hour }
205205

206-
retryAfterFn := func(ctxDone bool) time.Duration { return time.Hour * 1 }
207-
r.Use(ThrottleWithOpts(ThrottleOpts{Limit: 10, RetryAfterFn: retryAfterFn}))
206+
r.Use(ThrottleWithOpts(ThrottleOpts{
207+
Limit: 5,
208+
BacklogLimit: 0,
209+
RetryAfterFn: retryAfterFn,
210+
}))
208211

209212
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
213+
time.Sleep(time.Second * 1) // Expensive operation.
210214
w.WriteHeader(http.StatusOK)
211-
time.Sleep(time.Second * 4) // Expensive operation.
212-
w.Write(testContent)
215+
w.Write([]byte("ok"))
213216
})
214217

215218
server := httptest.NewServer(r)
216219
defer server.Close()
220+
client := http.Client{}
217221

218-
client := http.Client{
219-
Timeout: time.Second * 60, // Maximum waiting time.
222+
type result struct {
223+
status int
224+
header http.Header
220225
}
221226

222227
var wg sync.WaitGroup
228+
totalRequests := 10
229+
resultsCh := make(chan result, totalRequests)
223230

224-
for i := 0; i < 10; i++ {
231+
for i := 0; i < totalRequests; i++ {
225232
wg.Add(1)
226-
go func(i int) {
233+
go func() {
227234
defer wg.Done()
228-
229-
res, err := client.Get(server.URL)
230-
assertNoError(t, err)
231-
assertEqual(t, http.StatusOK, res.StatusCode)
232-
}(i)
235+
res, _ := client.Get(server.URL)
236+
resultsCh <- result{status: res.StatusCode, header: res.Header}
237+
}()
233238
}
234239

235-
time.Sleep(time.Second * 1)
236-
237-
for i := 0; i < 10; i++ {
238-
wg.Add(1)
239-
go func(i int) {
240-
defer wg.Done()
241-
242-
res, err := client.Get(server.URL)
243-
assertNoError(t, err)
244-
assertEqual(t, http.StatusTooManyRequests, res.StatusCode)
245-
assertEqual(t, res.Header.Get("Retry-After"), "3600")
246-
}(i)
240+
wg.Wait()
241+
close(resultsCh)
242+
243+
count200 := 0
244+
count429 := 0
245+
for res := range resultsCh {
246+
switch res.status {
247+
case http.StatusOK:
248+
count200++
249+
continue
250+
case http.StatusTooManyRequests:
251+
count429++
252+
assertEqual(t, "3600", res.header.Get("Retry-After"))
253+
continue
254+
default:
255+
t.Fatalf("Unexpected status code: %d", res.status)
256+
continue
257+
}
247258
}
248259

249-
wg.Wait()
250-
}*/
260+
assertEqual(t, 5, count200)
261+
assertEqual(t, 5, count429)
262+
}
251263

252264
func TestThrottleCustomStatusCode(t *testing.T) {
253265
const timeout = time.Second * 3

0 commit comments

Comments
 (0)