~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to django/contrib/messages/tests/test_cookie.py

  • Committer: Package Import Robot
  • Author(s): Luke Faraone
  • Date: 2013-11-07 15:33:49 UTC
  • mfrom: (1.3.12)
  • Revision ID: package-import@ubuntu.com-20131107153349-e31sc149l2szs3jb
Tags: 1.6-1
* New upstream version. Closes: #557474, #724637.
* python-django now also suggests the installation of ipython,
  bpython, python-django-doc, and libgdal1.
  Closes: #636511, #686333, #704203
* Set package maintainer to Debian Python Modules Team.
* Bump standards version to 3.9.5, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import json
 
2
 
 
3
from django.contrib.messages import constants
 
4
from django.contrib.messages.tests.base import BaseTests
 
5
from django.contrib.messages.storage.cookie import (CookieStorage,
 
6
    MessageEncoder, MessageDecoder)
 
7
from django.contrib.messages.storage.base import Message
 
8
from django.test import TestCase
 
9
from django.test.utils import override_settings
 
10
from django.utils.safestring import SafeData, mark_safe
 
11
 
 
12
 
 
13
def set_cookie_data(storage, messages, invalid=False, encode_empty=False):
 
14
    """
 
15
    Sets ``request.COOKIES`` with the encoded data and removes the storage
 
16
    backend's loaded data cache.
 
17
    """
 
18
    encoded_data = storage._encode(messages, encode_empty=encode_empty)
 
19
    if invalid:
 
20
        # Truncate the first character so that the hash is invalid.
 
21
        encoded_data = encoded_data[1:]
 
22
    storage.request.COOKIES = {CookieStorage.cookie_name: encoded_data}
 
23
    if hasattr(storage, '_loaded_data'):
 
24
        del storage._loaded_data
 
25
 
 
26
 
 
27
def stored_cookie_messages_count(storage, response):
 
28
    """
 
29
    Returns an integer containing the number of messages stored.
 
30
    """
 
31
    # Get a list of cookies, excluding ones with a max-age of 0 (because
 
32
    # they have been marked for deletion).
 
33
    cookie = response.cookies.get(storage.cookie_name)
 
34
    if not cookie or cookie['max-age'] == 0:
 
35
        return 0
 
36
    data = storage._decode(cookie.value)
 
37
    if not data:
 
38
        return 0
 
39
    if data[-1] == CookieStorage.not_finished:
 
40
        data.pop()
 
41
    return len(data)
 
42
 
 
43
 
 
44
@override_settings(SESSION_COOKIE_DOMAIN='.example.com')
 
45
class CookieTest(BaseTests, TestCase):
 
46
    storage_class = CookieStorage
 
47
 
 
48
    def stored_messages_count(self, storage, response):
 
49
        return stored_cookie_messages_count(storage, response)
 
50
 
 
51
    def test_get(self):
 
52
        storage = self.storage_class(self.get_request())
 
53
        # Set initial data.
 
54
        example_messages = ['test', 'me']
 
55
        set_cookie_data(storage, example_messages)
 
56
        # Test that the message actually contains what we expect.
 
57
        self.assertEqual(list(storage), example_messages)
 
58
 
 
59
    def test_domain(self):
 
60
        """
 
61
        Ensure that CookieStorage honors SESSION_COOKIE_DOMAIN.
 
62
        Refs #15618.
 
63
        """
 
64
        # Test before the messages have been consumed
 
65
        storage = self.get_storage()
 
66
        response = self.get_response()
 
67
        storage.add(constants.INFO, 'test')
 
68
        storage.update(response)
 
69
        self.assertTrue('test' in response.cookies['messages'].value)
 
70
        self.assertEqual(response.cookies['messages']['domain'], '.example.com')
 
71
        self.assertEqual(response.cookies['messages']['expires'], '')
 
72
 
 
73
        # Test after the messages have been consumed
 
