@@ -104,6 +104,7 @@ describe('Test TokenBucket Rate Limiter', () => {
104104 // tokens returned in processRequest is equal to the capacity
105105 // still available in the fixed window
106106
107+ // adds additional ms so that:
107108 // rolling window proportion: .99999...
108109 // 1 + 10 * .9 = 10 (floored)
109110 const result = await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE + 1 , 1 ) ;
@@ -123,7 +124,31 @@ describe('Test TokenBucket Rate Limiter', () => {
123124 expect ( count . currentTokens ) . toBe ( 1 ) ;
124125 } ) ;
125126
126- // three different tests within, with different rolling window proportions (.25, .5, .75)
127+ // five different tests within, with different rolling window proportions (0.01, .25, .5, .75, 1)
128+ test ( 'rolling window at 100% allows requests under capacity' , async ( ) => {
129+ // 100% of rolling window present in previous fixed window
130+ // 1*60000 = 60000 (time after initial fixedWindowStart
131+ // to set rolling window at 100% of previous fixed window)
132+
133+ // to set initial fixedWindowStart
134+ await setTokenCountInClient ( client , user4 , 0 , 0 , timestamp ) ;
135+
136+ // large request at very end of first fixed window
137+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , 8 ) ;
138+
139+ // 2 + 8 * 1 = 10, right at capacity (request should be allowed)
140+ // tokens until capacity: 0 (tokens property returned by processRequest method)
141+ const result = await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE , 2 ) ;
142+ expect ( result . tokens ) . toBe ( 0 ) ;
143+ expect ( result . success ) . toBe ( true ) ;
144+
145+ // currentTokens (in current fixed window): 4
146+ // previousTokens (in previous fixed window): 8
147+ const count1 = await getWindowFromClient ( client , user4 ) ;
148+ expect ( count1 . currentTokens ) . toBe ( 2 ) ;
149+ expect ( count1 . previousTokens ) . toBe ( 8 ) ;
150+ } ) ;
151+
127152 test ( 'rolling window at 75% allows requests under capacity' , async ( ) => {
128153 // 75% of rolling window present in previous fixed window
129154 // 1.25*60000 = 75000 (time after initial fixedWindowStart
@@ -133,13 +158,17 @@ describe('Test TokenBucket Rate Limiter', () => {
133158 await setTokenCountInClient ( client , user4 , 0 , 0 , timestamp ) ;
134159
135160 // large request at very end of first fixed window
136- await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE , 8 ) ;
161+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , 8 ) ;
137162
138163 // 4 + 8 * .75 = 10, right at capacity (request should be allowed)
139164 // tokens until capacity: 0 (tokens property returned by processRequest method)
140- expect (
141- ( await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE * 1.25 , 4 ) ) . tokens
142- ) . toBe ( 0 ) ;
165+ const result = await limiter . processRequest (
166+ user4 ,
167+ timestamp + WINDOW_SIZE * 1.25 ,
168+ 4
169+ ) ;
170+ expect ( result . tokens ) . toBe ( 0 ) ;
171+ expect ( result . success ) . toBe ( true ) ;
143172
144173 // currentTokens (in current fixed window): 4
145174 // previousTokens (in previous fixed window): 8
@@ -157,13 +186,17 @@ describe('Test TokenBucket Rate Limiter', () => {
157186 await setTokenCountInClient ( client , user4 , 0 , 0 , timestamp ) ;
158187
159188 // large request at very end of first fixed window
160- await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE , 8 ) ;
189+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , 8 ) ;
161190
162191 // 4 + 8 * .5 = 8, under capacity (request should be allowed)
163192 // tokens until capacity: 2 (tokens property returned by processRequest method)
164- expect (
165- ( await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE * 1.5 , 4 ) ) . tokens
166- ) . toBe ( 2 ) ;
193+ const result = await limiter . processRequest (
194+ user4 ,
195+ timestamp + WINDOW_SIZE * 1.5 ,
196+ 4
197+ ) ;
198+ expect ( result . tokens ) . toBe ( 2 ) ;
199+ expect ( result . success ) . toBe ( true ) ;
167200
168201 // currentTokens (in current fixed window): 4
169202 // previousTokens (in previous fixed window): 8
@@ -181,20 +214,52 @@ describe('Test TokenBucket Rate Limiter', () => {
181214 await setTokenCountInClient ( client , user4 , 0 , 0 , timestamp ) ;
182215
183216 // large request at very end of first fixed window
184- await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE , 8 ) ;
217+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , 8 ) ;
185218
186219 // 4 + 8 * .25 = 6, under capacity (request should be allowed)
187220 // tokens until capacity: 4 (tokens property returned by processRequest method)
188- expect (
189- ( await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE * 1.75 , 4 ) ) . tokens
190- ) . toBe ( 4 ) ;
221+ const result = await limiter . processRequest (
222+ user4 ,
223+ timestamp + WINDOW_SIZE * 1.75 ,
224+ 4
225+ ) ;
226+ expect ( result . tokens ) . toBe ( 4 ) ;
227+ expect ( result . success ) . toBe ( true ) ;
191228
192229 // currentTokens (in current fixed window): 4
193230 // previousTokens (in previous fixed window): 8
194231 const count = await getWindowFromClient ( client , user4 ) ;
195232 expect ( count . currentTokens ) . toBe ( 4 ) ;
196233 expect ( count . previousTokens ) . toBe ( 8 ) ;
197234 } ) ;
235+
236+ test ( 'rolling window at 1% allows requests under capacity' , async ( ) => {
237+ // 1% of rolling window present in previous fixed window
238+ // 0.01*60000 = 600 (time after initial fixedWindowStart
239+ // to set rolling window at 1% of previous fixed window)
240+
241+ // to set initial fixedWindowStart
242+ await setTokenCountInClient ( client , user4 , 0 , 0 , timestamp ) ;
243+
244+ // large request at very end of first fixed window
245+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , 8 ) ;
246+
247+ // 10 + 8 * .01 = 10, right at capacity (request should be allowed)
248+ // tokens until capacity: 0 (tokens property returned by processRequest method)
249+ const result = await limiter . processRequest (
250+ user4 ,
251+ timestamp + WINDOW_SIZE * 1.99 ,
252+ 4
253+ ) ;
254+ expect ( result . tokens ) . toBe ( 0 ) ;
255+ expect ( result . success ) . toBe ( true ) ;
256+
257+ // currentTokens (in current fixed window): 4
258+ // previousTokens (in previous fixed window): 8
259+ const count1 = await getWindowFromClient ( client , user4 ) ;
260+ expect ( count1 . currentTokens ) . toBe ( 4 ) ;
261+ expect ( count1 . previousTokens ) . toBe ( 8 ) ;
262+ } ) ;
198263 } ) ;
199264
200265 describe ( 'after a BLOCKED request...' , ( ) => {
@@ -214,15 +279,40 @@ describe('Test TokenBucket Rate Limiter', () => {
214279
215280 await setTokenCountInClient ( client , user2 , initRequest , 0 , timestamp ) ;
216281 // expect remaining tokens to be 4, b/c the 5 token request should be blocked
217- expect (
218- ( await limiter . processRequest ( user2 , timestamp + WINDOW_SIZE , 5 ) ) . tokens
219- ) . toBe ( CAPACITY - initRequest ) ;
282+ const result = await limiter . processRequest ( user2 , timestamp + WINDOW_SIZE - 1 , 5 ) ;
283+
284+ expect ( result . success ) . toBe ( false ) ;
285+ expect ( result . tokens ) . toBe ( CAPACITY - initRequest ) ;
220286
221287 // expect current tokens in the window to still be 6
222288 expect ( ( await getWindowFromClient ( client , user2 ) ) . currentTokens ) . toBe ( 6 ) ;
223289 } ) ;
224290
225- // 3 rolling window tests with different proportions (.25, .5, .75)
291+ // 5 rolling window tests with different proportions (.01, .25, .5, .75, 1)
292+ test ( 'rolling window at 100% blocks requests over allowed limit set by formula' , async ( ) => {
293+ // 100% of rolling window present in previous fixed window
294+ // 1*60000 = 60000 (time after initial fixedWindowStart
295+ // to set rolling window at 100% of previous fixed window)
296+
297+ // to set initial fixedWindowStart
298+ await setTokenCountInClient ( client , user4 , 0 , 0 , timestamp ) ;
299+
300+ const initRequest = 8 ;
301+
302+ // large request at very end of first fixed window
303+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , initRequest ) ;
304+
305+ // 3 + 8 * 1 = 11, above capacity (request should be blocked)
306+ const result = await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE , 3 ) ;
307+ expect ( result . tokens ) . toBe ( 10 ) ;
308+ expect ( result . success ) . toBe ( false ) ;
309+
310+ // currentTokens (in current fixed window): 0
311+ // previousTokens (in previous fixed window): 8
312+ const count1 = await getWindowFromClient ( client , user4 ) ;
313+ expect ( count1 . currentTokens ) . toBe ( 0 ) ;
314+ expect ( count1 . previousTokens ) . toBe ( initRequest ) ;
315+ } ) ;
226316 test ( 'rolling window at 75% blocks requests over allowed limit set by formula' , async ( ) => {
227317 // 75% of rolling window present in previous fixed window
228318 // 1.25*60000 = 75000 (time after initial fixedWindowStart
@@ -234,12 +324,16 @@ describe('Test TokenBucket Rate Limiter', () => {
234324 const initRequest = 8 ;
235325
236326 // large request at very end of first fixed window
237- await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE , initRequest ) ;
327+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , initRequest ) ;
238328
239329 // 5 + 8 * .75 = 11, above capacity (request should be blocked)
240- expect (
241- ( await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE * 1.25 , 5 ) ) . tokens
242- ) . toBe ( 10 ) ;
330+ const result = await limiter . processRequest (
331+ user4 ,
332+ timestamp + WINDOW_SIZE * 1.25 ,
333+ 5
334+ ) ;
335+ expect ( result . tokens ) . toBe ( 10 ) ;
336+ expect ( result . success ) . toBe ( false ) ;
243337
244338 // currentTokens (in current fixed window): 0
245339 // previousTokens (in previous fixed window): 8
@@ -260,12 +354,12 @@ describe('Test TokenBucket Rate Limiter', () => {
260354 const initRequest = 8 ;
261355
262356 // large request at very end of first fixed window
263- await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE , initRequest ) ;
357+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , initRequest ) ;
264358
265359 // 7 + 8 * .5 = 11, over capacity (request should be blocked)
266- expect (
267- ( await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE * 1.5 , 7 ) ) . tokens
268- ) . toBe ( 10 ) ;
360+ const result = await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE * 1.5 , 7 ) ;
361+ expect ( result . tokens ) . toBe ( 10 ) ;
362+ expect ( result . success ) . toBe ( false ) ;
269363
270364 // currentTokens (in current fixed window): 0
271365 // previousTokens (in previous fixed window): 8
@@ -285,19 +379,43 @@ describe('Test TokenBucket Rate Limiter', () => {
285379 const initRequest = 8 ;
286380
287381 // large request at very end of first fixed window
288- await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE , initRequest ) ;
382+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , initRequest ) ;
289383
290384 // 9 + 8 * .25 = 11, over capacity (request should be blocked)
291- expect (
292- ( await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE * 1.75 , 9 ) ) . tokens
293- ) . toBe ( 10 ) ;
385+ const result = await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE * 1.75 , 9 ) ;
386+ expect ( result . tokens ) . toBe ( 10 ) ;
387+ expect ( result . success ) . toBe ( false ) ;
294388
295389 // currentTokens (in current fixed window): 0
296390 // previousTokens (in previous fixed window): 8
297391 const count = await getWindowFromClient ( client , user4 ) ;
298392 expect ( count . currentTokens ) . toBe ( 0 ) ;
299393 expect ( count . previousTokens ) . toBe ( initRequest ) ;
300394 } ) ;
395+ test ( 'rolling window at 100% blocks requests over allowed limit set by formula' , async ( ) => {
396+ // 1% of rolling window present in previous fixed window
397+ // .01*60000 = 600 (time after initial fixedWindowStart
398+ // to set rolling window at 100% of previous fixed window)
399+
400+ // to set initial fixedWindowStart
401+ await setTokenCountInClient ( client , user4 , 0 , 0 , timestamp ) ;
402+
403+ const initRequest = 8 ;
404+
405+ // large request at very end of first fixed window
406+ await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE - 1 , initRequest ) ;
407+
408+ // 11 + 8 * .01 = 11, above capacity (request should be blocked)
409+ const result = await limiter . processRequest ( user4 , timestamp + WINDOW_SIZE , 11 ) ;
410+ expect ( result . tokens ) . toBe ( 10 ) ;
411+ expect ( result . success ) . toBe ( false ) ;
412+
413+ // currentTokens (in current fixed window): 0
414+ // previousTokens (in previous fixed window): 8
415+ const count1 = await getWindowFromClient ( client , user4 ) ;
416+ expect ( count1 . currentTokens ) . toBe ( 0 ) ;
417+ expect ( count1 . previousTokens ) . toBe ( initRequest ) ;
418+ } ) ;
301419 } ) ;
302420
303421 describe ( 'SlidingWindowCounter functions as expected' , ( ) => {
0 commit comments