@@ -187,4 +187,136 @@ public function testFlooding()
187187 $ this ->assertTrue ($ throttler ->check ('127.0.0.1 ' , $ rate , MINUTE , 0 ));
188188 $ this ->assertSame (10.0 , round ($ this ->cache ->get ('throttler_127.0.0.1 ' )));
189189 }
190+
191+ /**
192+ * @dataProvider tokenTimeUsecases
193+ */
194+ public function testTokenTimeCalculationUCs (int $ capacity , int $ seconds , array $ checkInputs ): void {
195+ $ key = 'testkey ' ;
196+ $ throttler = new Throttler ($ this ->cache );
197+
198+ // clear $key before test start
199+ $ throttler ->remove ($ key );
200+
201+ foreach ($ checkInputs as $ index => $ checkInput ) {
202+ $ throttler ->setTestTime ($ checkInput ['testTime ' ]);
203+ $ checkResult = $ throttler ->check ($ key , $ capacity , $ seconds , $ checkInput ['cost ' ]);
204+
205+ $ this ->assertEquals ($ checkInput ['expectedCheckResult ' ], $ checkResult , "Input# $ index: Wrong check() result " );
206+ $ this ->assertEquals ($ checkInput ['expectedTokenTime ' ], $ throttler ->getTokenTime (), "Input# $ index: Wrong tokenTime " );
207+ }
208+ }
209+
210+ public function tokenTimeUsecases (): array {
211+ return [
212+ '2 capacity / 200 seconds (100s refresh, 0.01 tokens/s) -> 5 checks, 1 cost each ' => [
213+ 'capacity ' => 2 ,
214+ 'seconds ' => 200 ,
215+ 'checkInputs ' => [
216+ [ // 2 -> 1
217+ 'testTime ' => 0 ,
218+ 'cost ' => 1 ,
219+ 'expectedCheckResult ' => true ,
220+ 'expectedTokenTime ' => 0
221+ ],
222+ [ // +3s / 1.03 -> 0.03
223+ 'testTime ' => 3 ,
224+ 'cost ' => 1 ,
225+ 'expectedCheckResult ' => true ,
226+ 'expectedTokenTime ' => 0
227+ ],
228+ [ // +0s / 0.03 -> 0.03 / (1 - 0.03) * 100 = 97
229+ 'testTime ' => 3 ,
230+ 'cost ' => 1 ,
231+ 'expectedCheckResult ' => false ,
232+ 'expectedTokenTime ' => 97
233+ ],
234+ [ // +1m 32s / 0.95 -> 0.95 / (1 - 0.95) * 100 = 5
235+ 'testTime ' => 95 ,
236+ 'cost ' => 1 ,
237+ 'expectedCheckResult ' => false ,
238+ 'expectedTokenTime ' => 5
239+ ],
240+ [ // +7s / 1.02 -> 0.02
241+ 'testTime ' => 102 ,
242+ 'cost ' => 1 ,
243+ 'expectedCheckResult ' => true ,
244+ 'expectedTokenTime ' => 0
245+ ],
246+ [ // +13s / 0.15 / (1 - 0.15) * 100 = 85
247+ 'testTime ' => 115 ,
248+ 'cost ' => 1 ,
249+ 'expectedCheckResult ' => false ,
250+ 'expectedTokenTime ' => 85
251+ ]
252+ ]
253+ ],
254+ '1 capacity / 3600 seconds (3600s refresh, 2.77e-4 tokens/s) -> 2 checks with 1 cost each ' => [
255+ 'capacity ' => 1 ,
256+ 'seconds ' => 3600 ,
257+ 'checkInputs ' => [
258+ [ // 1 -> 0
259+ 'testTime ' => 0 ,
260+ 'cost ' => 1 ,
261+ 'expectedCheckResult ' => true ,
262+ 'expectedTokenTime ' => 0
263+ ],
264+ [ // +6m / 0.1 -> 0.1 / (1 - 0.1) * 3600 = 3240
265+ 'testTime ' => 360 ,
266+ 'cost ' => 1 ,
267+ 'expectedCheckResult ' => false ,
268+ 'expectedTokenTime ' => 3240
269+ ]
270+ ]
271+ ],
272+ '10 capacity / 200 seconds (20s refresh, 0.05 tokens/s) -> 7 checks with different costs (RNG) ' => [
273+ 'capacity ' => 10 ,
274+ 'seconds ' => 200 ,
275+ 'checkInputs ' => [
276+ [ // -2t / 10 -> 8
277+ 'testTime ' => 0 ,
278+ 'cost ' => 2 ,
279+ 'expectedCheckResult ' => true ,
280+ 'expectedTokenTime ' => 0
281+ ],
282+ [ // +19s -2t / 8.95 -> 6.95
283+ 'testTime ' => 19 ,
284+ 'cost ' => 2 ,
285+ 'expectedCheckResult ' => true ,
286+ 'expectedTokenTime ' => 0
287+ ],
288+ [ // +16s -3t / 7.75 -> 4.75
289+ 'testTime ' => 35 ,
290+ 'cost ' => 3 ,
291+ 'expectedCheckResult ' => true ,
292+ 'expectedTokenTime ' => 0
293+ ],
294+ [ // +4s -2t / 4.95 -> 2.95
295+ 'testTime ' => 39 ,
296+ 'cost ' => 2 ,
297+ 'expectedCheckResult ' => true ,
298+ 'expectedTokenTime ' => 0
299+ ],
300+ [ // +13s -5t / 3.6 -> -1.4 (blow allowed)
301+ 'testTime ' => 52 ,
302+ 'cost ' => 5 ,
303+ 'expectedCheckResult ' => true ,
304+ 'expectedTokenTime ' => 0
305+ ],
306+ [ // +2s -2t / -1.3 -> -1.3 / (1 - (-1.3)) * 20 = 46
307+ 'testTime ' => 54 ,
308+ 'cost ' => 2 ,
309+ 'expectedCheckResult ' => false ,
310+ 'expectedTokenTime ' => 46
311+ ],
312+ [ // +7s -2t / -0.95 - -0.95 / (1 - (-0.95)) * 20 = 39
313+ 'testTime ' => 61 ,
314+ 'cost ' => 2 ,
315+ 'expectedCheckResult ' => false ,
316+ 'expectedTokenTime ' => 39
317+ ]
318+ ]
319+ ]
320+ ];
321+ }
190322}
0 commit comments