django-rest-framework/djangorestframework/tests/throttling.py

143 lines
4.2 KiB
Python
Raw Normal View History

2011-06-14 14:08:29 +04:00
"""
Tests for the throttling implementations in the permissions module.
"""
from django.test import TestCase
from django.contrib.auth.models import User
from django.core.cache import cache
from djangorestframework.compat import RequestFactory
2012-09-03 19:54:17 +04:00
from djangorestframework.views import APIView
2012-09-13 21:32:56 +04:00
from djangorestframework.throttling import UserRateThrottle
from djangorestframework.response import Response
2012-08-24 23:57:10 +04:00
2012-09-13 21:32:56 +04:00
class User3SecRateThrottle(UserRateThrottle):
2012-09-05 00:58:35 +04:00
rate = '3/sec'
2012-09-13 21:32:56 +04:00
class User3MinRateThrottle(UserRateThrottle):
rate = '3/min'
class MockView(APIView):
throttle_classes = (User3SecRateThrottle,)
def get(self, request):
return Response('foo')
2012-08-24 23:57:10 +04:00
2012-09-13 21:32:56 +04:00
class MockView_MinuteThrottling(APIView):
throttle_classes = (User3MinRateThrottle,)
2012-08-24 23:57:10 +04:00
2012-09-13 21:32:56 +04:00
def get(self, request):
return Response('foo')
2011-12-29 17:31:12 +04:00
class ThrottlingTests(TestCase):
2011-12-29 17:31:12 +04:00
urls = 'djangorestframework.tests.throttling'
def setUp(self):
2011-06-13 22:42:37 +04:00
"""
Reset the cache so that no throttles will be active
"""
cache.clear()
self.factory = RequestFactory()
2011-12-29 17:31:12 +04:00
def test_requests_are_throttled(self):
2011-06-13 22:42:37 +04:00
"""
Ensure request rate is limited
"""
request = self.factory.get('/')
for dummy in range(4):
response = MockView.as_view()(request)
2012-08-27 02:06:52 +04:00
self.assertEqual(429, response.status_code)
2011-12-29 17:31:12 +04:00
2011-06-13 22:42:37 +04:00
def set_throttle_timer(self, view, value):
"""
Explicitly set the timer, overriding time.time()
"""
2012-09-05 00:58:35 +04:00
view.throttle_classes[0].timer = lambda self: value
2011-06-13 22:42:37 +04:00
def test_request_throttling_expires(self):
2011-06-14 14:08:29 +04:00
"""
Ensure request rate is limited for a limited duration only
"""
2011-06-13 22:42:37 +04:00
self.set_throttle_timer(MockView, 0)
2011-06-14 14:08:29 +04:00
request = self.factory.get('/')
for dummy in range(4):
response = MockView.as_view()(request)
2012-08-27 02:06:52 +04:00
self.assertEqual(429, response.status_code)
2011-06-14 14:08:29 +04:00
# Advance the timer by one second
2011-06-13 22:42:37 +04:00
self.set_throttle_timer(MockView, 1)
2011-06-14 14:08:29 +04:00
response = MockView.as_view()(request)
self.assertEqual(200, response.status_code)
2011-12-29 17:31:12 +04:00
2011-06-11 22:29:01 +04:00
def ensure_is_throttled(self, view, expect):
request = self.factory.get('/')
request.user = User.objects.create(username='a')
for dummy in range(3):
2011-06-13 22:42:37 +04:00
view.as_view()(request)
request.user = User.objects.create(username='b')
response = view.as_view()(request)
2011-06-11 22:29:01 +04:00
self.assertEqual(expect, response.status_code)
2011-12-29 17:31:12 +04:00
def test_request_throttling_is_per_user(self):
2011-06-13 22:42:37 +04:00
"""
2011-12-29 17:31:12 +04:00
Ensure request rate is only limited per user, not globally for
2011-06-13 22:42:37 +04:00
PerUserThrottles
"""
2011-06-11 22:29:01 +04:00
self.ensure_is_throttled(MockView, 200)
2011-12-29 17:31:12 +04:00
2011-06-13 22:42:37 +04:00
def ensure_response_header_contains_proper_throttle_field(self, view, expected_headers):
"""
Ensure the response returns an X-Throttle field with status and next attributes
set properly.
"""
request = self.factory.get('/')
for timer, expect in expected_headers:
self.set_throttle_timer(view, timer)
2011-06-13 22:42:37 +04:00
response = view.as_view()(request)
2012-09-05 00:58:35 +04:00
if expect is not None:
self.assertEquals(response['X-Throttle-Wait-Seconds'], expect)
else:
self.assertFalse('X-Throttle-Wait-Seconds' in response.headers)
2011-12-29 17:31:12 +04:00
2011-06-13 22:42:37 +04:00
def test_seconds_fields(self):
"""
Ensure for second based throttles.
"""
self.ensure_response_header_contains_proper_throttle_field(MockView,
2012-09-05 00:58:35 +04:00
((0, None),
(0, None),
(0, None),
(0, '1')
2011-06-13 22:42:37 +04:00
))
2011-12-29 17:31:12 +04:00
2011-06-13 22:42:37 +04:00
def test_minutes_fields(self):
"""
Ensure for minute based throttles.
"""
self.ensure_response_header_contains_proper_throttle_field(MockView_MinuteThrottling,
2012-09-05 00:58:35 +04:00
((0, None),
(0, None),
(0, None),
(0, '60')
))
2011-12-29 17:31:12 +04:00
def test_next_rate_remains_constant_if_followed(self):
"""
If a client follows the recommended next request rate,
the throttling rate should stay constant.
"""
self.ensure_response_header_contains_proper_throttle_field(MockView_MinuteThrottling,
2012-09-05 00:58:35 +04:00
((0, None),
(20, None),
(40, None),
(60, None),
(80, None)
2011-06-13 22:42:37 +04:00
))