74
        storage = self.get_storage()
 
75
        response = self.get_response()
 
76
        storage.add(constants.INFO, 'test')
 
77
        for m in storage:
 
78
            pass # Iterate through the storage to simulate consumption of messages.
 
79
        storage.update(response)
 
80
        self.assertEqual(response.cookies['messages'].value, '')
 
81
        self.assertEqual(response.cookies['messages']['domain'], '.example.com')
 
82
        self.assertEqual(response.cookies['messages']['expires'], 'Thu, 01-Jan-1970 00:00:00 GMT')
 
83
 
 
84
    def test_get_bad_cookie(self):
 
85
        request = self.get_request()
 
86
        storage = self.storage_class(request)
 
87
        # Set initial (invalid) data.
 
88
        example_messages = ['test', 'me']
 
89
        set_cookie_data(storage, example_messages, invalid=True)
 
90
        # Test that the message actually contains what we expect.
 
91
        self.assertEqual(list(storage), [])
 
92
 
 
93
    def test_max_cookie_length(self):
 
94
        """
 
95
        Tests that, if the data exceeds what is allowed in a cookie, older
 
96
        messages are removed before saving (and returned by the ``update``
 
97
        method).
 
98
        """
 
99
        storage = self.get_storage()
 
100
        response = self.get_response()
 
101
 
 
102
        # When storing as a cookie, the cookie has constant overhead of approx
 
103
        # 54 chars, and each message has a constant overhead of about 37 chars
 
104
        # and a variable overhead of zero in the best case. We aim for a message
 
105
        # size which will fit 4 messages into the cookie, but not 5.
 
106
        # See also FallbackTest.test_session_fallback
 
107
        msg_size = int((CookieStorage.max_cookie_size - 54) / 4.5 - 37)
 
108
        for i in range(5):
 
109
            storage.add(constants.INFO, str(i) * msg_size)
 
110
        unstored_messages = storage.update(response)
 
111
 
 
112
        cookie_storing = self.stored_messages_count(storage, response)
 
113
        self.assertEqual(cookie_storing, 4)
 
114
 
 
115
        self.assertEqual(len(unstored_messages), 1)
 
116
        self.assertTrue(unstored_messages[0].message == '0' * msg_size)
 
117
 
 
118
    def test_json_encoder_decoder(self):
 
119
        """
 
120
        Tests that a complex nested data structure containing Message
 
121
        instances is properly encoded/decoded by the custom JSON
 
122
        encoder/decoder classes.
 
123
        """
 
124
        messages = [
 
125
            {
 
126
                'message': Message(constants.INFO, 'Test message'),
 
127
                'message_list': [Message(constants.INFO, 'message %s') \
 
128
                                 for x in range(5)] + [{'another-message': \
 
129
                                 Message(constants.ERROR, 'error')}],
 
130
            },
 
131
            Message(constants.INFO, 'message %s'),
 
132
        ]
 
133
        encoder = MessageEncoder(separators=(',', ':'))
 
134
        value = encoder.encode(messages)
 
135
        decoded_messages = json.loads(value, cls=MessageDecoder)
 
136
        self.assertEqual(messages, decoded_messages)
 
137
 
 
138
    def test_safedata(self):
 
139
        """
 
140
        Tests that a message containing SafeData is keeping its safe status when
 
141
        retrieved from the message storage.
 
142
        """
 
143
        def encode_decode(data):
 
144
            message = Message(constants.DEBUG, data)
 
145
            encoded = storage._encode(message)
 
146
            decoded = storage._decode(encoded)
 
147
            return decoded.message
 
148
 
 
149
        storage = self.get_storage()
 
150
 
 
151
        self.assertIsInstance(
 
152
            encode_decode(mark_safe("<b>Hello Django!</b>")), SafeData)
 
153
        self.assertNotIsInstance(
 
154
            encode_decode("<b>Hello Django!</b>"), SafeData)