root/trunk/pylucid_project/tests/cache.py

Revision 1634, 9.2 KB (checked in by JensDiemer, 2 years ago)

Update Meta Informations:

  • file encoding
  • shebang
  • copyleft and license line
  • svn:keywords
  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3"""
4    PyLucid unittest
5    ~~~~~~~~~~~~~~~~
6
7    Test the PyLucid page cache middleware.
8
9    Last commit info:
10    ~~~~~~~~~~~~~~~~~
11    $LastChangedDate$
12    $Rev$
13    $Author$
14
15    :copyleft: 2008 by the PyLucid team, see AUTHORS for more details.
16    :license: GNU GPL v3, see LICENSE.txt for more details.
17"""
18
19import os
20
21import tests
22from tests.utils.BrowserDebug import debug_response
23
24from django.conf import settings
25from django.http import HttpResponse
26from django.core.cache import cache
27
28from PyLucid.models import Page, Template, Style
29
30# Open only one traceback in a browser (=True) ?
31#ONE_BROWSER_TRACEBACK = False
32ONE_BROWSER_TRACEBACK = True
33
34PAGE_CONTENT_PREFIX = "page content:"
35
36CACHE_CONTENT = "Cached content!"
37
38SHORTCUT = "CacheTestPage"
39
40CACHE_KEY_PREFIX = settings.PAGE_CACHE_PREFIX + SHORTCUT
41
42class TestCache(tests.TestCase):
43    one_browser_traceback = ONE_BROWSER_TRACEBACK
44    _open = []
45
46    #--------------------------------------------------------------------------
47
48    @tests.requires_cache
49    def setUp(self):
50        settings.DEBUG=True
51
52        Page.objects.all().delete() # Delete all existins pages
53
54        self.template = tests.create_template(
55            name = "cache test template",
56            content = (
57                "{{ PAGE.content }}\n"
58                "{{ PAGE.get_permalink }}\n"
59                "<!-- script_duration -->"
60            ),
61        )
62
63        def get_page_dict(no):
64            page = {
65                "name": SHORTCUT + no,
66                "shortcut": SHORTCUT + no,
67                "content": PAGE_CONTENT_PREFIX + no,
68                "template": self.template,
69            }
70            return page
71
72        test_pages = [get_page_dict("1"), get_page_dict("2")]
73        tests.create_pages(test_pages, template=self.template)
74        #self.create_link_snapshot()
75
76        self._prepare_cache()
77
78    def _prepare_cache(self):
79        """
80        -delete the first test page, if exist in the cache.
81        -Add the second test page into the cache.
82        """
83        cache.delete(CACHE_KEY_PREFIX + "1")
84        response = HttpResponse(CACHE_CONTENT + "<!-- script_duration -->")
85        cache.set(CACHE_KEY_PREFIX + "2", response, 9999)
86
87    #--------------------------------------------------------------------------
88
89    def failIfFromCache(self, response, msg=None):
90        self.failUnlessEqual(response.status_code, 200)
91        self.assertResponse(
92            response,
93            must_contain=(PAGE_CONTENT_PREFIX, "render time", "queries"),
94            must_not_contain=("Traceback",)
95        )
96        self.failUnlessEqual(response["from_cache"], "no", msg)
97
98    def failIfNotFromCache(self, response, msg=None):
99        self.failUnlessEqual(response.status_code, 200)
100        url = response.request["PATH_INFO"]
101        if url == "/%s1" % SHORTCUT:
102            self.assertResponse(
103                response,
104                must_contain=(PAGE_CONTENT_PREFIX, "render time", "queries"),
105                must_not_contain=(CACHE_CONTENT, "Traceback",)
106            )
107        elif url == "/%s2" % SHORTCUT:
108            self.assertResponse(
109                response,
110                must_contain=(CACHE_CONTENT, "render time", "queries"),
111                must_not_contain=(PAGE_CONTENT_PREFIX, "Traceback",)
112            )
113        else:
114            raise AssertionError("Wrong url?")
115
116        self.failUnlessEqual(response["from_cache"], "yes", msg)
117
118    #--------------------------------------------------------------------------
119
120    @tests.requires_cache
121    def test_prepage(self):
122        """
123        Test the test environment ;)
124        """
125        # Test _prepare_cache()
126        self.failUnlessEqual(cache.get(CACHE_KEY_PREFIX + "1"), None)
127        response = cache.get(CACHE_KEY_PREFIX + "2")
128        self.failUnlessEqual(
129            response.content, CACHE_CONTENT + "<!-- script_duration -->"
130        )
131
132        # Check if the test pages exist
133        snapshot = {u'/CacheTestPage1/': [], u'/CacheTestPage2/': []}
134        self.link_snapshot_test(snapshot)
135
136        # Request the first test page
137        response = self.client.get("/%s1" % SHORTCUT)
138        #debug_response(response)
139        self.failUnlessEqual(response.status_code, 200)
140        self.assertResponse(
141            response,
142            must_contain=(PAGE_CONTENT_PREFIX, "render time", "queries"),
143            must_not_contain=("Traceback",)
144        )
145
146    @tests.requires_cache
147    def test_assertion(self):
148        """
149        The cache middleware should only use the cached response, if it's a
150        django HttpResponse instance otherwise it sould raise a AssertionError.
151        """
152        cache.set(
153            CACHE_KEY_PREFIX + "3",
154            "a string and not a django HttpResponse instance!",
155            9999
156        )
157        url = "/%s3" % SHORTCUT
158        self.assertRaises(AssertionError, self.client.get, url)
159
160    @tests.requires_cache
161    def test_cache(self):
162        """
163        Check if the second test page comes from the cache.
164        """
165        url = "/%s2" % SHORTCUT
166        response = self.client.get(url)
167        self.assertResponse(
168            response,
169            must_contain=(CACHE_CONTENT,),
170            must_not_contain=(PAGE_CONTENT_PREFIX,)
171        )
172
173    #--------------------------------------------------------------------------
174
175    @tests.requires_cache
176    def test_get(self):
177        """
178        Test the cache with normal GET request.
179        """
180        for i in xrange(3):
181            url = "/%s1" % SHORTCUT
182
183            # First request -> can't exist in the cache
184            response = self.client.get(url)
185            self.failIfFromCache(response, "loop: %s" % i)
186
187            # Second request must comes from the cache
188            response = self.client.get(url)
189            self.failIfNotFromCache(response, "loop: %s" % i)
190
191            # Delete the test page from the cache
192            cache.delete(CACHE_KEY_PREFIX + "1")
193
194
195    @tests.requires_cache
196    def test_post(self):
197        """
198        POST request should never use the cache.
199        """
200        # But a POST request should never use the cache
201        url = "/%s2" % SHORTCUT
202        response = self.client.post(url)
203        self.failIfFromCache(response)
204
205    #--------------------------------------------------------------------------
206
207    def _check_cache_after(self, func):
208        # The secont test page must now comes from the cache
209        url = "/%s2" % SHORTCUT
210        response = self.client.get(url)
211        self.failIfNotFromCache(response)
212
213        # execute the given function
214        func()
215
216        # After edit, the cache should be deleted.
217        response = cache.get(CACHE_KEY_PREFIX + "2")
218        self.failUnlessEqual(response, None)
219
220        # Check the GET response, too.
221        response = self.client.get(url)
222        self.failIfFromCache(response)
223
224
225    @tests.requires_cache
226    def test_page_edit(self):
227        """
228        After a page content has been edited, the cache variante must be
229        deleted.
230        """
231        def test_func():
232            """ 'edit' a page """
233            page = Page.objects.get(shortcut__exact=SHORTCUT + "2")
234            page.content = PAGE_CONTENT_PREFIX + "new content!"
235            page.save()
236
237        self._check_cache_after(test_func)
238
239    @tests.requires_cache
240    def test_template_edit(self):
241        """
242        If a template has been changes, the cache should be deleted.
243        """
244        def test_func():
245            """ 'edit' a template """
246            template = Template.objects.all()[0]
247            template.save()
248
249        self._check_cache_after(test_func)
250
251    @tests.requires_cache
252    def test_styleheet_edit(self):
253        """
254        If a styleheet has been changes, the cache should be deleted.
255        """
256        def test_func():
257            """ 'edit' a styleheet """
258            styleheet = Style.objects.all()[0]
259            styleheet.save()
260
261        self._check_cache_after(test_func)
262
263    #--------------------------------------------------------------------------
264
265    @tests.requires_cache
266    def test_wrong_url(self):
267        """
268        Test if the cache middleware checks bad characters in the url.
269        Normaly the urls-re doesn't match on bad urls. But the process_request
270        method of a middleware called before this.
271        """
272        content = "Should never comes from the cache!"
273        shortcut = "bad$char&here"
274        url = "/%s/" % shortcut
275        cache_key = settings.PAGE_CACHE_PREFIX + shortcut
276
277        # Insert a cache entry, so the cache middleware can found the cached
278        # page and will be response the cached content, if the shortcut will
279        # not be veryfied.
280        response = HttpResponse(content)
281        cache.set(cache_key, response, 9999)
282
283        # Request the cached page and check the response. It should not resonse
284        # the cached content. It should be apperar a 404 page not found.
285        response = self.client.get(url)
286        #debug_response(response)
287        self.failUnlessEqual(response.status_code, 404)
288        self.assertResponse(response, must_not_contain=(content,))
289
290
291if __name__ == "__main__":
292    # Run this unitest directly
293    import os
294    os.chdir("../")
295    filename = os.path.splitext(os.path.basename(__file__))[0]
296    tests.run_tests(test_labels=[filename])
Note: See TracBrowser for help on using the browser.