diff options
Diffstat (limited to 'djangorestframework/tests')
| -rw-r--r-- | djangorestframework/tests/throttling.py | 105 |
1 files changed, 83 insertions, 22 deletions
diff --git a/djangorestframework/tests/throttling.py b/djangorestframework/tests/throttling.py index be552638..b620ee24 100644 --- a/djangorestframework/tests/throttling.py +++ b/djangorestframework/tests/throttling.py @@ -1,57 +1,65 @@ """ Tests for the throttling implementations in the permissions module. """ -import time -from django.conf.urls.defaults import patterns from django.test import TestCase -from django.utils import simplejson as json from django.contrib.auth.models import User from django.core.cache import cache from djangorestframework.compat import RequestFactory from djangorestframework.views import View -from djangorestframework.permissions import PerUserThrottling, PerViewThrottling, PerResourceThrottling, ConfigurationException +from djangorestframework.permissions import PerUserThrottling, PerViewThrottling, PerResourceThrottling from djangorestframework.resources import FormResource class MockView(View): permissions = ( PerUserThrottling, ) - throttle = '3/sec' # 3 requests per second + throttle = '3/sec' def get(self, request): return 'foo' -class MockView1(MockView): +class MockView_PerViewThrottling(MockView): permissions = ( PerViewThrottling, ) -class MockView2(MockView): +class MockView_PerResourceThrottling(MockView): permissions = ( PerResourceThrottling, ) - #No resource set - -class MockView3(MockView2): resource = FormResource + +class MockView_MinuteThrottling(MockView): + throttle = '3/min' + + class ThrottlingTests(TestCase): urls = 'djangorestframework.tests.throttling' def setUp(self): - """Reset the cache so that no throttles will be active""" + """ + Reset the cache so that no throttles will be active + """ cache.clear() self.factory = RequestFactory() def test_requests_are_throttled(self): - """Ensure request rate is limited""" + """ + Ensure request rate is limited + """ request = self.factory.get('/') for dummy in range(4): response = MockView.as_view()(request) self.assertEqual(503, response.status_code) + def set_throttle_timer(self, view, value): + """ + Explicitly set the timer, overriding time.time() + """ + view.permissions[0].timer = lambda self: value + def test_request_throttling_expires(self): """ Ensure request rate is limited for a limited duration only """ - # Explicitly set the timer, overridding time.time() - MockView.permissions[0].timer = lambda self: 0 + self.set_throttle_timer(MockView, 0) request = self.factory.get('/') for dummy in range(4): @@ -59,7 +67,7 @@ class ThrottlingTests(TestCase): self.assertEqual(503, response.status_code) # Advance the timer by one second - MockView.permissions[0].timer = lambda self: 1 + self.set_throttle_timer(MockView, 1) response = MockView.as_view()(request) self.assertEqual(200, response.status_code) @@ -68,20 +76,73 @@ class ThrottlingTests(TestCase): request = self.factory.get('/') request.user = User.objects.create(username='a') for dummy in range(3): - response = view.as_view()(request) + view.as_view()(request) request.user = User.objects.create(username='b') response = view.as_view()(request) self.assertEqual(expect, response.status_code) def test_request_throttling_is_per_user(self): - """Ensure request rate is only limited per user, not globally for PerUserThrottles""" + """ + Ensure request rate is only limited per user, not globally for + PerUserThrottles + """ self.ensure_is_throttled(MockView, 200) def test_request_throttling_is_per_view(self): - """Ensure request rate is limited globally per View for PerViewThrottles""" - self.ensure_is_throttled(MockView1, 503) + """ + Ensure request rate is limited globally per View for PerViewThrottles + """ + self.ensure_is_throttled(MockView_PerViewThrottling, 503) def test_request_throttling_is_per_resource(self): - """Ensure request rate is limited globally per Resource for PerResourceThrottles""" - self.ensure_is_throttled(MockView3, 503) -
\ No newline at end of file + """ + Ensure request rate is limited globally per Resource for PerResourceThrottles + """ + self.ensure_is_throttled(MockView_PerResourceThrottling, 503) + + + 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) + response = view.as_view()(request) + self.assertEquals(response['X-Throttle'], expect) + + def test_seconds_fields(self): + """ + Ensure for second based throttles. + """ + self.ensure_response_header_contains_proper_throttle_field(MockView, + ((0, 'status=SUCCESS; next=0.33 sec'), + (0, 'status=SUCCESS; next=0.50 sec'), + (0, 'status=SUCCESS; next=1.00 sec'), + (0, 'status=FAILURE; next=1.00 sec') + )) + + def test_minutes_fields(self): + """ + Ensure for minute based throttles. + """ + self.ensure_response_header_contains_proper_throttle_field(MockView_MinuteThrottling, + ((0, 'status=SUCCESS; next=20.00 sec'), + (0, 'status=SUCCESS; next=30.00 sec'), + (0, 'status=SUCCESS; next=60.00 sec'), + (0, 'status=FAILURE; next=60.00 sec') + )) + + 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, + ((0, 'status=SUCCESS; next=20.00 sec'), + (20, 'status=SUCCESS; next=20.00 sec'), + (40, 'status=SUCCESS; next=20.00 sec'), + (60, 'status=SUCCESS; next=20.00 sec'), + (80, 'status=SUCCESS; next=20.00 sec') + )) |
