1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 #include <gtest/gtest.h>
5 #include "rgw_ratelimit.h"
8 using namespace std::chrono_literals
;
10 TEST(RGWRateLimit
, op_limit_not_enabled
)
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
);
22 TEST(RGWRateLimit
, reject_op_over_limit
)
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
;
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
);
38 TEST(RGWRateLimit
, accept_op_after_giveback
)
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
;
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
);
55 TEST(RGWRateLimit
, accept_op_after_refill
)
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
;
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
);
68 success
= ratelimit
.should_rate_limit("GET", key
, time
, &info
);
69 EXPECT_EQ(false, success
);
71 TEST(RGWRateLimit
, reject_bw_over_limit
)
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
;
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
);
88 TEST(RGWRateLimit
, accept_bw
)
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
;
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
);
105 TEST(RGWRateLimit
, check_bw_debt_at_max_120secs
)
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
;
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
);
119 success
= ratelimit
.should_rate_limit("GET", key
, time
, &info
);
120 EXPECT_EQ(false, success
);
122 TEST(RGWRateLimit
, check_that_bw_limit_not_affect_ops
)
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
;
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
);
140 TEST(RGWRateLimit
, read_limit_does_not_affect_writes
)
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
;
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
);
158 TEST(RGWRateLimit
, write_limit_does_not_affect_reads
)
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
;
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
);
177 TEST(RGWRateLimit
, allow_unlimited_access
)
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
;
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
);
191 TEST(RGWRateLimitGC
, NO_GC_AHEAD_OF_TIME
)
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
196 std::shared_ptr
<ActiveRateLimiter
> ratelimit(new ActiveRateLimiter(g_ceph_context
));
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
);
206 TEST(RGWRateLimiterGC
, GC_IS_WORKING
)
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
211 std::shared_ptr
<ActiveRateLimiter
> ratelimit(new ActiveRateLimiter(g_ceph_context
));
213 auto active
= ratelimit
->get_active();
214 RGWRateLimitInfo info
;
216 auto time
= ceph::coarse_real_clock::now();
217 std::string key
= "-1";
218 for(int i
= 0; i
< 2000000; i
++)
220 active
->should_rate_limit("GET", key
, time
, &info
);
221 key
= std::to_string(i
);
223 auto activegc
= ratelimit
->get_active();
224 EXPECT_NE(activegc
, active
);
228 TEST(RGWRateLimitEntry
, op_limit_not_enabled
)
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
);
237 TEST(RGWRateLimitEntry
, reject_op_over_limit
)
239 // check that request is being rejected because there are not enough tokens
241 RGWRateLimitInfo info
;
242 RateLimiterEntry entry
;
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
);
251 TEST(RGWRateLimitEntry
, accept_op_after_giveback
)
253 // check that giveback is working fine
254 RGWRateLimitInfo info
;
255 RateLimiterEntry entry
;
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
);
265 TEST(RGWRateLimitEntry
, accept_op_after_refill
)
267 // check that tokens are being filled properly
268 RateLimiterEntry entry
;
269 RGWRateLimitInfo info
;
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
);
275 success
= entry
.should_rate_limit(true, &info
, time
);
276 EXPECT_EQ(false, success
);
278 TEST(RGWRateLimitEntry
, reject_bw_over_limit
)
280 // check that a newer request is rejected if there is no enough tokens (bw)
281 RateLimiterEntry entry
;
282 RGWRateLimitInfo info
;
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
);
292 TEST(RGWRateLimitEntry
, accept_bw
)
294 // check that when there are enough tokens (bw) the request is still being served
295 RateLimiterEntry entry
;
296 RGWRateLimitInfo info
;
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
);
306 TEST(RGWRateLimitEntry
, check_bw_debt_at_max_120secs
)
308 // check that the bandwidth debt is not larger than 120 seconds
309 RateLimiterEntry entry
;
310 RGWRateLimitInfo info
;
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
);
317 success
= entry
.should_rate_limit(true, &info
, time
);
318 EXPECT_EQ(false, success
);
320 TEST(RGWRateLimitEntry
, check_that_bw_limit_not_affect_ops
)
322 // check that high read bytes limit, does not affect ops limit
323 RateLimiterEntry entry
;
324 RGWRateLimitInfo info
;
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
);
335 TEST(RGWRateLimitEntry
, read_limit_does_not_affect_writes
)
337 // read limit does not affect writes
338 RateLimiterEntry entry
;
339 RGWRateLimitInfo info
;
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
);
350 TEST(RGWRateLimitEntry
, write_limit_does_not_affect_reads
)
352 // write limit does not affect reads
353 RateLimiterEntry entry
;
354 RGWRateLimitInfo info
;
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
);
367 TEST(RGWRateLimitEntry
, allow_unlimited_access
)
369 // 0 values in RGWRateLimitInfo should allow unlimited access (default value)
370 RateLimiterEntry entry
;
371 RGWRateLimitInfo info
;
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
);