109
115
return ratelimit.RateLimitMiddleware(app, conf, logger=FakeLogger())
110
116
return limit_filter
131
cur_time = time_override.pop(0)
133
time_override = [None if i is None else i + time_ticker
134
for i in time_override]
113
140
class TestRateLimit(unittest.TestCase):
115
def _run(self, callable_func, num, rate, extra_sleep=0,
116
total_time=None, check_time=True):
142
def _reset_time(self):
147
self.was_sleep = eventlet.sleep
148
eventlet.sleep = mock_sleep
149
self.was_time = time.time
150
time.time = mock_time
154
eventlet.sleep = self.was_sleep
155
time.time = self.was_time
157
def _run(self, callable_func, num, rate, check_time=True):
117
159
begin = time.time()
118
160
for x in range(0, num):
119
161
result = callable_func()
120
# Extra sleep is here to test with different call intervals.
121
time.sleep(extra_sleep)
122
162
end = time.time()
123
if total_time is None:
124
total_time = num / rate
163
total_time = float(num) / rate - 1.0 / rate # 1st request isn't limited
125
164
# Allow for one second of variation in the total time.
126
165
time_diff = abs(total_time - (end - begin))
128
self.assertTrue(time_diff < 1)
167
self.assertEquals(round(total_time, 1), round(time_ticker, 1))
131
170
def test_get_container_maxrate(self):
150
189
logger=FakeLogger())
151
190
the_app.memcache_client = fake_memcache
152
191
self.assertEquals(len(the_app.get_ratelimitable_key_tuples(
153
'GET', 'a', None, None)), 1)
154
self.assertEquals(len(the_app.get_ratelimitable_key_tuples(
155
'POST', 'a', 'c', None)), 0)
192
'DELETE', 'a', None, None)), 0)
156
193
self.assertEquals(len(the_app.get_ratelimitable_key_tuples(
157
194
'PUT', 'a', 'c', None)), 1)
158
195
self.assertEquals(len(the_app.get_ratelimitable_key_tuples(
159
'GET', 'a', 'c', None)), 1)
196
'DELETE', 'a', 'c', None)), 1)
160
197
self.assertEquals(len(the_app.get_ratelimitable_key_tuples(
161
198
'GET', 'a', 'c', 'o')), 0)
162
199
self.assertEquals(len(the_app.get_ratelimitable_key_tuples(
163
200
'PUT', 'a', 'c', 'o')), 1)
165
def test_ratelimit(self):
168
conf_dict = {'account_ratelimit': current_rate}
169
self.test_ratelimit = ratelimit.filter_factory(conf_dict)(FakeApp())
170
ratelimit.http_connect = mock_http_connect(204)
171
req = Request.blank('/v/a')
202
def test_account_ratelimit(self):
205
conf_dict = {'account_ratelimit': current_rate}
206
self.test_ratelimit = ratelimit.filter_factory(conf_dict)(FakeApp())
207
ratelimit.http_connect = mock_http_connect(204)
208
for meth, exp_time in [('DELETE', 9.8), ('GET', 0),
209
('POST', 0), ('PUT', 9.8)]:
210
req = Request.blank('/v/a%s/c' % meth)
212
req.environ['swift.cache'] = FakeMemcache()
213
make_app_call = lambda: self.test_ratelimit(req.environ,
216
self._run(make_app_call, num_calls, current_rate,
217
check_time=bool(exp_time))
218
self.assertEquals(round(time.time() - begin, 1), exp_time)
221
def test_ratelimit_set_incr(self):
224
conf_dict = {'account_ratelimit': current_rate}
225
self.test_ratelimit = ratelimit.filter_factory(conf_dict)(FakeApp())
226
ratelimit.http_connect = mock_http_connect(204)
227
req = Request.blank('/v/a/c')
172
229
req.environ['swift.cache'] = FakeMemcache()
230
req.environ['swift.cache'].init_incr_return_neg = True
173
231
make_app_call = lambda: self.test_ratelimit(req.environ,
175
self._run(make_app_call, num_calls, current_rate)
234
self._run(make_app_call, num_calls, current_rate, check_time=False)
235
self.assertEquals(round(time.time() - begin, 1), 9.8)
177
237
def test_ratelimit_whitelist(self):
179
240
conf_dict = {'account_ratelimit': current_rate,
180
241
'max_sleep_time_seconds': 2,
242
301
the_497s = [t for t in threads if \
243
302
''.join(t.result).startswith('Your account')]
244
303
self.assertEquals(len(the_497s), 5)
245
time_took = time.time() - begin
246
self.assert_(round(time_took, 1) == 0)
304
self.assertEquals(time_ticker, 0)
248
306
def test_ratelimit_max_rate_double(self):
250
310
conf_dict = {'account_ratelimit': current_rate,
251
311
'clock_accuracy': 100,
252
312
'max_sleep_time_seconds': 1}
253
# making clock less accurate for nosetests running slow
254
313
self.test_ratelimit = dummy_filter_factory(conf_dict)(FakeApp())
255
314
ratelimit.http_connect = mock_http_connect(204)
256
315
self.test_ratelimit.log_sleep_time_seconds = .00001
257
req = Request.blank('/v/a')
316
req = Request.blank('/v/a/c')
258
318
req.environ['swift.cache'] = FakeMemcache()
261
class rate_caller(Thread):
263
def __init__(self, parent, name):
264
Thread.__init__(self)
269
self.result1 = self.parent.test_ratelimit(req.environ,
272
self.result2 = self.parent.test_ratelimit(req.environ,
277
rc = rate_caller(self, "thread %s" % i)
280
for thread in threads:
282
all_results = [''.join(t.result1) for t in threads]
283
all_results += [''.join(t.result2) for t in threads]
284
the_498s = [t for t in all_results if t.startswith('Slow down')]
285
self.assertEquals(len(the_498s), 2)
286
time_took = time.time() - begin
287
self.assert_(1.5 <= round(time_took, 1) < 1.7, time_took)
320
time_override = [0, 0, 0, 0, None]
321
# simulates 4 requests coming in at same time, then sleeping
322
r = self.test_ratelimit(req.environ, start_response)
324
r = self.test_ratelimit(req.environ, start_response)
326
r = self.test_ratelimit(req.environ, start_response)
327
self.assertEquals(r[0], 'Slow down')
329
r = self.test_ratelimit(req.environ, start_response)
330
self.assertEquals(r[0], 'Slow down')
332
r = self.test_ratelimit(req.environ, start_response)
333
self.assertEquals(r[0], '204 No Content')
289
335
def test_ratelimit_max_rate_multiple_acc(self):
319
365
threads.append(rc)
320
366
for thread in threads:
322
time_took = time.time() - begin
323
# the all 15 threads still take 1.5 secs
324
self.assert_(1.5 <= round(time_took, 1) < 1.7)
326
def test_ratelimit_acc_vrs_container(self):
327
conf_dict = {'clock_accuracy': 1000,
328
'account_ratelimit': 10,
329
'max_sleep_time_seconds': 4,
330
'container_ratelimit_10': 6,
331
'container_ratelimit_50': 2,
332
'container_ratelimit_75': 1}
333
self.test_ratelimit = dummy_filter_factory(conf_dict)(FakeApp())
334
ratelimit.http_connect = mock_http_connect(204)
335
req = Request.blank('/v/a/c')
336
req.environ['swift.cache'] = FakeMemcache()
337
cont_key = get_container_memcache_key('a', 'c')
339
class rate_caller(Thread):
341
def __init__(self, parent, name):
342
Thread.__init__(self)
347
self.result = self.parent.test_ratelimit(req.environ,
350
def runthreads(threads, nt):
352
rc = rate_caller(self, "thread %s" % i)
355
for thread in threads:
359
req.environ['swift.cache'].set(cont_key, {'container_size': 20})
362
runthreads(threads, 3)
363
time_took = time.time() - begin
364
self.assert_(round(time_took, 1) == .4)
369
time_took = time.time() - begin
370
self.assertEquals(1.5, round(time_took, 1))
366
372
def test_call_invalid_path(self):
367
373
env = {'REQUEST_METHOD': 'GET',
393
399
req.environ['swift.cache'] = None
394
400
make_app_call = lambda: self.test_ratelimit(req.environ,
396
self._run(make_app_call, num_calls, current_rate)
403
self._run(make_app_call, num_calls, current_rate, check_time=False)
404
time_took = time.time() - begin
405
self.assertEquals(round(time_took, 1), 0) # no memcache, no limiting
398
407
def test_restarting_memcache(self):