~ubuntu-branches/ubuntu/saucy/python-django/saucy-updates

« back to all changes in this revision

Viewing changes to django/contrib/sessions/tests.py

  • Committer: Package Import Robot
  • Author(s): Luke Faraone, Jakub Wilk, Luke Faraone
  • Date: 2013-05-09 15:10:47 UTC
  • mfrom: (1.1.21) (4.4.27 sid)
  • Revision ID: package-import@ubuntu.com-20130509151047-aqv8d71oj9wvcv8c
Tags: 1.5.1-2
[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Luke Faraone ]
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from __future__ import with_statement
2
 
 
3
 
from datetime import datetime, timedelta
 
1
from datetime import timedelta
 
2
import os
4
3
import shutil
5
4
import string
6
5
import tempfile
14
13
from django.contrib.sessions.backends.signed_cookies import SessionStore as CookieSession
15
14
from django.contrib.sessions.models import Session
16
15
from django.contrib.sessions.middleware import SessionMiddleware
17
 
from django.core.cache.backends.base import CacheKeyWarning
 
16
from django.core.cache import get_cache
 
17
from django.core import management
18
18
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
19
19
from django.http import HttpResponse
20
20
from django.test import TestCase, RequestFactory
21
 
from django.test.utils import override_settings, get_warnings_state, restore_warnings_state
 
21
from django.test.utils import override_settings
 
22
from django.utils import six
22
23
from django.utils import timezone
23
24
from django.utils import unittest
24
25
 
84
85
        self.session['some key'] = 1
85
86
        self.session.modified = False
86
87
        self.session.accessed = False
87
 
        self.assertTrue('some key' in self.session)
 
88
        self.assertIn('some key', self.session)
88
89
        self.assertTrue(self.session.accessed)
89
90
        self.assertFalse(self.session.modified)
90
91
 
91
92
    def test_values(self):
92
 
        self.assertEqual(self.session.values(), [])
 
93
        self.assertEqual(list(self.session.values()), [])
93
94
        self.assertTrue(self.session.accessed)
94
95
        self.session['some key'] = 1
95
 
        self.assertEqual(self.session.values(), [1])
 
96
        self.assertEqual(list(self.session.values()), [1])
96
97
 
97
98
    def test_iterkeys(self):
98
99
        self.session['x'] = 1
99
100
        self.session.modified = False
100
101
        self.session.accessed = False
101
 
        i = self.session.iterkeys()
 
102
        i = six.iterkeys(self.session)
102
103
        self.assertTrue(hasattr(i, '__iter__'))
103
104
        self.assertTrue(self.session.accessed)
104
105
        self.assertFalse(self.session.modified)
108
109
        self.session['x'] = 1
109
110
        self.session.modified = False
110
111
        self.session.accessed = False
111
 
        i = self.session.itervalues()
 
112
        i = six.itervalues(self.session)
112
113
        self.assertTrue(hasattr(i, '__iter__'))
113
114
        self.assertTrue(self.session.accessed)
114
115
        self.assertFalse(self.session.modified)
118
119
        self.session['x'] = 1
119
120
        self.session.modified = False
120
121
        self.session.accessed = False
121
 
        i = self.session.iteritems()
 
122
        i = six.iteritems(self.session)
122
123
        self.assertTrue(hasattr(i, '__iter__'))
123
124
        self.assertTrue(self.session.accessed)
124
125
        self.assertFalse(self.session.modified)
128
129
        self.session['x'] = 1
129
130
        self.session.modified = False
130
131
        self.session.accessed = False
131
 
        self.assertEqual(self.session.items(), [('x', 1)])
 
132
        self.assertEqual(list(self.session.items()), [('x', 1)])
132
133
        self.session.clear()
133
 
        self.assertEqual(self.session.items(), [])
 
134
        self.assertEqual(list(self.session.items()), [])
134
135
        self.assertTrue(self.session.accessed)
135
136
        self.assertTrue(self.session.modified)
136
137
 
137
138
    def test_save(self):
 
139
        if (hasattr(self.session, '_cache') and'DummyCache' in
 
140
            settings.CACHES[settings.SESSION_CACHE_ALIAS]['BACKEND']):
 
141
            raise unittest.SkipTest("Session saving tests require a real cache backend")
138
142
        self.session.save()
139
143
        self.assertTrue(self.session.exists(self.session.session_key))
140
144
 
157
161
        self.session['a'], self.session['b'] = 'c', 'd'
158
162
        self.session.save()
159
163
        prev_key = self.session.session_key
