blob: 65270e9f665a8b86ee2a2b97461dbf414d9dc671 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/reporting/util/rate_limiter_leaky_bucket.h"
#include <cstddef>
#include "base/rand_util.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace reporting {
namespace {
constexpr size_t kMaxLevel = 1024u;
constexpr base::TimeDelta kFillingTime = base::Seconds(16);
constexpr base::TimeDelta kFillingPeriod = base::Seconds(2);
constexpr size_t kEventCount = 8;
class RateLimiterLeakyBucketTest : public ::testing::Test {
protected:
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
RateLimiterLeakyBucket rate_limiter_{kMaxLevel, kFillingTime, kFillingPeriod};
};
TEST_F(RateLimiterLeakyBucketTest, SingularEvent) {
// Initially - not even 1-byte event can be accepted.
ASSERT_FALSE(rate_limiter_.Acquire(1u));
// Same when bucket is almost full.
task_environment_.FastForwardBy(kFillingTime - kFillingPeriod);
ASSERT_FALSE(rate_limiter_.Acquire(1u));
// Accept only once it is full.
task_environment_.FastForwardBy(kFillingPeriod);
ASSERT_TRUE(rate_limiter_.Acquire(kMaxLevel));
ASSERT_FALSE(rate_limiter_.Acquire(1u));
}
TEST_F(RateLimiterLeakyBucketTest, SteadyEventsStream) {
// Let the bucket fill in.
task_environment_.FastForwardBy(kFillingTime);
// Drop one event every `kFillingPeriod` sec,
// allowing one event through and no more.
for (size_t i = 0; i < kEventCount; ++i) {
ASSERT_TRUE(rate_limiter_.Acquire(1u));
ASSERT_FALSE(rate_limiter_.Acquire(1u));
// We only used 1 byte, will fill in again in 1 period.
task_environment_.FastForwardBy(kFillingPeriod);
}
}
TEST_F(RateLimiterLeakyBucketTest, RandomizedEventsStream) {
// Let the bucket fill in.
task_environment_.FastForwardBy(kFillingTime);
// Drop one event every `kFillingPeriod + random` sec,
// allowing one event through and no more.
for (size_t i = 0; i < kEventCount; ++i) {
ASSERT_TRUE(rate_limiter_.Acquire(1u));
ASSERT_FALSE(rate_limiter_.Acquire(1u));
// We only used 1 byte, will fill in again in 1 period, plus add a random.
task_environment_.FastForwardBy(kFillingPeriod +
base::Milliseconds(base::RandInt(0, 100)));
}
}
TEST_F(RateLimiterLeakyBucketTest, LargeEventsStream) {
// Let the bucket fill in.
task_environment_.FastForwardBy(kFillingTime);
// Drop one event every `kFillingTime` sec,
// allowing one event through and no more.
for (size_t i = 0; i < kEventCount; ++i) {
// See that it was enough for maximum event size, but no more.
ASSERT_TRUE(rate_limiter_.Acquire(kMaxLevel));
ASSERT_FALSE(rate_limiter_.Acquire(1u));
// `kFillingPeriod` is not sufficient now.
task_environment_.FastForwardBy(kFillingPeriod);
ASSERT_FALSE(rate_limiter_.Acquire(1u));
// Let the bucket fill in.
task_environment_.FastForwardBy(kFillingTime - kFillingPeriod);
}
}
} // namespace
} // namespace reporting