• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.util.concurrent;
18 
19 import static java.lang.reflect.Modifier.isStatic;
20 import static java.util.concurrent.TimeUnit.MICROSECONDS;
21 import static java.util.concurrent.TimeUnit.MILLISECONDS;
22 import static java.util.concurrent.TimeUnit.NANOSECONDS;
23 import static java.util.concurrent.TimeUnit.SECONDS;
24 import static org.junit.Assert.assertThrows;
25 
26 import com.google.common.collect.ImmutableClassToInstanceMap;
27 import com.google.common.collect.ImmutableSet;
28 import com.google.common.collect.Lists;
29 import com.google.common.testing.NullPointerTester;
30 import com.google.common.testing.NullPointerTester.Visibility;
31 import com.google.common.util.concurrent.RateLimiter.SleepingStopwatch;
32 import java.lang.reflect.Method;
33 import java.util.Arrays;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Random;
37 import java.util.concurrent.TimeUnit;
38 import junit.framework.TestCase;
39 import org.mockito.Mockito;
40 
41 /**
42  * Tests for RateLimiter.
43  *
44  * @author Dimitris Andreou
45  */
46 public class RateLimiterTest extends TestCase {
47   private static final double EPSILON = 1e-8;
48 
49   private final FakeStopwatch stopwatch = new FakeStopwatch();
50 
testSimple()51   public void testSimple() {
52     RateLimiter limiter = RateLimiter.create(5.0, stopwatch);
53     limiter.acquire(); // R0.00, since it's the first request
54     limiter.acquire(); // R0.20
55     limiter.acquire(); // R0.20
56     assertEvents("R0.00", "R0.20", "R0.20");
57   }
58 
testImmediateTryAcquire()59   public void testImmediateTryAcquire() {
60     RateLimiter r = RateLimiter.create(1);
61     assertTrue("Unable to acquire initial permit", r.tryAcquire());
62     assertFalse("Capable of acquiring secondary permit", r.tryAcquire());
63   }
64 
testDoubleMinValueCanAcquireExactlyOnce()65   public void testDoubleMinValueCanAcquireExactlyOnce() {
66     RateLimiter r = RateLimiter.create(Double.MIN_VALUE, stopwatch);
67     assertTrue("Unable to acquire initial permit", r.tryAcquire());
68     assertFalse("Capable of acquiring an additional permit", r.tryAcquire());
69     stopwatch.sleepMillis(Integer.MAX_VALUE);
70     assertFalse("Capable of acquiring an additional permit after sleeping", r.tryAcquire());
71   }
72 
testSimpleRateUpdate()73   public void testSimpleRateUpdate() {
74     RateLimiter limiter = RateLimiter.create(5.0, 5, SECONDS);
75     assertEquals(5.0, limiter.getRate());
76     limiter.setRate(10.0);
77     assertEquals(10.0, limiter.getRate());
78 
79     assertThrows(IllegalArgumentException.class, () -> limiter.setRate(0.0));
80     assertThrows(IllegalArgumentException.class, () -> limiter.setRate(-10.0));
81   }
82 
testAcquireParameterValidation()83   public void testAcquireParameterValidation() {
84     RateLimiter limiter = RateLimiter.create(999);
85     assertThrows(IllegalArgumentException.class, () -> limiter.acquire(0));
86     assertThrows(IllegalArgumentException.class, () -> limiter.acquire(-1));
87     assertThrows(IllegalArgumentException.class, () -> limiter.tryAcquire(0));
88     assertThrows(IllegalArgumentException.class, () -> limiter.tryAcquire(-1));
89     assertThrows(IllegalArgumentException.class, () -> limiter.tryAcquire(0, 1, SECONDS));
90     assertThrows(IllegalArgumentException.class, () -> limiter.tryAcquire(-1, 1, SECONDS));
91   }
92 
testSimpleWithWait()93   public void testSimpleWithWait() {
94     RateLimiter limiter = RateLimiter.create(5.0, stopwatch);
95     limiter.acquire(); // R0.00
96     stopwatch.sleepMillis(200); // U0.20, we are ready for the next request...
97     limiter.acquire(); // R0.00, ...which is granted immediately
98     limiter.acquire(); // R0.20
99     assertEvents("R0.00", "U0.20", "R0.00", "R0.20");
100   }
101 
testSimpleAcquireReturnValues()102   public void testSimpleAcquireReturnValues() {
103     RateLimiter limiter = RateLimiter.create(5.0, stopwatch);
104     assertEquals(0.0, limiter.acquire(), EPSILON); // R0.00
105     stopwatch.sleepMillis(200); // U0.20, we are ready for the next request...
106     assertEquals(0.0, limiter.acquire(), EPSILON); // R0.00, ...which is granted immediately
107     assertEquals(0.2, limiter.acquire(), EPSILON); // R0.20
108     assertEvents("R0.00", "U0.20", "R0.00", "R0.20");
109   }
110 
testSimpleAcquireEarliestAvailableIsInPast()111   public void testSimpleAcquireEarliestAvailableIsInPast() {
112     RateLimiter limiter = RateLimiter.create(5.0, stopwatch);
113     assertEquals(0.0, limiter.acquire(), EPSILON);
114     stopwatch.sleepMillis(400);
115     assertEquals(0.0, limiter.acquire(), EPSILON);
116     assertEquals(0.0, limiter.acquire(), EPSILON);
117     assertEquals(0.2, limiter.acquire(), EPSILON);
118   }
119 
testOneSecondBurst()120   public void testOneSecondBurst() {
121     RateLimiter limiter = RateLimiter.create(5.0, stopwatch);
122     stopwatch.sleepMillis(1000); // max capacity reached
123     stopwatch.sleepMillis(1000); // this makes no difference
124     limiter.acquire(1); // R0.00, since it's the first request
125 
126     limiter.acquire(1); // R0.00, from capacity
127     limiter.acquire(3); // R0.00, from capacity
128     limiter.acquire(1); // R0.00, concluding a burst of 5 permits
129 
130     limiter.acquire(); // R0.20, capacity exhausted
131     assertEvents(
132         "U1.00", "U1.00", "R0.00", "R0.00", "R0.00", "R0.00", // first request and burst
133         "R0.20");
134   }
135 
testCreateWarmupParameterValidation()136   public void testCreateWarmupParameterValidation() {
137     RateLimiter unused;
138     unused = RateLimiter.create(1.0, 1, NANOSECONDS);
139     unused = RateLimiter.create(1.0, 0, NANOSECONDS);
140 
141     assertThrows(IllegalArgumentException.class, () -> RateLimiter.create(0.0, 1, NANOSECONDS));
142 
143     assertThrows(IllegalArgumentException.class, () -> RateLimiter.create(1.0, -1, NANOSECONDS));
144   }
145 
146   @AndroidIncompatible // difference in String.format rounding?
testWarmUp()147   public void testWarmUp() {
148     RateLimiter limiter = RateLimiter.create(2.0, 4000, MILLISECONDS, 3.0, stopwatch);
149     for (int i = 0; i < 8; i++) {
150       limiter.acquire(); // #1
151     }
152     stopwatch.sleepMillis(500); // #2: to repay for the last acquire
153     stopwatch.sleepMillis(4000); // #3: becomes cold again
154     for (int i = 0; i < 8; i++) {
155       limiter.acquire(); // // #4
156     }
157     stopwatch.sleepMillis(500); // #5: to repay for the last acquire
158     stopwatch.sleepMillis(2000); // #6: didn't get cold! It would take another 2 seconds to go cold
159     for (int i = 0; i < 8; i++) {
160       limiter.acquire(); // #7
161     }
162     assertEvents(
163         "R0.00, R1.38, R1.13, R0.88, R0.63, R0.50, R0.50, R0.50", // #1
164         "U0.50", // #2
165         "U4.00", // #3
166         "R0.00, R1.38, R1.13, R0.88, R0.63, R0.50, R0.50, R0.50", // #4
167         "U0.50", // #5
168         "U2.00", // #6
169         "R0.00, R0.50, R0.50, R0.50, R0.50, R0.50, R0.50, R0.50"); // #7
170   }
171 
testWarmUpWithColdFactor()172   public void testWarmUpWithColdFactor() {
173     RateLimiter limiter = RateLimiter.create(5.0, 4000, MILLISECONDS, 10.0, stopwatch);
174     for (int i = 0; i < 8; i++) {
175       limiter.acquire(); // #1
176     }
177     stopwatch.sleepMillis(200); // #2: to repay for the last acquire
178     stopwatch.sleepMillis(4000); // #3: becomes cold again
179     for (int i = 0; i < 8; i++) {
180       limiter.acquire(); // // #4
181     }
182     stopwatch.sleepMillis(200); // #5: to repay for the last acquire
183     stopwatch.sleepMillis(1000); // #6: still warm! It would take another 3 seconds to go cold
184     for (int i = 0; i < 8; i++) {
185       limiter.acquire(); // #7
186     }
187     assertEvents(
188         "R0.00, R1.75, R1.26, R0.76, R0.30, R0.20, R0.20, R0.20", // #1
189         "U0.20", // #2
190         "U4.00", // #3
191         "R0.00, R1.75, R1.26, R0.76, R0.30, R0.20, R0.20, R0.20", // #4
192         "U0.20", // #5
193         "U1.00", // #6
194         "R0.00, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20"); // #7
195   }
196 
testWarmUpWithColdFactor1()197   public void testWarmUpWithColdFactor1() {
198     RateLimiter limiter = RateLimiter.create(5.0, 4000, MILLISECONDS, 1.0, stopwatch);
199     for (int i = 0; i < 8; i++) {
200       limiter.acquire(); // #1
201     }
202     stopwatch.sleepMillis(340); // #2
203     for (int i = 0; i < 8; i++) {
204       limiter.acquire(); // #3
205     }
206     assertEvents(
207         "R0.00, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20", // #1
208         "U0.34", // #2
209         "R0.00, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20, R0.20"); // #3
210   }
211 
212   @AndroidIncompatible // difference in String.format rounding?
testWarmUpAndUpdate()213   public void testWarmUpAndUpdate() {
214     RateLimiter limiter = RateLimiter.create(2.0, 4000, MILLISECONDS, 3.0, stopwatch);
215     for (int i = 0; i < 8; i++) {
216       limiter.acquire(); // // #1
217     }
218     stopwatch.sleepMillis(4500); // #2: back to cold state (warmup period + repay last acquire)
219     for (int i = 0; i < 3; i++) { // only three steps, we're somewhere in the warmup period
220       limiter.acquire(); // #3
221     }
222 
223     limiter.setRate(4.0); // double the rate!
224     limiter.acquire(); // #4, we repay the debt of the last acquire (imposed by the old rate)
225     for (int i = 0; i < 4; i++) {
226       limiter.acquire(); // #5
227     }
228     stopwatch.sleepMillis(4250); // #6, back to cold state (warmup period + repay last acquire)
229     for (int i = 0; i < 11; i++) {
230       limiter.acquire(); // #7, showing off the warmup starting from totally cold
231     }
232 
233     // make sure the areas (times) remain the same, while permits are different
234     assertEvents(
235         "R0.00, R1.38, R1.13, R0.88, R0.63, R0.50, R0.50, R0.50", // #1
236         "U4.50", // #2
237         "R0.00, R1.38, R1.13", // #3, after that the rate changes
238         "R0.88", // #4, this is what the throttling would be with the old rate
239         "R0.34, R0.28, R0.25, R0.25", // #5
240         "U4.25", // #6
241         "R0.00, R0.72, R0.66, R0.59, R0.53, R0.47, R0.41", // #7
242         "R0.34, R0.28, R0.25, R0.25"); // #7 (cont.), note, this matches #5
243   }
244 
testWarmUpAndUpdateWithColdFactor()245   public void testWarmUpAndUpdateWithColdFactor() {
246     RateLimiter limiter = RateLimiter.create(5.0, 4000, MILLISECONDS, 10.0, stopwatch);
247     for (int i = 0; i < 8; i++) {
248       limiter.acquire(); // #1
249     }
250     stopwatch.sleepMillis(4200); // #2: back to cold state (warmup period + repay last acquire)
251     for (int i = 0; i < 3; i++) { // only three steps, we're somewhere in the warmup period
252       limiter.acquire(); // #3
253     }
254 
255     limiter.setRate(10.0); // double the rate!
256     limiter.acquire(); // #4, we repay the debt of the last acquire (imposed by the old rate)
257     for (int i = 0; i < 4; i++) {
258       limiter.acquire(); // #5
259     }
260     stopwatch.sleepMillis(4100); // #6, back to cold state (warmup period + repay last acquire)
261     for (int i = 0; i < 11; i++) {
262       limiter.acquire(); // #7, showing off the warmup starting from totally cold
263     }
264 
265     // make sure the areas (times) remain the same, while permits are different
266     assertEvents(
267         "R0.00, R1.75, R1.26, R0.76, R0.30, R0.20, R0.20, R0.20", // #1
268         "U4.20", // #2
269         "R0.00, R1.75, R1.26", // #3, after that the rate changes
270         "R0.76", // #4, this is what the throttling would be with the old rate
271         "R0.20, R0.10, R0.10, R0.10", // #5
272         "U4.10", // #6
273         "R0.00, R0.94, R0.81, R0.69, R0.57, R0.44, R0.32", // #7
274         "R0.20, R0.10, R0.10, R0.10"); // #7 (cont.), note, this matches #5
275   }
276 
testBurstyAndUpdate()277   public void testBurstyAndUpdate() {
278     RateLimiter rateLimiter = RateLimiter.create(1.0, stopwatch);
279     rateLimiter.acquire(1); // no wait
280     rateLimiter.acquire(1); // R1.00, to repay previous
281 
282     rateLimiter.setRate(2.0); // update the rate!
283 
284     rateLimiter.acquire(1); // R1.00, to repay previous (the previous was under the old rate!)
285     rateLimiter.acquire(2); // R0.50, to repay previous (now the rate takes effect)
286     rateLimiter.acquire(4); // R1.00, to repay previous
287     rateLimiter.acquire(1); // R2.00, to repay previous
288     assertEvents("R0.00", "R1.00", "R1.00", "R0.50", "R1.00", "R2.00");
289   }
290 
testTryAcquire_noWaitAllowed()291   public void testTryAcquire_noWaitAllowed() {
292     RateLimiter limiter = RateLimiter.create(5.0, stopwatch);
293     assertTrue(limiter.tryAcquire(0, SECONDS));
294     assertFalse(limiter.tryAcquire(0, SECONDS));
295     assertFalse(limiter.tryAcquire(0, SECONDS));
296     stopwatch.sleepMillis(100);
297     assertFalse(limiter.tryAcquire(0, SECONDS));
298   }
299 
testTryAcquire_someWaitAllowed()300   public void testTryAcquire_someWaitAllowed() {
301     RateLimiter limiter = RateLimiter.create(5.0, stopwatch);
302     assertTrue(limiter.tryAcquire(0, SECONDS));
303     assertTrue(limiter.tryAcquire(200, MILLISECONDS));
304     assertFalse(limiter.tryAcquire(100, MILLISECONDS));
305     stopwatch.sleepMillis(100);
306     assertTrue(limiter.tryAcquire(100, MILLISECONDS));
307   }
308 
testTryAcquire_overflow()309   public void testTryAcquire_overflow() {
310     RateLimiter limiter = RateLimiter.create(5.0, stopwatch);
311     assertTrue(limiter.tryAcquire(0, MICROSECONDS));
312     stopwatch.sleepMillis(100);
313     assertTrue(limiter.tryAcquire(Long.MAX_VALUE, MICROSECONDS));
314   }
315 
testTryAcquire_negative()316   public void testTryAcquire_negative() {
317     RateLimiter limiter = RateLimiter.create(5.0, stopwatch);
318     assertTrue(limiter.tryAcquire(5, 0, SECONDS));
319     stopwatch.sleepMillis(900);
320     assertFalse(limiter.tryAcquire(1, Long.MIN_VALUE, SECONDS));
321     stopwatch.sleepMillis(100);
322     assertTrue(limiter.tryAcquire(1, -1, SECONDS));
323   }
324 
testSimpleWeights()325   public void testSimpleWeights() {
326     RateLimiter rateLimiter = RateLimiter.create(1.0, stopwatch);
327     rateLimiter.acquire(1); // no wait
328     rateLimiter.acquire(1); // R1.00, to repay previous
329     rateLimiter.acquire(2); // R1.00, to repay previous
330     rateLimiter.acquire(4); // R2.00, to repay previous
331     rateLimiter.acquire(8); // R4.00, to repay previous
332     rateLimiter.acquire(1); // R8.00, to repay previous
333     assertEvents("R0.00", "R1.00", "R1.00", "R2.00", "R4.00", "R8.00");
334   }
335 
testInfinity_Bursty()336   public void testInfinity_Bursty() {
337     RateLimiter limiter = RateLimiter.create(Double.POSITIVE_INFINITY, stopwatch);
338     limiter.acquire(Integer.MAX_VALUE / 4);
339     limiter.acquire(Integer.MAX_VALUE / 2);
340     limiter.acquire(Integer.MAX_VALUE);
341     assertEvents("R0.00", "R0.00", "R0.00"); // no wait, infinite rate!
342 
343     limiter.setRate(2.0);
344     limiter.acquire();
345     limiter.acquire();
346     limiter.acquire();
347     limiter.acquire();
348     limiter.acquire();
349     assertEvents(
350         "R0.00", // First comes the saved-up burst, which defaults to a 1-second burst (2 requests).
351         "R0.00", "R0.00", // Now comes the free request.
352         "R0.50", // Now it's 0.5 seconds per request.
353         "R0.50");
354 
355     limiter.setRate(Double.POSITIVE_INFINITY);
356     limiter.acquire();
357     limiter.acquire();
358     limiter.acquire();
359     assertEvents("R0.50", "R0.00", "R0.00"); // we repay the last request (.5sec), then back to +oo
360   }
361 
362   /** https://code.google.com/p/guava-libraries/issues/detail?id=1791 */
testInfinity_BustyTimeElapsed()363   public void testInfinity_BustyTimeElapsed() {
364     RateLimiter limiter = RateLimiter.create(Double.POSITIVE_INFINITY, stopwatch);
365     stopwatch.instant += 1000000;
366     limiter.setRate(2.0);
367     for (int i = 0; i < 5; i++) {
368       limiter.acquire();
369     }
370     assertEvents(
371         "R0.00", // First comes the saved-up burst, which defaults to a 1-second burst (2 requests).
372         "R0.00", "R0.00", // Now comes the free request.
373         "R0.50", // Now it's 0.5 seconds per request.
374         "R0.50");
375   }
376 
testInfinity_WarmUp()377   public void testInfinity_WarmUp() {
378     RateLimiter limiter = RateLimiter.create(Double.POSITIVE_INFINITY, 10, SECONDS, 3.0, stopwatch);
379     limiter.acquire(Integer.MAX_VALUE / 4);
380     limiter.acquire(Integer.MAX_VALUE / 2);
381     limiter.acquire(Integer.MAX_VALUE);
382     assertEvents("R0.00", "R0.00", "R0.00");
383 
384     limiter.setRate(1.0);
385     limiter.acquire();
386     limiter.acquire();
387     limiter.acquire();
388     assertEvents("R0.00", "R1.00", "R1.00");
389 
390     limiter.setRate(Double.POSITIVE_INFINITY);
391     limiter.acquire();
392     limiter.acquire();
393     limiter.acquire();
394     assertEvents("R1.00", "R0.00", "R0.00");
395   }
396 
testInfinity_WarmUpTimeElapsed()397   public void testInfinity_WarmUpTimeElapsed() {
398     RateLimiter limiter = RateLimiter.create(Double.POSITIVE_INFINITY, 10, SECONDS, 3.0, stopwatch);
399     stopwatch.instant += 1000000;
400     limiter.setRate(1.0);
401     for (int i = 0; i < 5; i++) {
402       limiter.acquire();
403     }
404     assertEvents("R0.00", "R1.00", "R1.00", "R1.00", "R1.00");
405   }
406 
407   /**
408    * Make sure that bursts can never go above 1-second-worth-of-work for the current rate, even when
409    * we change the rate.
410    */
testWeNeverGetABurstMoreThanOneSec()411   public void testWeNeverGetABurstMoreThanOneSec() {
412     RateLimiter limiter = RateLimiter.create(1.0, stopwatch);
413     int[] rates = {1000, 1, 10, 1000000, 10, 1};
414     for (int rate : rates) {
415       int oneSecWorthOfWork = rate;
416       stopwatch.sleepMillis(rate * 1000);
417       limiter.setRate(rate);
418       long burst = measureTotalTimeMillis(limiter, oneSecWorthOfWork, new Random());
419       // we allow one second worth of work to go in a burst (i.e. take less than a second)
420       assertTrue(burst <= 1000);
421       long afterBurst = measureTotalTimeMillis(limiter, oneSecWorthOfWork, new Random());
422       // but work beyond that must take at least one second
423       assertTrue(afterBurst >= 1000);
424     }
425   }
426 
427   /**
428    * This neat test shows that no matter what weights we use in our requests, if we push X amount of
429    * permits in a cool state, where X = rate * timeToCoolDown, and we have specified a
430    * timeToWarmUp() period, it will cost as the prescribed amount of time. E.g., calling
431    * [acquire(5), acquire(1)] takes exactly the same time as [acquire(2), acquire(3), acquire(1)].
432    */
testTimeToWarmUpIsHonouredEvenWithWeights()433   public void testTimeToWarmUpIsHonouredEvenWithWeights() {
434     Random random = new Random();
435     int warmupPermits = 10;
436     double[] coldFactorsToTest = {2.0, 3.0, 10.0};
437     double[] qpsToTest = {4.0, 2.0, 1.0, 0.5, 0.1};
438     for (int trial = 0; trial < 100; trial++) {
439       for (double coldFactor : coldFactorsToTest) {
440         for (double qps : qpsToTest) {
441           // If warmupPermits = maxPermits - thresholdPermits then
442           // warmupPeriod = (1 + coldFactor) * warmupPermits * stableInterval / 2
443           long warmupMillis = (long) ((1 + coldFactor) * warmupPermits / (2.0 * qps) * 1000.0);
444           RateLimiter rateLimiter =
445               RateLimiter.create(qps, warmupMillis, MILLISECONDS, coldFactor, stopwatch);
446           assertEquals(warmupMillis, measureTotalTimeMillis(rateLimiter, warmupPermits, random));
447         }
448       }
449     }
450   }
451 
testNulls()452   public void testNulls() {
453     NullPointerTester tester =
454         new NullPointerTester()
455             .setDefault(SleepingStopwatch.class, stopwatch)
456             .setDefault(int.class, 1)
457             .setDefault(double.class, 1.0d);
458     tester.testStaticMethods(RateLimiter.class, Visibility.PACKAGE);
459     tester.testInstanceMethods(RateLimiter.create(5.0, stopwatch), Visibility.PACKAGE);
460   }
461 
testVerySmallDoubleValues()462   public void testVerySmallDoubleValues() throws Exception {
463     RateLimiter rateLimiter = RateLimiter.create(Double.MIN_VALUE, stopwatch);
464     assertTrue("Should acquire initial permit", rateLimiter.tryAcquire());
465     assertFalse("Should not acquire additional permit", rateLimiter.tryAcquire());
466     stopwatch.sleepMillis(5000);
467     assertFalse(
468         "Should not acquire additional permit even after sleeping", rateLimiter.tryAcquire());
469   }
470 
measureTotalTimeMillis(RateLimiter rateLimiter, int permits, Random random)471   private long measureTotalTimeMillis(RateLimiter rateLimiter, int permits, Random random) {
472     long startTime = stopwatch.instant;
473     while (permits > 0) {
474       int nextPermitsToAcquire = Math.max(1, random.nextInt(permits));
475       permits -= nextPermitsToAcquire;
476       rateLimiter.acquire(nextPermitsToAcquire);
477     }
478     rateLimiter.acquire(1); // to repay for any pending debt
479     return NANOSECONDS.toMillis(stopwatch.instant - startTime);
480   }
481 
assertEvents(String... events)482   private void assertEvents(String... events) {
483     assertEquals(Arrays.toString(events), stopwatch.readEventsAndClear());
484   }
485 
486   /**
487    * The stopwatch gathers events and presents them as strings. R0.6 means a delay of 0.6 seconds
488    * caused by the (R)ateLimiter U1.0 means the (U)ser caused the stopwatch to sleep for a second.
489    */
490   static class FakeStopwatch extends SleepingStopwatch {
491     long instant = 0L;
492     final List<String> events = Lists.newArrayList();
493 
494     @Override
readMicros()495     public long readMicros() {
496       return NANOSECONDS.toMicros(instant);
497     }
498 
sleepMillis(int millis)499     void sleepMillis(int millis) {
500       sleepMicros("U", MILLISECONDS.toMicros(millis));
501     }
502 
sleepMicros(String caption, long micros)503     void sleepMicros(String caption, long micros) {
504       instant += MICROSECONDS.toNanos(micros);
505       events.add(caption + String.format(Locale.ROOT, "%3.2f", (micros / 1000000.0)));
506     }
507 
508     @Override
sleepMicrosUninterruptibly(long micros)509     protected void sleepMicrosUninterruptibly(long micros) {
510       sleepMicros("R", micros);
511     }
512 
readEventsAndClear()513     String readEventsAndClear() {
514       try {
515         return events.toString();
516       } finally {
517         events.clear();
518       }
519     }
520 
521     @Override
toString()522     public String toString() {
523       return events.toString();
524     }
525   }
526 
527   @AndroidIncompatible // Mockito loses its ability to mock doGetRate as of Android 21
testMockingMockito()528   public void testMockingMockito() throws Exception {
529     RateLimiter mock = Mockito.mock(RateLimiter.class);
530     for (Method method : RateLimiter.class.getMethods()) {
531       if (!isStatic(method.getModifiers())
532           && !NOT_WORKING_ON_MOCKS.contains(method.getName())
533           && !method.getDeclaringClass().equals(Object.class)) {
534         method.invoke(mock, arbitraryParameters(method));
535       }
536     }
537   }
538 
arbitraryParameters(Method method)539   private static Object[] arbitraryParameters(Method method) {
540     Class<?>[] parameterTypes = method.getParameterTypes();
541     Object[] params = new Object[parameterTypes.length];
542     for (int i = 0; i < parameterTypes.length; i++) {
543       params[i] = PARAMETER_VALUES.get(parameterTypes[i]);
544     }
545     return params;
546   }
547 
548   private static final ImmutableSet<String> NOT_WORKING_ON_MOCKS =
549       ImmutableSet.of("latestPermitAgeSec", "latestPermitAge", "setRate", "getAvailablePermits");
550 
551   // We would use ArbitraryInstances, but it returns 0, invalid for many RateLimiter methods.
552   private static final ImmutableClassToInstanceMap<Object> PARAMETER_VALUES =
553       ImmutableClassToInstanceMap.builder()
554           .put(int.class, 1)
555           .put(long.class, 1L)
556           .put(double.class, 1.0)
557           .put(TimeUnit.class, SECONDS)
558           .build();
559 }
560