160
 
        prev_data = self.session.items()
 
164
        prev_data = list(self.session.items())
161
165
        self.session.cycle_key()
162
166
        self.assertNotEqual(self.session.session_key, prev_key)
163
 
        self.assertEqual(self.session.items(), prev_data)
 
167
        self.assertEqual(list(self.session.items()), prev_data)
164
168
 
165
169
    def test_invalid_key(self):
166
170
        # Submitting an invalid session key (either by guessing, or if the db has
195
199
        self.assertEqual(self.session.get_expiry_age(), settings.SESSION_COOKIE_AGE)
196
200
 
197
201
    def test_custom_expiry_seconds(self):
198
 
        # Using seconds
 
202
        modification = timezone.now()
 
203
 
199
204
        self.session.set_expiry(10)
200
 
        delta = self.session.get_expiry_date() - timezone.now()
201
 
        self.assertTrue(delta.seconds in (9, 10))
202
 
 
203
 
        age = self.session.get_expiry_age()
204
 
        self.assertTrue(age in (9, 10))
 
205
 
 
206
        date = self.session.get_expiry_date(modification=modification)
 
207
        self.assertEqual(date, modification + timedelta(seconds=10))
 
208
 
 
209
        age = self.session.get_expiry_age(modification=modification)
 
210
        self.assertEqual(age, 10)
205
211
 
206
212
    def test_custom_expiry_timedelta(self):
207
 
        # Using timedelta
208
 
        self.session.set_expiry(timedelta(seconds=10))
209
 
        delta = self.session.get_expiry_date() - timezone.now()
210
 
        self.assertTrue(delta.seconds in (9, 10))
211
 
 
212
 
        age = self.session.get_expiry_age()
213
 
        self.assertTrue(age in (9, 10))
 
213
        modification = timezone.now()
 
214
 
 
215
        # Mock timezone.now, because set_expiry calls it on this code path.
 
216
        original_now = timezone.now
 
217
        try:
 
218
            timezone.now = lambda: modification
 
219
            self.session.set_expiry(timedelta(seconds=10))
 
220
        finally:
 
221
            timezone.now = original_now
 
222
 
 
223
        date = self.session.get_expiry_date(modification=modification)
 
224
        self.assertEqual(date, modification + timedelta(seconds=10))
 
225
 
 
226
        age = self.session.get_expiry_age(modification=modification)
 
227
        self.assertEqual(age, 10)
214
228
 
215
229
    def test_custom_expiry_datetime(self):
216
 
        # Using fixed datetime
217
 
        self.session.set_expiry(timezone.now() + timedelta(seconds=10))
218
 
        delta = self.session.get_expiry_date() - timezone.now()
219
 
        self.assertTrue(delta.seconds in (9, 10))
220
 
 
221
 
        age = self.session.get_expiry_age()
222
 
        self.assertTrue(age in (9, 10))
 
230
        modification = timezone.now()
 
231
 
 
232
        self.session.set_expiry(modification + timedelta(seconds=10))
 
233
 
 
234
        date = self.session.get_expiry_date(modification=modification)
 
235
        self.assertEqual(date, modification + timedelta(seconds=10))
 
236
 
 
237
        age = self.session.get_expiry_age(modification=modification)
 
238
        self.assertEqual(age, 10)
223
239
 
224
240
    def test_custom_expiry_reset(self):
225
241
        self.session.set_expiry(None)
256
272
        encoded = self.session.encode(data)
257
273
        self.assertEqual(self.session.decode(encoded), data)
258
274
 
 
275
    def test_actual_expiry(self):
 
276
        # Regression test for #19200
 
277
        old_session_key = None
 
278
        new_session_key = None
 
279
        try:
 
280
            self.session['foo'] = 'bar'
 
281
            self.session.set_expiry(-timedelta(seconds=10))
 
282
            self.session.save()
 
283
            old_session_key = self.session.session_key
 
284
            # With an expiry date in the past, the session expires instantly.
 
285
            new_session = self.backend(self.session.session_key)
 
286
            new_session_key = new_session.session_key
 
287
            self.assertNotIn('foo', new_session)
 
288
        finally:
 
289
            self.session.delete(old_session_key)
 
290
            self.session.delete(new_session_key)
 
291
 
259
292
 
260
293
class DatabaseSessionTests(SessionTestsMixin, TestCase):
261
294
 
288
321
        del self.session._session_cache
289
322
        self.assertEqual(self.session['y'], 2)
290
323
 
291
 
 
292
 
