def setUp(self): super().setUp() self.middleware = middleware.TieredCacheMiddleware() self.request = RequestFactory().get('/') self.request.user = self._mock_user(is_staff=True) self.request_cache = RequestCache() self.request_cache.clear_all_namespaces()
def setUp(self): super().setUp() self.middleware = middleware.RequestCacheMiddleware() self.request = RequestFactory().get('/') self.request_cache = RequestCache() self.other_request_cache = RequestCache(TEST_NAMESPACE) self._dirty_request_cache()
def test_clear_all_namespaces(self): self.request_cache.set(TEST_KEY, EXPECTED_VALUE) self.other_request_cache.set(TEST_KEY, EXPECTED_VALUE) RequestCache.clear_all_namespaces() cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertFalse(cached_response.is_found) cached_response = self.other_request_cache.get_cached_response( TEST_KEY) self.assertFalse(cached_response.is_found)
class TestTieredCacheMiddleware(TestCase): @override_settings(MIDDLEWARE=[ 'edx_django_utils.cache.middleware.RequestCacheMiddleware', 'edx_django_utils.cache.middleware.TieredCacheMiddleware' ]) def setUp(self): super(TestTieredCacheMiddleware, self).setUp() self.middleware = middleware.TieredCacheMiddleware() self.request = RequestFactory().get('/') self.request.user = self._mock_user(is_staff=True) self.request_cache = RequestCache() self.request_cache.clear_all_namespaces() def test_process_request(self): self.middleware.process_request(self.request) self.assertFalse( self.request_cache.get_cached_response( SHOULD_FORCE_CACHE_MISS_KEY).value) def test_process_request_force_django_cache_miss(self): request = RequestFactory().get( '/?{}=tRuE'.format(FORCE_CACHE_MISS_PARAM)) request.user = self._mock_user(is_staff=True) self.middleware.process_request(request) self.assertTrue( self.request_cache.get_cached_response( SHOULD_FORCE_CACHE_MISS_KEY).value) def test_process_request_force_django_cache_miss_non_staff(self): request = RequestFactory().get( '/?{}=tRuE'.format(FORCE_CACHE_MISS_PARAM)) request.user = self._mock_user(is_staff=False) self.middleware.process_request(request) self.assertFalse( self.request_cache.get_cached_response( SHOULD_FORCE_CACHE_MISS_KEY).value) @override_settings(MIDDLEWARE=['some.Middleware']) def test_tiered_cache_missing_middleware(self): with self.assertRaises(AssertionError): middleware.TieredCacheMiddleware() def _mock_user(self, is_staff=True): mock_user = MagicMock() mock_user.is_active = True mock_user.is_staff = is_staff return mock_user
class TestTieredCacheMiddleware(TestCase): # pylint: disable=missing-class-docstring def setUp(self): super(TestTieredCacheMiddleware, self).setUp() self.middleware = middleware.TieredCacheMiddleware() self.request = RequestFactory().get('/') self.request.user = self._mock_user(is_staff=True) self.request_cache = RequestCache() self.request_cache.clear_all_namespaces() def test_process_request(self): self.middleware.process_request(self.request) self.assertFalse( self.request_cache.get_cached_response( SHOULD_FORCE_CACHE_MISS_KEY).value) def test_process_request_force_cache_miss(self): request = RequestFactory().get( '/?{}=tRuE'.format(FORCE_CACHE_MISS_PARAM)) request.user = self._mock_user(is_staff=True) self.middleware.process_request(request) self.assertTrue( self.request_cache.get_cached_response( SHOULD_FORCE_CACHE_MISS_KEY).value) def test_process_request_force_cache_miss_non_staff(self): request = RequestFactory().get( '/?{}=tRuE'.format(FORCE_CACHE_MISS_PARAM)) request.user = self._mock_user(is_staff=False) self.middleware.process_request(request) self.assertFalse( self.request_cache.get_cached_response( SHOULD_FORCE_CACHE_MISS_KEY).value) def _mock_user(self, is_staff=True): mock_user = MagicMock() mock_user.is_active = True mock_user.is_staff = is_staff return mock_user
def _pathway_data(self, pathway_key): """ Given a Pathway key, get its data (the list of XBlocks in it). Cached per-request for performance. """ assert isinstance(pathway_key, PathwayLocator) cache = RequestCache(namespace='lx-pathway-plugin') cache_key = '_pathway_data:{}'.format(str(pathway_key)) cache_response = cache.get_cached_response(cache_key) if cache_response.is_found: return cache_response.value try: pathway = Pathway.objects.get(uuid=pathway_key.uuid) except Pathway.DoesNotExist: log.exception("Pathway does not exist for pathway key {}".format(pathway_key)) raise result = getattr(pathway, 'draft_data' if self.use_draft else 'published_data') cache.set(cache_key, result) return result
class TestRequestCacheMiddleware(TestCase): # pylint: disable=missing-class-docstring def setUp(self): super().setUp() self.middleware = middleware.RequestCacheMiddleware() self.request = RequestFactory().get('/') self.request_cache = RequestCache() self.other_request_cache = RequestCache(TEST_NAMESPACE) self._dirty_request_cache() def test_process_request(self): self.middleware.process_request(self.request) self._check_request_caches_cleared() def test_process_response(self): response = self.middleware.process_response(self.request, EXPECTED_VALUE) self.assertEqual(response, EXPECTED_VALUE) self._check_request_caches_cleared() def _check_request_caches_cleared(self): """ Checks that all request caches were cleared. """ self.assertFalse( self.request_cache.get_cached_response(TEST_KEY).is_found) self.assertFalse( self.other_request_cache.get_cached_response(TEST_KEY).is_found) def _dirty_request_cache(self): """ Dirties the request caches to ensure the middleware is clearing it. """ self.request_cache.set(TEST_KEY, EXPECTED_VALUE) self.other_request_cache.set(TEST_KEY, EXPECTED_VALUE)
def test_clear_all_namespaces_other_thread(self): """ Clearing all namespaces for a different thread should not clear this request cache. """ self.request_cache.set(TEST_KEY, EXPECTED_VALUE) other_thread = Thread( target=lambda: RequestCache.clear_all_namespaces()) # pylint: disable=unnecessary-lambda other_thread.start() other_thread.join() cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_found)
class TestRequestCacheMiddleware(TestCase): # pylint: disable=missing-class-docstring @override_settings(MIDDLEWARE=[ 'edx_django_utils.cache.middleware.RequestCacheMiddleware' ]) def setUp(self): super(TestRequestCacheMiddleware, self).setUp() self.middleware = middleware.RequestCacheMiddleware() self.request = RequestFactory().get('/') self.request_cache = RequestCache() self.other_request_cache = RequestCache(TEST_NAMESPACE) self._dirty_request_cache() def test_process_request(self): self.middleware.process_request(self.request) self._check_request_caches_cleared() def test_process_response(self): response = self.middleware.process_response(self.request, EXPECTED_VALUE) self.assertEqual(response, EXPECTED_VALUE) self._check_request_caches_cleared() def test_process_exception(self): # pylint: disable=assignment-from-no-return response = self.middleware.process_exception(self.request, EXPECTED_VALUE) self.assertEqual(response, None) self._check_request_caches_cleared() def _check_request_caches_cleared(self): """ Checks that all request caches were cleared. """ self.assertFalse( self.request_cache.get_cached_response(TEST_KEY).is_found) self.assertFalse( self.other_request_cache.get_cached_response(TEST_KEY).is_found) def _dirty_request_cache(self): """ Dirties the request caches to ensure the middleware is clearing it. """ self.request_cache.set(TEST_KEY, EXPECTED_VALUE) self.other_request_cache.set(TEST_KEY, EXPECTED_VALUE)
def setUp(self): super().setUp() RequestCache.clear_all_namespaces() self.request_cache = RequestCache() self.other_request_cache = RequestCache(TEST_NAMESPACE)
class TestRequestCache(TestCase): # pylint: disable=missing-class-docstring def setUp(self): super().setUp() RequestCache.clear_all_namespaces() self.request_cache = RequestCache() self.other_request_cache = RequestCache(TEST_NAMESPACE) def test_get_cached_response_hit(self): self.request_cache.set(TEST_KEY, EXPECTED_VALUE) cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_found) self.assertEqual(cached_response.value, EXPECTED_VALUE) cached_response = self.other_request_cache.get_cached_response( TEST_KEY) self.assertFalse(cached_response.is_found) self.other_request_cache.set(TEST_KEY_2, EXPECTED_VALUE) cached_response = self.request_cache.get_cached_response(TEST_KEY_2) self.assertFalse(cached_response.is_found) cached_response = self.other_request_cache.get_cached_response( TEST_KEY_2) self.assertTrue(cached_response.is_found) self.assertEqual(cached_response.value, EXPECTED_VALUE) def test_get_cached_response_hit_with_cached_none(self): self.request_cache.set(TEST_KEY, None) cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_found) self.assertEqual(cached_response.value, None) def test_get_cached_response_miss(self): cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertFalse(cached_response.is_found) def test_get_cached_response_with_default(self): self.request_cache.setdefault(TEST_KEY, EXPECTED_VALUE) cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_found) self.assertEqual(cached_response.value, EXPECTED_VALUE) def test_get_cached_response_with_default_after_set(self): self.request_cache.set(TEST_KEY, EXPECTED_VALUE_2) self.request_cache.setdefault(TEST_KEY, EXPECTED_VALUE) cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_found) self.assertEqual(cached_response.value, EXPECTED_VALUE_2) def test_cache_data(self): self.assertDictEqual(self.request_cache.data, {}) key_value_pairs = [(TEST_KEY, EXPECTED_VALUE), (TEST_KEY_2, EXPECTED_VALUE_2)] expected_dict = {} for key, value in key_value_pairs: self.request_cache.set(key, value) expected_dict[key] = value self.assertDictEqual(self.request_cache.data, expected_dict) def test_clear(self): self.request_cache.set(TEST_KEY, EXPECTED_VALUE) self.other_request_cache.set(TEST_KEY, EXPECTED_VALUE) self.request_cache.clear() cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertFalse(cached_response.is_found) cached_response = self.other_request_cache.get_cached_response( TEST_KEY) self.assertTrue(cached_response.is_found) def test_clear_all_namespaces(self): self.request_cache.set(TEST_KEY, EXPECTED_VALUE) self.other_request_cache.set(TEST_KEY, EXPECTED_VALUE) RequestCache.clear_all_namespaces() cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertFalse(cached_response.is_found) cached_response = self.other_request_cache.get_cached_response( TEST_KEY) self.assertFalse(cached_response.is_found) def test_clear_all_namespaces_other_thread(self): """ Clearing all namespaces for a different thread should not clear this request cache. """ self.request_cache.set(TEST_KEY, EXPECTED_VALUE) other_thread = Thread( target=lambda: RequestCache.clear_all_namespaces()) # pylint: disable=unnecessary-lambda other_thread.start() other_thread.join() cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_found) def test_delete(self): self.request_cache.set(TEST_KEY, EXPECTED_VALUE) self.request_cache.set(TEST_KEY_2, EXPECTED_VALUE) self.other_request_cache.set(TEST_KEY, EXPECTED_VALUE) self.request_cache.delete(TEST_KEY) cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertFalse(cached_response.is_found) cached_response = self.request_cache.get_cached_response(TEST_KEY_2) self.assertTrue(cached_response.is_found) self.assertEqual(cached_response.value, EXPECTED_VALUE) cached_response = self.other_request_cache.get_cached_response( TEST_KEY) self.assertTrue(cached_response.is_found) def test_delete_missing_key(self): try: self.request_cache.delete(TEST_KEY) except KeyError: self.fail( 'Deleting a missing key from the request cache should not cause an error.' ) def test_create_request_cache_with_default_namespace(self): with self.assertRaises(AssertionError): RequestCache(DEFAULT_REQUEST_CACHE_NAMESPACE)
def setUp(self): super().setUp() self.request_cache = RequestCache() TieredCache.dangerous_clear_all_tiers()
class TestTieredCache(TestCase): # pylint: disable=missing-class-docstring def setUp(self): super().setUp() self.request_cache = RequestCache() TieredCache.dangerous_clear_all_tiers() def test_get_cached_response_all_tier_miss(self): cached_response = TieredCache.get_cached_response(TEST_KEY) self.assertFalse(cached_response.is_found) def test_get_cached_response_request_cache_hit(self): self.request_cache.set(TEST_KEY, EXPECTED_VALUE) cached_response = TieredCache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_found) self.assertEqual(cached_response.value, EXPECTED_VALUE) @mock.patch('django.core.cache.cache.get') def test_get_cached_response_django_cache_hit(self, mock_cache_get): mock_cache_get.return_value = EXPECTED_VALUE cached_response = TieredCache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_found) self.assertEqual(cached_response.value, EXPECTED_VALUE) cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertTrue( cached_response.is_found, 'Django cache hit should cache value in request cache.') @mock.patch('django.core.cache.cache.get') def test_get_cached_response_force_cache_miss(self, mock_cache_get): self.request_cache.set(SHOULD_FORCE_CACHE_MISS_KEY, True) mock_cache_get.return_value = EXPECTED_VALUE cached_response = TieredCache.get_cached_response(TEST_KEY) self.assertFalse(cached_response.is_found) cached_response = self.request_cache.get_cached_response(TEST_KEY) self.assertFalse( cached_response.is_found, 'Forced Django cache miss should not cache value in request cache.' ) @mock.patch('django.core.cache.cache.set') def test_set_all_tiers(self, mock_cache_set): mock_cache_set.return_value = EXPECTED_VALUE TieredCache.set_all_tiers(TEST_KEY, EXPECTED_VALUE, TEST_DJANGO_TIMEOUT_CACHE) mock_cache_set.assert_called_with(TEST_KEY, EXPECTED_VALUE, TEST_DJANGO_TIMEOUT_CACHE) self.assertEqual( self.request_cache.get_cached_response(TEST_KEY).value, EXPECTED_VALUE) @mock.patch('django.core.cache.cache.clear') def test_dangerous_clear_all_tiers_and_namespaces(self, mock_cache_clear): TieredCache.set_all_tiers(TEST_KEY, EXPECTED_VALUE) TieredCache.dangerous_clear_all_tiers() self.assertFalse( self.request_cache.get_cached_response(TEST_KEY).is_found) mock_cache_clear.assert_called_once_with() @mock.patch('django.core.cache.cache.delete') def test_delete(self, mock_cache_delete): TieredCache.set_all_tiers(TEST_KEY, EXPECTED_VALUE) TieredCache.set_all_tiers(TEST_KEY_2, EXPECTED_VALUE) TieredCache.delete_all_tiers(TEST_KEY) self.assertFalse( self.request_cache.get_cached_response(TEST_KEY).is_found) self.assertEqual( self.request_cache.get_cached_response(TEST_KEY_2).value, EXPECTED_VALUE) mock_cache_delete.assert_called_with(TEST_KEY)
def test_create_request_cache_with_default_namespace(self): with self.assertRaises(AssertionError): RequestCache(DEFAULT_REQUEST_CACHE_NAMESPACE)