]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/rgw/test_rgw_ratelimit.cc
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / test / rgw / test_rgw_ratelimit.cc
CommitLineData
20effc67
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab ft=cpp
3
4#include <gtest/gtest.h>
1e59de90 5#include "rgw_ratelimit.h"
20effc67
TL
6
7
8using namespace std::chrono_literals;
9
10TEST(RGWRateLimit, op_limit_not_enabled)
11{
12 // info.enabled = false, so no limit
13 std::atomic_bool replacing;
14 std::condition_variable cv;
15 RateLimiter ratelimit(replacing, cv);
16 RGWRateLimitInfo info;
17 auto time = ceph::coarse_real_clock::now();
18 std::string key = "uuser123";
19 bool success = ratelimit.should_rate_limit("PUT", key, time, &info);
20 EXPECT_EQ(false, success);
21}
22TEST(RGWRateLimit, reject_op_over_limit)
23{
24 // check that request is being rejected because there are not enough tokens
25 std::atomic_bool replacing;
26 std::condition_variable cv;
27 RateLimiter ratelimit(replacing, cv);
28 RGWRateLimitInfo info;
29 info.enabled = true;
30 info.max_read_ops = 1;
31 auto time = ceph::coarse_real_clock::now();
32 std::string key = "uuser123";
33 bool success = ratelimit.should_rate_limit("GET", key, time, &info);
34 time = ceph::coarse_real_clock::now();
35 success = ratelimit.should_rate_limit("GET", key, time, &info);
36 EXPECT_EQ(true, success);
37}
38TEST(RGWRateLimit, accept_op_after_giveback)
39{
40 // check that giveback is working fine
41 std::atomic_bool replacing;
42 std::condition_variable cv;
43 RateLimiter ratelimit(replacing, cv);
44 RGWRateLimitInfo info;
45 info.enabled = true;
46 info.max_read_ops = 1;
47 auto time = ceph::coarse_real_clock::now();
48 std::string key = "uuser123";
49 bool success = ratelimit.should_rate_limit("GET", key, time, &info);
50 ratelimit.giveback_tokens("GET", key);
51 time = ceph::coarse_real_clock::now();
52 success = ratelimit.should_rate_limit("GET", key, time, &info);
53 EXPECT_EQ(false, success);
54}
55TEST(RGWRateLimit, accept_op_after_refill)
56{
57 // check that tokens are being filled properly
58 std::atomic_bool replacing;
59 std::condition_variable cv;
60 RateLimiter ratelimit(replacing, cv);
61 RGWRateLimitInfo info;
62 info.enabled = true;
63 info.max_read_ops = 1;
64 auto time = ceph::coarse_real_clock::now();
65 std::string key = "uuser123";
66 bool success = ratelimit.should_rate_limit("GET", key, time, &info);
67 time += 61s;
68 success = ratelimit.should_rate_limit("GET", key, time, &info);
69 EXPECT_EQ(false, success);
70}
71TEST(RGWRateLimit, reject_bw_over_limit)
72{
73 // check that a newer request is rejected if there is no enough tokens (bw)
74 std::atomic_bool replacing;
75 std::condition_variable cv;
76 RateLimiter ratelimit(replacing, cv);
77 RGWRateLimitInfo info;
78 info.enabled = true;
79 info.max_read_bytes = 1;
80 auto time = ceph::coarse_real_clock::now();
81 std::string key = "uuser123";
82 bool success = ratelimit.should_rate_limit("GET", key, time, &info);
83 ratelimit.decrease_bytes("GET",key, 2, &info);
84 time = ceph::coarse_real_clock::now();
85 success = ratelimit.should_rate_limit("GET", key, time, &info);
86 EXPECT_EQ(true, success);
87}
88TEST(RGWRateLimit, accept_bw)
89{
90 // check that when there are enough tokens (bw) the request is still being served
91 std::atomic_bool replacing;
92 std::condition_variable cv;
93 RateLimiter ratelimit(replacing, cv);
94 RGWRateLimitInfo info;
95 info.enabled = true;
96 info.max_read_bytes = 2;
97 auto time = ceph::coarse_real_clock::now();
98 std::string key = "uuser123";
99 bool success = ratelimit.should_rate_limit("GET", key, time, &info);
100 ratelimit.decrease_bytes("GET",key, 1, &info);
101 time = ceph::coarse_real_clock::now();
102 success = ratelimit.should_rate_limit("GET", key, time, &info);
103 EXPECT_EQ(false, success);
104}
105TEST(RGWRateLimit, check_bw_debt_at_max_120secs)
106{
107 // check that the bandwidth debt is not larger than 120 seconds
108 std::atomic_bool replacing;
109 std::condition_variable cv;
110 RateLimiter ratelimit(replacing, cv);
111 RGWRateLimitInfo info;
112 info.enabled = true;
113 info.max_read_bytes = 2;
114 auto time = ceph::coarse_real_clock::now();
115 std::string key = "uuser123";
116 bool success = ratelimit.should_rate_limit("GET", key, time, &info);
117 ratelimit.decrease_bytes("GET",key, 100, &info);
118 time += 121s;
119 success = ratelimit.should_rate_limit("GET", key, time, &info);
120 EXPECT_EQ(false, success);
121}
122TEST(RGWRateLimit, check_that_bw_limit_not_affect_ops)
123{
124 // check that high read bytes limit, does not affect ops limit
125 std::atomic_bool replacing;
126 std::condition_variable cv;
127 RateLimiter ratelimit(replacing, cv);
128 RGWRateLimitInfo info;
129 info.enabled = true;
130 info.max_read_ops = 1;
131 info.max_read_bytes = 100000000;
132 auto time = ceph::coarse_real_clock::now();
133 std::string key = "uuser123";
134 bool success = ratelimit.should_rate_limit("GET", key, time, &info);
135 ratelimit.decrease_bytes("GET",key, 10000, &info);
136 time = ceph::coarse_real_clock::now();
137 success = ratelimit.should_rate_limit("GET", key, time, &info);
138 EXPECT_EQ(true, success);
139}
140TEST(RGWRateLimit, read_limit_does_not_affect_writes)
141{
142 // read limit does not affect writes
143 std::atomic_bool replacing;
144 std::condition_variable cv;
145 RateLimiter ratelimit(replacing, cv);
146 RGWRateLimitInfo info;
147 info.enabled = true;
148 info.max_read_ops = 1;
149 info.max_read_bytes = 100000000;
150 auto time = ceph::coarse_real_clock::now();
151 std::string key = "uuser123";
152 bool success = ratelimit.should_rate_limit("PUT", key, time, &info);
153 ratelimit.decrease_bytes("PUT",key, 10000, &info);
154 time = ceph::coarse_real_clock::now();
155 success = ratelimit.should_rate_limit("PUT", key, time, &info);
156 EXPECT_EQ(false, success);
157}
158TEST(RGWRateLimit, write_limit_does_not_affect_reads)
159{
160 // write limit does not affect reads
161 std::atomic_bool replacing;
162 std::condition_variable cv;
163 RateLimiter ratelimit(replacing, cv);
164 RGWRateLimitInfo info;
165 info.enabled = true;
166 info.max_write_ops = 1;
167 info.max_write_bytes = 100000000;
168 auto time = ceph::coarse_real_clock::now();
169 std::string key = "uuser123";
170 bool success = ratelimit.should_rate_limit("GET", key, time, &info);
171 ratelimit.decrease_bytes("GET",key, 10000, &info);
172 time = ceph::coarse_real_clock::now();
173 success = ratelimit.should_rate_limit("GET", key, time, &info);
174 EXPECT_EQ(false, success);
175}
176
177TEST(RGWRateLimit, allow_unlimited_access)
178{
179 // 0 values in RGWRateLimitInfo should allow unlimited access
180 std::atomic_bool replacing;
181 std::condition_variable cv;
182 RateLimiter ratelimit(replacing, cv);
183 RGWRateLimitInfo info;
184 info.enabled = true;
185 auto time = ceph::coarse_real_clock::now();
186 std::string key = "uuser123";
187 bool success = ratelimit.should_rate_limit("GET", key, time, &info);
188 EXPECT_EQ(false, success);
189}
190
191TEST(RGWRateLimitGC, NO_GC_AHEAD_OF_TIME)
192{
193 // Test if GC is not starting the replace before getting to map_size * 0.9
194 // Please make sure to change those values when you change the map_size in the code
195
196 std::shared_ptr<ActiveRateLimiter> ratelimit(new ActiveRateLimiter(g_ceph_context));
197 ratelimit->start();
198 auto active = ratelimit->get_active();
199 RGWRateLimitInfo info;
200 auto time = ceph::coarse_real_clock::now();
201 std::string key = "uuser123";
202 active->should_rate_limit("GET", key, time, &info);
203 auto activegc = ratelimit->get_active();
204 EXPECT_EQ(activegc, active);
205}
206TEST(RGWRateLimiterGC, GC_IS_WORKING)
207{
208 // Test if GC is replacing the active RateLimiter
209 // Please make sure to change those values when you change the map_size in the code
210
211 std::shared_ptr<ActiveRateLimiter> ratelimit(new ActiveRateLimiter(g_ceph_context));
212 ratelimit->start();
213 auto active = ratelimit->get_active();
214 RGWRateLimitInfo info;
215 info.enabled = true;
216 auto time = ceph::coarse_real_clock::now();
217 std::string key = "-1";
218 for(int i = 0; i < 2000000; i++)
219 {
220 active->should_rate_limit("GET", key, time, &info);
221 key = std::to_string(i);
222 }
223 auto activegc = ratelimit->get_active();
224 EXPECT_NE(activegc, active);
225}
226
227
228TEST(RGWRateLimitEntry, op_limit_not_enabled)
229{
230 // info.enabled = false, so no limit
231 RateLimiterEntry entry;
232 RGWRateLimitInfo info;
233 auto time = ceph::coarse_real_clock::now().time_since_epoch();
234 bool success = entry.should_rate_limit(false, &info, time);
235 EXPECT_EQ(false, success);
236}
237TEST(RGWRateLimitEntry, reject_op_over_limit)
238{
239 // check that request is being rejected because there are not enough tokens
240
241 RGWRateLimitInfo info;
242 RateLimiterEntry entry;
243 info.enabled = true;
244 info.max_read_ops = 1;
245 auto time = ceph::coarse_real_clock::now().time_since_epoch();
246 bool success = entry.should_rate_limit(true, &info, time);
247 time = ceph::coarse_real_clock::now().time_since_epoch();
248 success = entry.should_rate_limit(true, &info, time);
249 EXPECT_EQ(true, success);
250}
251TEST(RGWRateLimitEntry, accept_op_after_giveback)
252{
253 // check that giveback is working fine
254 RGWRateLimitInfo info;
255 RateLimiterEntry entry;
256 info.enabled = true;
257 info.max_read_ops = 1;
258 auto time = ceph::coarse_real_clock::now().time_since_epoch();
259 bool success = entry.should_rate_limit(true, &info, time);
260 entry.giveback_tokens(true);
261 time = ceph::coarse_real_clock::now().time_since_epoch();
262 success = entry.should_rate_limit(true, &info, time);
263 EXPECT_EQ(false, success);
264}
265TEST(RGWRateLimitEntry, accept_op_after_refill)
266{
267 // check that tokens are being filled properly
268 RateLimiterEntry entry;
269 RGWRateLimitInfo info;
270 info.enabled = true;
271 info.max_read_ops = 1;
272 auto time = ceph::coarse_real_clock::now().time_since_epoch();
273 bool success = entry.should_rate_limit(true, &info, time);
274 time += 61s;
275 success = entry.should_rate_limit(true, &info, time);
276 EXPECT_EQ(false, success);
277}
278TEST(RGWRateLimitEntry, reject_bw_over_limit)
279{
280 // check that a newer request is rejected if there is no enough tokens (bw)
281 RateLimiterEntry entry;
282 RGWRateLimitInfo info;
283 info.enabled = true;
284 info.max_read_bytes = 1;
285 auto time = ceph::coarse_real_clock::now().time_since_epoch();
286 bool success = entry.should_rate_limit(true, &info, time);
287 entry.decrease_bytes(true, 2, &info);
288 time = ceph::coarse_real_clock::now().time_since_epoch();
289 success = entry.should_rate_limit(true, &info, time);
290 EXPECT_EQ(true, success);
291}
292TEST(RGWRateLimitEntry, accept_bw)
293{
294 // check that when there are enough tokens (bw) the request is still being served
295 RateLimiterEntry entry;
296 RGWRateLimitInfo info;
297 info.enabled = true;
298 info.max_read_bytes = 2;
299 auto time = ceph::coarse_real_clock::now().time_since_epoch();
300 bool success = entry.should_rate_limit(true, &info, time);
301 entry.decrease_bytes(true, 1, &info);
302 time = ceph::coarse_real_clock::now().time_since_epoch();
303 success = entry.should_rate_limit(true, &info, time);
304 EXPECT_EQ(false, success);
305}
306TEST(RGWRateLimitEntry, check_bw_debt_at_max_120secs)
307{
308 // check that the bandwidth debt is not larger than 120 seconds
309 RateLimiterEntry entry;
310 RGWRateLimitInfo info;
311 info.enabled = true;
312 info.max_read_bytes = 2;
313 auto time = ceph::coarse_real_clock::now().time_since_epoch();
314 bool success = entry.should_rate_limit(true, &info, time);
315 entry.decrease_bytes(true, 100, &info);
316 time += 121s;
317 success = entry.should_rate_limit(true, &info, time);
318 EXPECT_EQ(false, success);
319}
320TEST(RGWRateLimitEntry, check_that_bw_limit_not_affect_ops)
321{
322 // check that high read bytes limit, does not affect ops limit
323 RateLimiterEntry entry;
324 RGWRateLimitInfo info;
325 info.enabled = true;
326 info.max_read_ops = 1;
327 info.max_read_bytes = 100000000;
328 auto time = ceph::coarse_real_clock::now().time_since_epoch();
329 bool success = entry.should_rate_limit(true, &info, time);
330 entry.decrease_bytes(true, 10000, &info);
331 time = ceph::coarse_real_clock::now().time_since_epoch();
332 success = entry.should_rate_limit(true, &info, time);
333 EXPECT_EQ(true, success);
334}
335TEST(RGWRateLimitEntry, read_limit_does_not_affect_writes)
336{
337 // read limit does not affect writes
338 RateLimiterEntry entry;
339 RGWRateLimitInfo info;
340 info.enabled = true;
341 info.max_read_ops = 1;
342 info.max_read_bytes = 100000000;
343 auto time = ceph::coarse_real_clock::now().time_since_epoch();
344 bool success = entry.should_rate_limit(false, &info, time);
345 entry.decrease_bytes(false, 10000, &info);
346 time = ceph::coarse_real_clock::now().time_since_epoch();
347 success = entry.should_rate_limit(false, &info, time);
348 EXPECT_EQ(false, success);
349}
350TEST(RGWRateLimitEntry, write_limit_does_not_affect_reads)
351{
352 // write limit does not affect reads
353 RateLimiterEntry entry;
354 RGWRateLimitInfo info;
355 info.enabled = true;
356 info.max_write_ops = 1;
357 info.max_write_bytes = 100000000;
358 auto time = ceph::coarse_real_clock::now().time_since_epoch();
359 std::string key = "uuser123";
360 bool success = entry.should_rate_limit(true, &info, time);
361 entry.decrease_bytes(true, 10000, &info);
362 time = ceph::coarse_real_clock::now().time_since_epoch();
363 success = entry.should_rate_limit(true, &info, time);
364 EXPECT_EQ(false, success);
365}
366
367TEST(RGWRateLimitEntry, allow_unlimited_access)
368{
369 // 0 values in RGWRateLimitInfo should allow unlimited access (default value)
370 RateLimiterEntry entry;
371 RGWRateLimitInfo info;
372 info.enabled = true;
373 auto time = ceph::coarse_real_clock::now().time_since_epoch();
374 bool success = entry.should_rate_limit(true, &info, time);
375 EXPECT_EQ(false, success);
376}