DatabaseSessionWithTimeZoneTests = override_settings(USE_TZ=True)(DatabaseSessionTests)
 
324
    @override_settings(SESSION_ENGINE="django.contrib.sessions.backends.db")
 
325
    def test_clearsessions_command(self):
 
326
        """
 
327
        Test clearsessions command for clearing expired sessions.
 
328
        """
 
329
        self.assertEqual(0, Session.objects.count())
 
330
 
 
331
        # One object in the future
 
332
        self.session['foo'] = 'bar'
 
333
        self.session.set_expiry(3600)
 
334
        self.session.save()
 
335
 
 
336
        # One object in the past
 
337
        other_session = self.backend()
 
338
        other_session['foo'] = 'bar'
 
339
        other_session.set_expiry(-3600)
 
340
        other_session.save()
 
341
 
 
342
        # Two sessions are in the database before clearsessions...
 
343
        self.assertEqual(2, Session.objects.count())
 
344
        management.call_command('clearsessions')
 
345
        # ... and one is deleted.
 
346
        self.assertEqual(1, Session.objects.count())
 
347
 
 
348
 
 
349
@override_settings(USE_TZ=True)
 
350
class DatabaseSessionWithTimeZoneTests(DatabaseSessionTests):
 
351
    pass
293
352
 
294
353
 
295
354
class CacheDBSessionTests(SessionTestsMixin, TestCase):
296
355
 
297
356
    backend = CacheDBSession
298
357
 
 
358
    @unittest.skipIf('DummyCache' in
 
359
        settings.CACHES[settings.SESSION_CACHE_ALIAS]['BACKEND'],
 
360
        "Session saving tests require a real cache backend")
299
361
    def test_exists_searches_cache_first(self):
300
362
        self.session.save()
301
363
        with self.assertNumQueries(0):
302
364
            self.assertTrue(self.session.exists(self.session.session_key))
303
365
 
304
366
    def test_load_overlong_key(self):
305
 
        warnings_state = get_warnings_state()
306
 
        warnings.filterwarnings('ignore',
307
 
                                category=CacheKeyWarning)
308
 
        self.session._session_key = (string.ascii_letters + string.digits) * 20
309
 
        self.assertEqual(self.session.load(), {})
310
 
        restore_warnings_state(warnings_state)
311
 
 
312
 
 
313
 
CacheDBSessionWithTimeZoneTests = override_settings(USE_TZ=True)(CacheDBSessionTests)
 
367
        # Some backends might issue a warning
 
368
        with warnings.catch_warnings():
 
369
            warnings.simplefilter("ignore")
 
370
            self.session._session_key = (string.ascii_letters + string.digits) * 20
 
371
            self.assertEqual(self.session.load(), {})
 
372
 
 
373
 
 
374
@override_settings(USE_TZ=True)
 
375
class CacheDBSessionWithTimeZoneTests(CacheDBSessionTests):
 
376
    pass
314
377
 
315
378
 
316
379
# Don't need DB flushing for these tests, so can use unittest.TestCase as base class
319
382
    backend = FileSession
320
383
 
321
384
    def setUp(self):
322
 
        super(FileSessionTests, self).setUp()
323
385
        # Do file session tests in an isolated directory, and kill it after we're done.
324
386
        self.original_session_file_path = settings.SESSION_FILE_PATH
325
387
        self.temp_session_store = settings.SESSION_FILE_PATH = tempfile.mkdtemp()
 
388
        # Reset the file session backend's internal caches
 
389
        if hasattr(self.backend, '_storage_path'):
 
390
            del self.backend._storage_path
 
391
        super(FileSessionTests, self).setUp()
326
392
 
327
393
    def tearDown(self):
 
394
        super(FileSessionTests, self).tearDown()
328
395
        settings.SESSION_FILE_PATH = self.original_session_file_path
329
396
        shutil.rmtree(self.temp_session_store)
330
 
        super(FileSessionTests, self).tearDown()
331
397
 
332
398
    @override_settings(
333
399
        SESSION_FILE_PATH="/if/this/directory/exists/you/have/a/weird/computer")
334
400
    def test_configuration_check(self):
 
401
        del self.backend._storage_path
335
402
        # Make sure the file backend checks for a good storage dir
336
403
        self.assertRaises(ImproperlyConfigured, self.backend)
337
404
 
345
412
        self.assertRaises(SuspiciousOperation,
346
413
                          self.backend("a/b/c").load)
347
414
 
 
415
    @override_settings(SESSION_ENGINE="django.contrib.sessions.backends.file")
 
416
    def test_clearsessions_command(self):
 
