blob: 1709913e807a412886519af7ac5f939ba3dec400 [file] [log] [blame]
/*
* Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/test/TokenBucketTest.h>
#include <gtest/gtest.h>
using namespace folly;
TEST(TokenBucket, ReverseTime) {
const double rate = 1000;
TokenBucket tokenBucket(rate, rate * 0.01 + 1e-6, 0);
size_t count = 0;
while (tokenBucket.consume(1, 0.1)) {
count += 1;
}
EXPECT_EQ(10, count);
// Going backwards in time has no affect on the toke count (this protects
// against different threads providing out of order timestamps).
double tokensBefore = tokenBucket.available();
EXPECT_FALSE(tokenBucket.consume(1, 0.09999999));
EXPECT_EQ(tokensBefore, tokenBucket.available());
}
TEST_P(TokenBucketTest, sanity) {
std::pair<double, double> params = GetParam();
double rate = params.first;
double consumeSize = params.second;
const double tenMillisecondBurst = rate * 0.010;
// Select a burst size of 10 milliseconds at the max rate or the consume size
// if 10 ms at rate is too small.
const double burstSize = std::max(consumeSize, tenMillisecondBurst);
TokenBucket tokenBucket(rate, burstSize, 0);
double tokenCounter = 0;
double currentTime = 0;
// Simulate time advancing 10 seconds
for (; currentTime <= 10.0; currentTime += 0.001) {
EXPECT_FALSE(tokenBucket.consume(burstSize + 1, currentTime));
while (tokenBucket.consume(consumeSize, currentTime)) {
tokenCounter += consumeSize;
}
// Tokens consumed should exceed some lower bound based on rate.
// Note: The token bucket implementation is not precise, so the lower bound
// is somewhat fudged. The upper bound is accurate however.
EXPECT_LE(rate * currentTime * 0.9 - 1, tokenCounter);
// Tokens consumed should not exceed some upper bound based on rate.
EXPECT_GE(rate * currentTime + 1e-6, tokenCounter);
}
}
static std::vector<std::pair<double, double> > rateToConsumeSize = {
{100, 1},
{1000, 1},
{10000, 1},
{10000, 5},
};
INSTANTIATE_TEST_CASE_P(TokenBucket,
TokenBucketTest,
::testing::ValuesIn(rateToConsumeSize));