示例#1
0
    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()
示例#2
0
    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()
示例#3
0
    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)
示例#4
0
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
示例#5
0
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
示例#6
0
 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
示例#7
0
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)
示例#8
0
    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)
示例#10
0
 def setUp(self):
     super().setUp()
     RequestCache.clear_all_namespaces()
     self.request_cache = RequestCache()
     self.other_request_cache = RequestCache(TEST_NAMESPACE)
示例#11
0
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)
示例#12
0
 def setUp(self):
     super().setUp()
     self.request_cache = RequestCache()
     TieredCache.dangerous_clear_all_tiers()
示例#13
0
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)
示例#14
0
 def test_create_request_cache_with_default_namespace(self):
     with self.assertRaises(AssertionError):
         RequestCache(DEFAULT_REQUEST_CACHE_NAMESPACE)