using namespace std::chrono_literals;
+TEST(RGWRateLimitEntry, compute_delay)
+{
+ // Disabled limit returns 0 regardless of the deficit
+ EXPECT_EQ(0, RateLimiterEntry::compute_delay(0, 0, 1));
+ EXPECT_EQ(0, RateLimiterEntry::compute_delay(0, 1, 1));
+ EXPECT_EQ(0, RateLimiterEntry::compute_delay(0, 1000, 1));
+ EXPECT_EQ(0, RateLimiterEntry::compute_delay(0, 1001, 1));
+ EXPECT_EQ(0, RateLimiterEntry::compute_delay(-1, 1000, 1));
+
+ // Zero or negative deficit returns 0 (caller treats as "no delay needed")
+ EXPECT_EQ(0, RateLimiterEntry::compute_delay(1000, 0, 1));
+ EXPECT_EQ(0, RateLimiterEntry::compute_delay(1000, -1, 1));
+ EXPECT_EQ(0, RateLimiterEntry::compute_delay(1000, -1000, 1));
+
+ // Ceil division at interval=1: tokens replenish at `limit` per second
+ EXPECT_EQ(1, RateLimiterEntry::compute_delay(1000, 1, 1));
+ EXPECT_EQ(1, RateLimiterEntry::compute_delay(1000, 1000, 1));
+ EXPECT_EQ(2, RateLimiterEntry::compute_delay(1000, 1001, 1));
+ EXPECT_EQ(2, RateLimiterEntry::compute_delay(1000, 2000, 1));
+ EXPECT_EQ(3, RateLimiterEntry::compute_delay(1000, 2001, 1));
+
+ // Ceil division at interval=100: tokens replenish at `limit` per 100s
+ EXPECT_EQ(0, RateLimiterEntry::compute_delay(10000, 0, 100));
+ EXPECT_EQ(1, RateLimiterEntry::compute_delay(10000, 1, 100));
+ EXPECT_EQ(1, RateLimiterEntry::compute_delay(10000, 100, 100));
+ EXPECT_EQ(2, RateLimiterEntry::compute_delay(10000, 101, 100));
+ EXPECT_EQ(2, RateLimiterEntry::compute_delay(10000, 200, 100));
+ EXPECT_EQ(3, RateLimiterEntry::compute_delay(10000, 201, 100));
+}
+
TEST(RGWRateLimit, op_limit_not_enabled)
{
// info.enabled = false, so no limit
RGWRateLimitInfo info;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("PUT", key, time, &info, "");
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("PUT", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, reject_op_over_limit)
{
- // check that request is being rejected because there are not enough tokens
+ // check that request is being rejected because there are not enough tokens,
+ // and that the returned delay matches the configured interval (default 60s)
+ // when the user is exactly one token short.
std::atomic_bool replacing;
std::condition_variable cv;
RateLimiter ratelimit(g_ceph_context, replacing, cv);
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(true, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(60, delay);
}
TEST(RGWRateLimit, accept_op_after_giveback)
{
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
ratelimit.giveback_tokens("GET", key, "", &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, accept_op_after_refill)
{
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
time += 61s;
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, reject_bw_over_limit)
{
info.max_read_bytes = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
ratelimit.decrease_bytes("GET",key, 2, &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(true, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimit, accept_bw)
{
info.max_read_bytes = 2;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
ratelimit.decrease_bytes("GET",key, 1, &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, check_bw_debt_at_max_120secs)
{
info.max_read_bytes = 2;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
ratelimit.decrease_bytes("GET",key, 100, &info);
time += 121s;
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, check_that_bw_limit_not_affect_ops)
{
info.max_read_bytes = 100000000;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
ratelimit.decrease_bytes("GET",key, 10000, &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(true, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimit, read_limit_does_not_affect_writes)
{
info.max_read_bytes = 100000000;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("PUT", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("PUT", key, time, &info, "");
ratelimit.decrease_bytes("PUT",key, 10000, &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("PUT", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("PUT", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, write_limit_does_not_affect_reads)
{
info.max_write_bytes = 100000000;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
ratelimit.decrease_bytes("GET",key, 10000, &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, allow_unlimited_access)
info.enabled = true;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser123";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, unlimited_access_not_left_large_read_ops_budget)
for (int i = 0; i < 10; i++)
{
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
time += 61s;
info.max_read_ops = 1; // make read ops limited
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, unlimited_access_not_left_large_write_ops_budget)
for (int i = 0; i < 10; i++)
{
- bool success = ratelimit.should_rate_limit("PUT", key, time, &info, "");
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("PUT", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
time += 61s;
info.max_write_ops = 1; // make write ops limited
- bool success = ratelimit.should_rate_limit("PUT", key, time, &info, "");
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("PUT", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitGC, NO_GC_AHEAD_OF_TIME)
RateLimiterEntry entry;
RGWRateLimitInfo info;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(false, success);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, reject_op_over_limit)
{
- // check that request is being rejected because there are not enough tokens
-
+ // check that request is being rejected because there are not enough tokens,
+ // and that the returned delay matches the configured interval (default 60s)
+ // when the user is exactly one token short.
RGWRateLimitInfo info;
RateLimiterEntry entry;
info.enabled = true;
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(true, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(60, delay);
}
TEST(RGWRateLimitEntry, accept_op_after_giveback)
{
info.enabled = true;
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
entry.giveback_tokens(OpType::Read);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, accept_op_after_refill)
{
info.enabled = true;
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
time += 61s;
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, reject_bw_over_limit)
{
info.enabled = true;
info.max_read_bytes = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
entry.decrease_bytes(true, 2, &info);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(true, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimitEntry, accept_bw)
{
info.enabled = true;
info.max_read_bytes = 2;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
entry.decrease_bytes(true, 1, &info);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, check_bw_debt_at_max_120secs)
{
info.enabled = true;
info.max_read_bytes = 2;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
entry.decrease_bytes(true, 100, &info);
time += 121s;
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, check_that_bw_limit_not_affect_ops)
{
info.max_read_ops = 1;
info.max_read_bytes = 100000000;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
entry.decrease_bytes(true, 10000, &info);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(true, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimitEntry, read_limit_does_not_affect_writes)
{
info.max_read_ops = 1;
info.max_read_bytes = 100000000;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Write, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Write, &info, time);
entry.decrease_bytes(false, 10000, &info);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Write, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Write, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, write_limit_does_not_affect_reads)
{
info.max_write_bytes = 100000000;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
std::string key = "uuser123";
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
entry.decrease_bytes(true, 10000, &info);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, allow_unlimited_access)
RGWRateLimitInfo info;
info.enabled = true;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(false, success);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(0, delay);
}
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
- EXPECT_EQ(true, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimit, accept_list_op_after_giveback)
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
ratelimit.giveback_tokens("GET", key, RES_LIST_TYPE_2, &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, accept_list_op_after_refill)
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
time += 61s;
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, list_limit_does_not_affect_reads)
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
// Should still be able to do a normal GET (read)
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, read_limit_does_not_affect_lists)
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
// Should still be able to do a LIST op
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, list_limit_does_not_affect_writes)
info.max_write_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
// Should still be able to do a PUT (write)
- success = ratelimit.should_rate_limit("PUT", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("PUT", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, unlimited_access_not_left_large_list_ops_budget)
for (int i = 0; i < 10; i++)
{
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ EXPECT_EQ(0, delay);
}
time += 61s;
info.max_list_ops = 1; // make list ops limited
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, write_limit_does_not_affect_lists)
info.max_write_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("PUT", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("PUT", key, time, &info, "");
// Should still be able to do a LIST op
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, list_limit_does_not_affect_deletes)
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
// Should still be able to do a DELETE op
- success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, delete_limit_does_not_affect_lists)
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
// Should still be able to do a LIST op
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_LIST_TYPE_2);
+ EXPECT_EQ(0, delay);
}
// LIST RES_DELIMITER minimal tests
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
- EXPECT_EQ(true, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimit, accept_delimiter_op_after_giveback)
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
ratelimit.giveback_tokens("GET", key, RES_DELIMITER, &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, accept_delimiter_op_after_refill)
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
time += 61s;
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_DELIMITER);
+ EXPECT_EQ(0, delay);
}
// LIST RES_PREFIX minimal tests
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
- EXPECT_EQ(true, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimit, accept_prefix_op_after_giveback)
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
ratelimit.giveback_tokens("GET", key, RES_PREFIX, &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, accept_prefix_op_after_refill)
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_list";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
time += 61s;
- success = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, RES_PREFIX);
+ EXPECT_EQ(0, delay);
}
info.enabled = true;
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::List, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::List, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::List, &info, time);
- EXPECT_EQ(true, success);
+ delay = entry.should_rate_limit(OpType::List, &info, time);
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimitEntry, accept_list_op_after_giveback)
info.enabled = true;
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::List, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::List, &info, time);
entry.giveback_tokens(OpType::List);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::List, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::List, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, accept_list_op_after_refill)
info.enabled = true;
info.max_list_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::List, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::List, &info, time);
time += 61s;
- success = entry.should_rate_limit(OpType::List, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::List, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, list_limit_does_not_affect_reads)
info.max_list_ops = 1;
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::List, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::List, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, read_limit_does_not_affect_lists)
info.max_list_ops = 1;
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::List, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::List, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, list_limit_does_not_affect_writes)
info.max_list_ops = 1;
info.max_write_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::List, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::List, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Write, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Write, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, write_limit_does_not_affect_lists)
info.max_list_ops = 1;
info.max_write_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Write, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Write, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::List, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::List, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, list_limit_does_not_affect_deletes)
info.max_list_ops = 1;
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::List, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::List, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Delete, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Delete, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, delete_limit_does_not_affect_lists)
info.max_list_ops = 1;
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Delete, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Delete, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::List, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::List, &info, time);
+ EXPECT_EQ(0, delay);
}
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_delete";
- bool success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
- EXPECT_EQ(true, success);
+ delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimit, accept_delete_op_after_giveback)
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_delete";
- bool success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
ratelimit.giveback_tokens("DELETE", key, "", &info);
time = ceph::coarse_real_clock::now();
- success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, accept_delete_op_after_refill)
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_delete";
- bool success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
time += 61s;
- success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, delete_limit_does_not_affect_reads)
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_delete";
- bool success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
// Should still be able to do a normal GET (read)
- success = ratelimit.should_rate_limit("GET", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, read_limit_does_not_affect_deletes)
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_delete";
- bool success = ratelimit.should_rate_limit("GET", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("GET", key, time, &info, "");
// Should still be able to do a DELETE op
- success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, write_limit_does_not_affect_deletes)
info.max_write_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_delete";
- bool success = ratelimit.should_rate_limit("PUT", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("PUT", key, time, &info, "");
// Should still be able to do a DELETE op
- success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, delete_limit_does_not_affect_writes)
info.max_write_ops = 1;
auto time = ceph::coarse_real_clock::now();
std::string key = "uuser_delete";
- bool success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ int64_t delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
// Should still be able to do a PUT (write)
- success = ratelimit.should_rate_limit("PUT", key, time, &info, "");
- EXPECT_EQ(false, success);
+ delay = ratelimit.should_rate_limit("PUT", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimit, unlimited_access_not_left_large_delete_ops_budget)
for (int i = 0; i < 10; i++)
{
- bool success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
time += 61s;
info.max_delete_ops = 1; // make delete ops limited
- bool success = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
- EXPECT_EQ(false, success);
+ int64_t delay = ratelimit.should_rate_limit("DELETE", key, time, &info, "");
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, reject_delete_op_over_limit)
info.enabled = true;
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Delete, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Delete, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Delete, &info, time);
- EXPECT_EQ(true, success);
+ delay = entry.should_rate_limit(OpType::Delete, &info, time);
+ EXPECT_GT(delay, 0);
}
TEST(RGWRateLimitEntry, accept_delete_op_after_giveback)
info.enabled = true;
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Delete, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Delete, &info, time);
entry.giveback_tokens(OpType::Delete);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Delete, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Delete, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, accept_delete_op_after_refill)
info.enabled = true;
info.max_delete_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Delete, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Delete, &info, time);
time += 61s;
- success = entry.should_rate_limit(OpType::Delete, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Delete, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, delete_limit_does_not_affect_reads)
info.max_delete_ops = 1;
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Delete, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Delete, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Read, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Read, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, read_limit_does_not_affect_deletes)
info.max_delete_ops = 1;
info.max_read_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Read, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Read, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Delete, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Delete, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, write_limit_does_not_affect_deletes)
info.max_delete_ops = 1;
info.max_write_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Write, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Write, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Delete, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Delete, &info, time);
+ EXPECT_EQ(0, delay);
}
TEST(RGWRateLimitEntry, delete_limit_does_not_affect_writes)
info.max_delete_ops = 1;
info.max_write_ops = 1;
auto time = ceph::coarse_real_clock::now().time_since_epoch();
- bool success = entry.should_rate_limit(OpType::Delete, &info, time);
+ int64_t delay = entry.should_rate_limit(OpType::Delete, &info, time);
time = ceph::coarse_real_clock::now().time_since_epoch();
- success = entry.should_rate_limit(OpType::Write, &info, time);
- EXPECT_EQ(false, success);
+ delay = entry.should_rate_limit(OpType::Write, &info, time);
+ EXPECT_EQ(0, delay);
}