2 * Copyright 2016 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <folly/test/TokenBucketTest.h>
19 #include <gtest/gtest.h>
21 using namespace folly;
23 TEST(TokenBucket, ReverseTime) {
24 const double rate = 1000;
25 TokenBucket tokenBucket(rate, rate * 0.01 + 1e-6, 0);
27 while (tokenBucket.consume(1, 0.1)) {
31 // Going backwards in time has no affect on the toke count (this protects
32 // against different threads providing out of order timestamps).
33 double tokensBefore = tokenBucket.available();
34 EXPECT_FALSE(tokenBucket.consume(1, 0.09999999));
35 EXPECT_EQ(tokensBefore, tokenBucket.available());
38 TEST_P(TokenBucketTest, sanity) {
39 std::pair<double, double> params = GetParam();
40 double rate = params.first;
41 double consumeSize = params.second;
43 const double tenMillisecondBurst = rate * 0.010;
44 // Select a burst size of 10 milliseconds at the max rate or the consume size
45 // if 10 ms at rate is too small.
46 const double burstSize = std::max(consumeSize, tenMillisecondBurst);
47 TokenBucket tokenBucket(rate, burstSize, 0);
48 double tokenCounter = 0;
49 double currentTime = 0;
50 // Simulate time advancing 10 seconds
51 for (; currentTime <= 10.0; currentTime += 0.001) {
52 EXPECT_FALSE(tokenBucket.consume(burstSize + 1, currentTime));
53 while (tokenBucket.consume(consumeSize, currentTime)) {
54 tokenCounter += consumeSize;
56 // Tokens consumed should exceed some lower bound based on rate.
57 // Note: The token bucket implementation is not precise, so the lower bound
58 // is somewhat fudged. The upper bound is accurate however.
59 EXPECT_LE(rate * currentTime * 0.9 - 1, tokenCounter);
60 // Tokens consumed should not exceed some upper bound based on rate.
61 EXPECT_GE(rate * currentTime + 1e-6, tokenCounter);
65 static std::vector<std::pair<double, double> > rateToConsumeSize = {
72 INSTANTIATE_TEST_CASE_P(TokenBucket,
74 ::testing::ValuesIn(rateToConsumeSize));