417
        """
 
418
        Test clearsessions command for clearing expired sessions.
 
419
        """
 
420
        storage_path = self.backend._get_storage_path()
 
421
        file_prefix = settings.SESSION_COOKIE_NAME
 
422
 
 
423
        def count_sessions():
 
424
            return len([session_file for session_file in os.listdir(storage_path)
 
425
                                     if session_file.startswith(file_prefix)])
 
426
 
 
427
        self.assertEqual(0, count_sessions())
 
428
 
 
429
        # One object in the future
 
430
        self.session['foo'] = 'bar'
 
431
        self.session.set_expiry(3600)
 
432
        self.session.save()
 
433
 
 
434
        # One object in the past
 
435
        other_session = self.backend()
 
436
        other_session['foo'] = 'bar'
 
437
        other_session.set_expiry(-3600)
 
438
        other_session.save()
 
439
 
 
440
        # Two sessions are in the filesystem before clearsessions...
 
441
        self.assertEqual(2, count_sessions())
 
442
        management.call_command('clearsessions')
 
443
        # ... and one is deleted.
 
444
        self.assertEqual(1, count_sessions())
 
445
 
348
446
 
349
447
class CacheSessionTests(SessionTestsMixin, unittest.TestCase):
350
448
 
351
449
    backend = CacheSession
352
450
 
353
451
    def test_load_overlong_key(self):
354
 
        warnings_state = get_warnings_state()
355
 
        warnings.filterwarnings('ignore',
356
 
                                category=CacheKeyWarning)
357
 
        self.session._session_key = (string.ascii_letters + string.digits) * 20
358
 
        self.assertEqual(self.session.load(), {})
359
 
        restore_warnings_state(warnings_state)
 
452
        # Some backends might issue a warning
 
453
        with warnings.catch_warnings():
 
454
            warnings.simplefilter("ignore")
 
455
            self.session._session_key = (string.ascii_letters + string.digits) * 20
 
456
            self.assertEqual(self.session.load(), {})
 
457
 
 
458
    def test_default_cache(self):
 
459
        self.session.save()
 
460
        self.assertNotEqual(get_cache('default').get(self.session.cache_key), None)
 
461
 
 
462
    @override_settings(CACHES={
 
463
        'default': {
 
464
            'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
 
465
        },
 
466
        'sessions': {
 
467
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
 
468
        },
 
469
    }, SESSION_CACHE_ALIAS='sessions')
 
470
    def test_non_default_cache(self):
 
471
        self.session.save()
 
472
        self.assertEqual(get_cache('default').get(self.session.cache_key), None)
 
473
        self.assertNotEqual(get_cache('sessions').get(self.session.cache_key), None)
360
474
 
361
475
 
362
476
class SessionMiddlewareTests(unittest.TestCase):
405
519
 
406
520
        # Handle the response through the middleware
407
521
        response = middleware.process_response(request, response)
408
 
        # If it isn't in the cookie, that's fine (Python 2.5)
409
 
        if 'httponly' in settings.SESSION_COOKIE_NAME:
410
 
            self.assertFalse(
411
 
               response.cookies[settings.SESSION_COOKIE_NAME]['httponly'])
 
522
        self.assertFalse(response.cookies[settings.SESSION_COOKIE_NAME]['httponly'])
412
523
 
413
524
        self.assertNotIn('httponly',
414
525
                         str(response.cookies[settings.SESSION_COOKIE_NAME]))
415
526
 
 
527
    def test_session_save_on_500(self):
 
528
        request = RequestFactory().get('/')
 
529
        response = HttpResponse('Horrible error')
 
530
        response.status_code = 500
 
531
        middleware = SessionMiddleware()
 
532
 
 
533
        # Simulate a request the modifies the session
 
534
        middleware.process_request(request)
 
535
        request.session['hello'] = 'world'
 
536
 
 
537
        # Handle the response through the middleware
 
538
        response = middleware.process_response(request, response)
 
539
 
 
540
        # Check that the value wasn't saved above.
 
541
        self.assertNotIn('hello', request.session.load())
 
542
 
416
543
 
417
544
class CookieSessionTests(SessionTestsMixin, TestCase):
418
545
 
433
560
        testing for this behavior is meaningless.
434
561
        """
435
562
        pass
 
563
 
 
564
    @unittest.expectedFailure
 
565
    def test_actual_expiry(self):
 
566
        # The cookie backend doesn't handle non-default expiry dates, see #19201
 
567
        super(CookieSessionTests, self).test_actual_expiry()