/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 "TokenBucketTest.h"

#include <boost/optional/optional.hpp>
#include <stddef.h>
#include <algorithm>
#include <string>
#include <vector>

#include "gtest/gtest.h"
#include "utils/TokenBucket.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_SUITE_P(TokenBucket, TokenBucketTest, ::testing::ValuesIn(rateToConsumeSize));

TEST(TokenBucket, drainOnFail)
{
    DynamicTokenBucket tokenBucket;

    // Almost empty the bucket
    EXPECT_TRUE(tokenBucket.consume(9, 10, 10, 1));

    // Request more tokens than available
    EXPECT_FALSE(tokenBucket.consume(5, 10, 10, 1));
    EXPECT_DOUBLE_EQ(1.0, tokenBucket.available(10, 10, 1));

    // Again request more tokens than available, but ask to drain
    EXPECT_DOUBLE_EQ(1.0, tokenBucket.consumeOrDrain(5, 10, 10, 1));
    EXPECT_DOUBLE_EQ(0.0, tokenBucket.consumeOrDrain(1, 10, 10, 1));
}

TEST(TokenBucket, returnTokensTest)
{
    DynamicTokenBucket tokenBucket;

    // Empty the bucket.
    EXPECT_TRUE(tokenBucket.consume(10, 10, 10, 5));
    // consume should fail now.
    EXPECT_FALSE(tokenBucket.consume(1, 10, 10, 5));
    EXPECT_DOUBLE_EQ(0.0, tokenBucket.consumeOrDrain(1, 10, 10, 5));

    // Return tokens. Return 40 'excess' tokens but they wont be available to
    // later callers.
    tokenBucket.returnTokens(50, 10);
    // Should be able to allocate 10 tokens again but the extra 40 returned in
    // previous call are gone.
    EXPECT_TRUE(tokenBucket.consume(10, 10, 10, 5));
    EXPECT_FALSE(tokenBucket.consume(1, 10, 10, 5));
}

TEST(TokenBucket, consumeOrBorrowTest)
{
    DynamicTokenBucket tokenBucket;

    // Empty the bucket.
    EXPECT_TRUE(tokenBucket.consume(10, 10, 10, 1));
    // consume should fail now.
    EXPECT_FALSE(tokenBucket.consume(1, 10, 10, 1));
    // Now borrow from future allocations. Each call is asking for 1s worth of
    // allocations so it should return (i+1)*1s in the ith iteration as the time
    // caller needs to wait.
    for (int i = 0; i < 10; ++i) {
        auto waitTime = tokenBucket.consumeWithBorrowNonBlocking(10, 10, 10, 1);
        EXPECT_TRUE(waitTime.is_initialized());
        EXPECT_DOUBLE_EQ((i + 1) * 1.0, *waitTime);
    }

    // No allocation will succeed until nowInSeconds goes higher than 11s.
    EXPECT_FALSE(tokenBucket.consume(1, 10, 10, 11));
}
