]> git.proxmox.com Git - ceph.git/blob - 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
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>
5 #include "rgw_ratelimit.h"
6
7
8 using namespace std::chrono_literals;
9
10 TEST(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 }
22 TEST(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 }
38 TEST(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 }
55 TEST(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 }
71 TEST(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 }
88 TEST(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 }
105 TEST(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 }
122 TEST(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 }
140 TEST(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 }
158 TEST(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
177 TEST(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
191 TEST(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 }
206 TEST(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
228 TEST(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 }
237 TEST(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 }
251 TEST(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 }
265 TEST(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 }
278 TEST(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 }
292 TEST(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 }
306 TEST(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 }
320 TEST(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 }
335 TEST(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 }
350 TEST(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
367 TEST(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 }