summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authormartin.bohacek <bohacekm@gmail.com>2012-06-05 13:29:33 +0200
committermartin.bohacek <bohacekm@gmail.com>2012-06-05 13:29:33 +0200
commiteee791e9b216333ad0b4c6c441a88828bf9aee62 (patch)
tree3f01e97ea9b0ac28e9c9718b35ae92d163865b1c /tests
parentfbb73894395b728ec96c661da6f87523718c5398 (diff)
parent840ffd80baad85c05670d6b642f654cffaa93cc3 (diff)
Merge branch 'master' of https://github.com/django/django
Diffstat (limited to 'tests')
-rw-r--r--tests/modeltests/defer/tests.py15
-rw-r--r--tests/modeltests/field_subclassing/tests.py4
-rw-r--r--tests/modeltests/files/tests.py13
-rw-r--r--tests/modeltests/fixtures/tests.py30
-rw-r--r--tests/modeltests/known_related_objects/__init__.py0
-rw-r--r--tests/modeltests/known_related_objects/fixtures/tournament.json65
-rw-r--r--tests/modeltests/known_related_objects/models.py19
-rw-r--r--tests/modeltests/known_related_objects/tests.py88
-rw-r--r--tests/modeltests/model_forms/tests.py14
-rw-r--r--tests/modeltests/model_inheritance/tests.py18
-rw-r--r--tests/modeltests/serializers/tests.py18
-rw-r--r--tests/modeltests/str/tests.py8
-rw-r--r--tests/modeltests/update_only_fields/tests.py5
-rw-r--r--tests/modeltests/user_commands/management/commands/dance.py8
-rw-r--r--tests/modeltests/user_commands/tests.py21
-rw-r--r--tests/modeltests/validation/test_error_messages.py150
-rw-r--r--tests/regressiontests/admin_scripts/tests.py11
-rw-r--r--tests/regressiontests/admin_util/tests.py2
-rw-r--r--tests/regressiontests/admin_widgets/tests.py2
-rw-r--r--tests/regressiontests/backends/tests.py12
-rw-r--r--tests/regressiontests/cache/tests.py12
-rw-r--r--tests/regressiontests/conditional_processing/models.py4
-rw-r--r--tests/regressiontests/csrf_tests/tests.py2
-rw-r--r--tests/regressiontests/file_storage/tests.py54
-rw-r--r--tests/regressiontests/file_uploads/tests.py32
-rw-r--r--tests/regressiontests/fixtures_regress/tests.py19
-rw-r--r--tests/regressiontests/forms/tests/fields.py59
-rw-r--r--tests/regressiontests/forms/tests/filepath_test_files/.dot-file0
-rw-r--r--tests/regressiontests/forms/tests/filepath_test_files/directory/.keep0
-rw-r--r--tests/regressiontests/forms/tests/filepath_test_files/fake-image.jpg0
-rw-r--r--tests/regressiontests/forms/tests/filepath_test_files/real-text-file.txt0
-rw-r--r--tests/regressiontests/forms/tests/forms.py6
-rw-r--r--tests/regressiontests/forms/tests/models.py6
-rw-r--r--tests/regressiontests/forms/tests/regressions.py5
-rw-r--r--tests/regressiontests/forms/tests/widgets.py2
-rw-r--r--tests/regressiontests/generic_views/base.py52
-rw-r--r--tests/regressiontests/generic_views/dates.py31
-rw-r--r--tests/regressiontests/generic_views/list.py10
-rw-r--r--tests/regressiontests/generic_views/templates/generic_views/book_archive.html2
-rw-r--r--tests/regressiontests/generic_views/templates/generic_views/book_archive_year.html2
-rw-r--r--tests/regressiontests/generic_views/urls.py9
-rw-r--r--tests/regressiontests/handlers/tests.py2
-rw-r--r--tests/regressiontests/httpwrappers/tests.py10
-rw-r--r--tests/regressiontests/i18n/commands/compilation.py23
-rw-r--r--tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mobin454 -> 528 bytes
-rw-r--r--tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po6
-rw-r--r--tests/regressiontests/i18n/tests.py18
-rw-r--r--tests/regressiontests/inspectdb/tests.py26
-rw-r--r--tests/regressiontests/localflavor/es/tests.py2
-rw-r--r--tests/regressiontests/localflavor/mk/tests.py2
-rw-r--r--tests/regressiontests/mail/tests.py50
-rw-r--r--tests/regressiontests/model_fields/tests.py14
-rw-r--r--tests/regressiontests/model_forms_regress/tests.py6
-rw-r--r--tests/regressiontests/queries/models.py2
-rw-r--r--tests/regressiontests/queries/tests.py59
-rw-r--r--tests/regressiontests/requests/tests.py88
-rw-r--r--tests/regressiontests/servers/tests.py6
-rw-r--r--tests/regressiontests/signing/tests.py6
-rw-r--r--tests/regressiontests/staticfiles_tests/storage.py7
-rw-r--r--tests/regressiontests/staticfiles_tests/tests.py122
-rw-r--r--tests/regressiontests/string_lookup/tests.py2
-rw-r--r--tests/regressiontests/templates/tests.py14
-rw-r--r--tests/regressiontests/templates/unicode.py12
-rw-r--r--tests/regressiontests/test_client_regress/models.py1034
-rw-r--r--tests/regressiontests/test_client_regress/tests.py1006
-rw-r--r--tests/regressiontests/test_client_regress/views.py5
-rw-r--r--tests/regressiontests/test_runner/tests.py11
-rw-r--r--tests/regressiontests/views/__init__.py6
-rw-r--r--tests/regressiontests/views/tests/debug.py104
-rw-r--r--tests/regressiontests/views/tests/static.py10
-rw-r--r--tests/regressiontests/views/views.py23
71 files changed, 1954 insertions, 1532 deletions
diff --git a/tests/modeltests/defer/tests.py b/tests/modeltests/defer/tests.py
index 09138293af..eb09162b01 100644
--- a/tests/modeltests/defer/tests.py
+++ b/tests/modeltests/defer/tests.py
@@ -158,3 +158,18 @@ class DeferTests(TestCase):
self.assert_delayed(child, 1)
self.assertEqual(child.name, 'p1')
self.assertEqual(child.value, 'xx')
+
+ def test_defer_inheritance_pk_chaining(self):
+ """
+ When an inherited model is fetched from the DB, its PK is also fetched.
+ When getting the PK of the parent model it is useful to use the already
+ fetched parent model PK if it happens to be available. Tests that this
+ is done.
+ """
+ s1 = Secondary.objects.create(first="x1", second="y1")
+ bc = BigChild.objects.create(name="b1", value="foo", related=s1,
+ other="bar")
+ bc_deferred = BigChild.objects.only('name').get(pk=bc.pk)
+ with self.assertNumQueries(0):
+ bc_deferred.id
+ self.assertEqual(bc_deferred.pk, bc_deferred.id)
diff --git a/tests/modeltests/field_subclassing/tests.py b/tests/modeltests/field_subclassing/tests.py
index c6a2335f37..48755123f2 100644
--- a/tests/modeltests/field_subclassing/tests.py
+++ b/tests/modeltests/field_subclassing/tests.py
@@ -18,6 +18,10 @@ class CustomField(TestCase):
self.assertEqual(d.data, [1, 2, 3])
d = DataModel.objects.defer("data").get(pk=d.pk)
+ self.assertTrue(isinstance(d.data, list))
+ self.assertEqual(d.data, [1, 2, 3])
+ # Refetch for save
+ d = DataModel.objects.defer("data").get(pk=d.pk)
d.save()
d = DataModel.objects.get(pk=d.pk)
diff --git a/tests/modeltests/files/tests.py b/tests/modeltests/files/tests.py
index 3bfe193610..837723a049 100644
--- a/tests/modeltests/files/tests.py
+++ b/tests/modeltests/files/tests.py
@@ -1,5 +1,6 @@
from __future__ import absolute_import
+import gzip
import shutil
import tempfile
@@ -8,11 +9,12 @@ from django.core.files import File
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
+from django.utils import unittest
from .models import Storage, temp_storage, temp_storage_location
-class FileTests(TestCase):
+class FileStorageTests(TestCase):
def tearDown(self):
shutil.rmtree(temp_storage_location)
@@ -106,6 +108,8 @@ class FileTests(TestCase):
obj3.default.delete()
obj4.random.delete()
+
+class FileTests(unittest.TestCase):
def test_context_manager(self):
orig_file = tempfile.TemporaryFile()
base_file = File(orig_file)
@@ -114,3 +118,10 @@ class FileTests(TestCase):
self.assertFalse(f.closed)
self.assertTrue(f.closed)
self.assertTrue(orig_file.closed)
+
+ def test_file_mode(self):
+ # Should not set mode to None if it is not present.
+ # See #14681, stdlib gzip module crashes if mode is set to None
+ file = SimpleUploadedFile("mode_test.txt", "content")
+ self.assertFalse(hasattr(file, 'mode'))
+ g = gzip.GzipFile(fileobj=file)
diff --git a/tests/modeltests/fixtures/tests.py b/tests/modeltests/fixtures/tests.py
index d22010d7a0..478bbe9129 100644
--- a/tests/modeltests/fixtures/tests.py
+++ b/tests/modeltests/fixtures/tests.py
@@ -54,25 +54,25 @@ class FixtureLoadingTests(TestCase):
])
# Dump the current contents of the database as a JSON fixture
- self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]')
+ self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]')
# Try just dumping the contents of fixtures.Category
self._dumpdata_assert(['fixtures.Category'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}]')
# ...and just fixtures.Article
- self._dumpdata_assert(['fixtures.Article'], '[{"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}]')
+ self._dumpdata_assert(['fixtures.Article'], '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]')
# ...and both
- self._dumpdata_assert(['fixtures.Category', 'fixtures.Article'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}]')
+ self._dumpdata_assert(['fixtures.Category', 'fixtures.Article'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]')
# Specify a specific model twice
- self._dumpdata_assert(['fixtures.Article', 'fixtures.Article'], '[{"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}]')
+ self._dumpdata_assert(['fixtures.Article', 'fixtures.Article'], '[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}]')
# Specify a dump that specifies Article both explicitly and implicitly
- self._dumpdata_assert(['fixtures.Article', 'fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]')
+ self._dumpdata_assert(['fixtures.Article', 'fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]')
# Same again, but specify in the reverse order
- self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]')
+ self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]')
# Specify one model from one application, and an entire other application.
self._dumpdata_assert(['fixtures.Category', 'sites'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}]')
@@ -143,17 +143,17 @@ class FixtureLoadingTests(TestCase):
])
# By default, you get raw keys on dumpdata
- self._dumpdata_assert(['fixtures.book'], '[{"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}, {"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [3, 1]}}]')
+ self._dumpdata_assert(['fixtures.book'], '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [3, 1]}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]')
# But you can get natural keys if you ask for them and they are available
- self._dumpdata_assert(['fixtures.book'], '[{"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}, {"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_keys=True)
+ self._dumpdata_assert(['fixtures.book'], '[{"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]', natural_keys=True)
# Dump the current contents of the database as a JSON fixture
- self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 5, "model": "fixtures.article", "fields": {"headline": "XML identified as leading cause of cancer", "pub_date": "2006-06-16T16:00:00"}}, {"pk": 4, "model": "fixtures.article", "fields": {"headline": "Django conquers world!", "pub_date": "2006-06-16T15:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker on TV is great!", "pub_date": "2006-06-16T11:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "legal", "tagged_id": 3}}, {"pk": 3, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "django", "tagged_id": 4}}, {"pk": 4, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "world domination", "tagged_id": 4}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Artist formerly known as \\"Prince\\""}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 1, "model": "fixtures.visa", "fields": {"person": ["Django Reinhardt"], "permissions": [["add_user", "auth", "user"], ["change_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 2, "model": "fixtures.visa", "fields": {"person": ["Stephane Grappelli"], "permissions": [["add_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 3, "model": "fixtures.visa", "fields": {"person": ["Artist formerly known as \\"Prince\\""], "permissions": [["change_user", "auth", "user"]]}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}, {"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}]', natural_keys=True)
+ self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker on TV is great!", "pub_date": "2006-06-16T11:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}, {"pk": 4, "model": "fixtures.article", "fields": {"headline": "Django conquers world!", "pub_date": "2006-06-16T15:00:00"}}, {"pk": 5, "model": "fixtures.article", "fields": {"headline": "XML identified as leading cause of cancer", "pub_date": "2006-06-16T16:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "legal", "tagged_id": 3}}, {"pk": 3, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "django", "tagged_id": 4}}, {"pk": 4, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "world domination", "tagged_id": 4}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Artist formerly known as \\"Prince\\""}}, {"pk": 1, "model": "fixtures.visa", "fields": {"person": ["Django Reinhardt"], "permissions": [["add_user", "auth", "user"], ["change_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 2, "model": "fixtures.visa", "fields": {"person": ["Stephane Grappelli"], "permissions": [["add_user", "auth", "user"], ["delete_user", "auth", "user"]]}}, {"pk": 3, "model": "fixtures.visa", "fields": {"person": ["Artist formerly known as \\"Prince\\""], "permissions": [["change_user", "auth", "user"]]}}, {"pk": 1, "model": "fixtures.book", "fields": {"name": "Music for all ages", "authors": [["Artist formerly known as \\"Prince\\""], ["Django Reinhardt"]]}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]', natural_keys=True)
# Dump the current contents of the database as an XML fixture
self._dumpdata_assert(['fixtures'], """<?xml version="1.0" encoding="utf-8"?>
-<django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="5" model="fixtures.article"><field type="CharField" name="headline">XML identified as leading cause of cancer</field><field type="DateTimeField" name="pub_date">2006-06-16T16:00:00</field></object><object pk="4" model="fixtures.article"><field type="CharField" name="headline">Django conquers world!</field><field type="DateTimeField" name="pub_date">2006-06-16T15:00:00</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Copyright is fine the way it is</field><field type="DateTimeField" name="pub_date">2006-06-16T14:00:00</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker on TV is great!</field><field type="DateTimeField" name="pub_date">2006-06-16T11:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">legal</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="3" model="fixtures.tag"><field type="CharField" name="name">django</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="4" model="fixtures.tag"><field type="CharField" name="name">world domination</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Artist formerly known as "Prince"</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object><object pk="1" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Django Reinhardt</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="2" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Stephane Grappelli</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="3" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Artist formerly known as "Prince"</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="10" model="fixtures.book"><field type="CharField" name="name">Achieving self-awareness of Python programs</field><field to="fixtures.person" name="authors" rel="ManyToManyRel"></field></object><object pk="1" model="fixtures.book"><field type="CharField" name="name">Music for all ages</field><field to="fixtures.person" name="authors" rel="ManyToManyRel"><object><natural>Artist formerly known as "Prince"</natural></object><object><natural>Django Reinhardt</natural></object></field></object></django-objects>""", format='xml', natural_keys=True)
+<django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker on TV is great!</field><field type="DateTimeField" name="pub_date">2006-06-16T11:00:00</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Copyright is fine the way it is</field><field type="DateTimeField" name="pub_date">2006-06-16T14:00:00</field></object><object pk="4" model="fixtures.article"><field type="CharField" name="headline">Django conquers world!</field><field type="DateTimeField" name="pub_date">2006-06-16T15:00:00</field></object><object pk="5" model="fixtures.article"><field type="CharField" name="headline">XML identified as leading cause of cancer</field><field type="DateTimeField" name="pub_date">2006-06-16T16:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">legal</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="3" model="fixtures.tag"><field type="CharField" name="name">django</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="4" model="fixtures.tag"><field type="CharField" name="name">world domination</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">4</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Artist formerly known as "Prince"</field></object><object pk="1" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Django Reinhardt</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="2" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Stephane Grappelli</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>add_user</natural><natural>auth</natural><natural>user</natural></object><object><natural>delete_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="3" model="fixtures.visa"><field to="fixtures.person" name="person" rel="ManyToOneRel"><natural>Artist formerly known as "Prince"</natural></field><field to="auth.permission" name="permissions" rel="ManyToManyRel"><object><natural>change_user</natural><natural>auth</natural><natural>user</natural></object></field></object><object pk="1" model="fixtures.book"><field type="CharField" name="name">Music for all ages</field><field to="fixtures.person" name="authors" rel="ManyToManyRel"><object><natural>Artist formerly known as "Prince"</natural></object><object><natural>Django Reinhardt</natural></object></field></object><object pk="10" model="fixtures.book"><field type="CharField" name="name">Achieving self-awareness of Python programs</field><field to="fixtures.person" name="authors" rel="ManyToManyRel"></field></object></django-objects>""", format='xml', natural_keys=True)
def test_dumpdata_with_excludes(self):
# Load fixture1 which has a site, two articles, and a category
@@ -185,14 +185,14 @@ class FixtureLoadingTests(TestCase):
exclude_list=['fixtures.Article', 'fixtures.Book', 'sites'])
# Excluding a bogus app should throw an error
- self.assertRaises(SystemExit,
+ self.assertRaises(management.CommandError,
self._dumpdata_assert,
['fixtures', 'sites'],
'',
exclude_list=['foo_app'])
# Excluding a bogus model should throw an error
- self.assertRaises(SystemExit,
+ self.assertRaises(management.CommandError,
self._dumpdata_assert,
['fixtures', 'sites'],
'',
@@ -292,11 +292,11 @@ class FixtureLoadingTests(TestCase):
])
# Dump the current contents of the database as a JSON fixture
- self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "law", "tagged_id": 3}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Prince"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]', natural_keys=True)
+ self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "law", "tagged_id": 3}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Prince"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]', natural_keys=True)
# Dump the current contents of the database as an XML fixture
self._dumpdata_assert(['fixtures'], """<?xml version="1.0" encoding="utf-8"?>
-<django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Time to reform copyright</field><field type="DateTimeField" name="pub_date">2006-06-16T13:00:00</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker has no place on ESPN</field><field type="DateTimeField" name="pub_date">2006-06-16T12:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">law</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Prince</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object><object pk="10" model="fixtures.book"><field type="CharField" name="name">Achieving self-awareness of Python programs</field><field to="fixtures.person" name="authors" rel="ManyToManyRel"></field></object></django-objects>""", format='xml', natural_keys=True)
+<django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker has no place on ESPN</field><field type="DateTimeField" name="pub_date">2006-06-16T12:00:00</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Time to reform copyright</field><field type="DateTimeField" name="pub_date">2006-06-16T13:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">law</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Prince</field></object><object pk="10" model="fixtures.book"><field type="CharField" name="name">Achieving self-awareness of Python programs</field><field to="fixtures.person" name="authors" rel="ManyToManyRel"></field></object></django-objects>""", format='xml', natural_keys=True)
class FixtureTransactionTests(TransactionTestCase):
def _dumpdata_assert(self, args, output, format='json'):
@@ -329,7 +329,7 @@ class FixtureTransactionTests(TransactionTestCase):
])
# Dump the current contents of the database as a JSON fixture
- self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]')
+ self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]')
# Load fixture 4 (compressed), using format discovery
management.call_command('loaddata', 'fixture4', verbosity=0, commit=False)
diff --git a/tests/modeltests/known_related_objects/__init__.py b/tests/modeltests/known_related_objects/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/modeltests/known_related_objects/__init__.py
diff --git a/tests/modeltests/known_related_objects/fixtures/tournament.json b/tests/modeltests/known_related_objects/fixtures/tournament.json
new file mode 100644
index 0000000000..2f2b1c5627
--- /dev/null
+++ b/tests/modeltests/known_related_objects/fixtures/tournament.json
@@ -0,0 +1,65 @@
+[
+ {
+ "pk": 1,
+ "model": "known_related_objects.tournament",
+ "fields": {
+ "name": "Tourney 1"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "known_related_objects.tournament",
+ "fields": {
+ "name": "Tourney 2"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "known_related_objects.pool",
+ "fields": {
+ "tournament": 1,
+ "name": "T1 Pool 1"
+ }
+ },
+ {
+ "pk": 2,
+ "model": "known_related_objects.pool",
+ "fields": {
+ "tournament": 1,
+ "name": "T1 Pool 2"
+ }
+ },
+ {
+ "pk": 3,
+ "model": "known_related_objects.pool",
+ "fields": {
+ "tournament": 2,
+ "name": "T2 Pool 1"
+ }
+ },
+ {
+ "pk": 4,
+ "model": "known_related_objects.pool",
+ "fields": {
+ "tournament": 2,
+ "name": "T2 Pool 2"
+ }
+ },
+ {
+ "pk": 1,
+ "model": "known_related_objects.poolstyle",
+ "fields": {
+ "name": "T1 Pool 2 Style",
+ "pool": 2
+ }
+ },
+ {
+ "pk": 2,
+ "model": "known_related_objects.poolstyle",
+ "fields": {
+ "name": "T2 Pool 1 Style",
+ "pool": 3
+ }
+ }
+]
+
diff --git a/tests/modeltests/known_related_objects/models.py b/tests/modeltests/known_related_objects/models.py
new file mode 100644
index 0000000000..4c516dd7e8
--- /dev/null
+++ b/tests/modeltests/known_related_objects/models.py
@@ -0,0 +1,19 @@
+"""
+Existing related object instance caching.
+
+Test that queries are not redone when going back through known relations.
+"""
+
+from django.db import models
+
+class Tournament(models.Model):
+ name = models.CharField(max_length=30)
+
+class Pool(models.Model):
+ name = models.CharField(max_length=30)
+ tournament = models.ForeignKey(Tournament)
+
+class PoolStyle(models.Model):
+ name = models.CharField(max_length=30)
+ pool = models.OneToOneField(Pool)
+
diff --git a/tests/modeltests/known_related_objects/tests.py b/tests/modeltests/known_related_objects/tests.py
new file mode 100644
index 0000000000..24feab2241
--- /dev/null
+++ b/tests/modeltests/known_related_objects/tests.py
@@ -0,0 +1,88 @@
+from __future__ import absolute_import
+
+from django.test import TestCase
+
+from .models import Tournament, Pool, PoolStyle
+
+class ExistingRelatedInstancesTests(TestCase):
+ fixtures = ['tournament.json']
+
+ def test_foreign_key(self):
+ with self.assertNumQueries(2):
+ tournament = Tournament.objects.get(pk=1)
+ pool = tournament.pool_set.all()[0]
+ self.assertIs(tournament, pool.tournament)
+
+ def test_foreign_key_prefetch_related(self):
+ with self.assertNumQueries(2):
+ tournament = (Tournament.objects.prefetch_related('pool_set').get(pk=1))
+ pool = tournament.pool_set.all()[0]
+ self.assertIs(tournament, pool.tournament)
+
+ def test_foreign_key_multiple_prefetch(self):
+ with self.assertNumQueries(2):
+ tournaments = list(Tournament.objects.prefetch_related('pool_set'))
+ pool1 = tournaments[0].pool_set.all()[0]
+ self.assertIs(tournaments[0], pool1.tournament)
+ pool2 = tournaments[1].pool_set.all()[0]
+ self.assertIs(tournaments[1], pool2.tournament)
+
+ def test_one_to_one(self):
+ with self.assertNumQueries(2):
+ style = PoolStyle.objects.get(pk=1)
+ pool = style.pool
+ self.assertIs(style, pool.poolstyle)
+
+ def test_one_to_one_select_related(self):
+ with self.assertNumQueries(1):
+ style = PoolStyle.objects.select_related('pool').get(pk=1)
+ pool = style.pool
+ self.assertIs(style, pool.poolstyle)
+
+ def test_one_to_one_multi_select_related(self):
+ with self.assertNumQueries(1):
+ poolstyles = list(PoolStyle.objects.select_related('pool'))
+ self.assertIs(poolstyles[0], poolstyles[0].pool.poolstyle)
+ self.assertIs(poolstyles[1], poolstyles[1].pool.poolstyle)
+
+ def test_one_to_one_prefetch_related(self):
+ with self.assertNumQueries(2):
+ style = PoolStyle.objects.prefetch_related('pool').get(pk=1)
+ pool = style.pool
+ self.assertIs(style, pool.poolstyle)
+
+ def test_one_to_one_multi_prefetch_related(self):
+ with self.assertNumQueries(2):
+ poolstyles = list(PoolStyle.objects.prefetch_related('pool'))
+ self.assertIs(poolstyles[0], poolstyles[0].pool.poolstyle)
+ self.assertIs(poolstyles[1], poolstyles[1].pool.poolstyle)
+
+ def test_reverse_one_to_one(self):
+ with self.assertNumQueries(2):
+ pool = Pool.objects.get(pk=2)
+ style = pool.poolstyle
+ self.assertIs(pool, style.pool)
+
+ def test_reverse_one_to_one_select_related(self):
+ with self.assertNumQueries(1):
+ pool = Pool.objects.select_related('poolstyle').get(pk=2)
+ style = pool.poolstyle
+ self.assertIs(pool, style.pool)
+
+ def test_reverse_one_to_one_prefetch_related(self):
+ with self.assertNumQueries(2):
+ pool = Pool.objects.prefetch_related('poolstyle').get(pk=2)
+ style = pool.poolstyle
+ self.assertIs(pool, style.pool)
+
+ def test_reverse_one_to_one_multi_select_related(self):
+ with self.assertNumQueries(1):
+ pools = list(Pool.objects.select_related('poolstyle'))
+ self.assertIs(pools[1], pools[1].poolstyle.pool)
+ self.assertIs(pools[2], pools[2].poolstyle.pool)
+
+ def test_reverse_one_to_one_multi_prefetch_related(self):
+ with self.assertNumQueries(2):
+ pools = list(Pool.objects.prefetch_related('poolstyle'))
+ self.assertIs(pools[1], pools[1].poolstyle.pool)
+ self.assertIs(pools[2], pools[2].poolstyle.pool)
diff --git a/tests/modeltests/model_forms/tests.py b/tests/modeltests/model_forms/tests.py
index fdaae5b852..af8bcbca4e 100644
--- a/tests/modeltests/model_forms/tests.py
+++ b/tests/modeltests/model_forms/tests.py
@@ -1126,7 +1126,7 @@ class OldFormForXTests(TestCase):
f = TextFileForm(
data={'description': u'Assistance'},
- files={'file': SimpleUploadedFile('test1.txt', 'hello world')})
+ files={'file': SimpleUploadedFile('test1.txt', b'hello world')})
self.assertEqual(f.is_valid(), True)
self.assertEqual(type(f.cleaned_data['file']), SimpleUploadedFile)
instance = f.save()
@@ -1135,7 +1135,7 @@ class OldFormForXTests(TestCase):
instance.file.delete()
f = TextFileForm(
data={'description': u'Assistance'},
- files={'file': SimpleUploadedFile('test1.txt', 'hello world')})
+ files={'file': SimpleUploadedFile('test1.txt', b'hello world')})
self.assertEqual(f.is_valid(), True)
self.assertEqual(type(f.cleaned_data['file']), SimpleUploadedFile)
instance = f.save()
@@ -1144,7 +1144,7 @@ class OldFormForXTests(TestCase):
# Check if the max_length attribute has been inherited from the model.
f = TextFileForm(
data={'description': u'Assistance'},
- files={'file': SimpleUploadedFile('test-maxlength.txt', 'hello world')})
+ files={'file': SimpleUploadedFile('test-maxlength.txt', b'hello world')})
self.assertEqual(f.is_valid(), False)
# Edit an instance that already has the file defined in the model. This will not
@@ -1165,7 +1165,7 @@ class OldFormForXTests(TestCase):
f = TextFileForm(
data={'description': u'Assistance'},
- files={'file': SimpleUploadedFile('test2.txt', 'hello world')}, instance=instance)
+ files={'file': SimpleUploadedFile('test2.txt', b'hello world')}, instance=instance)
self.assertEqual(f.is_valid(), True)
instance = f.save()
self.assertEqual(instance.file.name, 'tests/test2.txt')
@@ -1174,7 +1174,7 @@ class OldFormForXTests(TestCase):
instance.file.delete()
f = TextFileForm(
data={'description': u'Assistance'},
- files={'file': SimpleUploadedFile('test2.txt', 'hello world')})
+ files={'file': SimpleUploadedFile('test2.txt', b'hello world')})
self.assertEqual(f.is_valid(), True)
instance = f.save()
self.assertEqual(instance.file.name, 'tests/test2.txt')
@@ -1193,7 +1193,7 @@ class OldFormForXTests(TestCase):
f = TextFileForm(
data={'description': u'Assistance'},
- files={'file': SimpleUploadedFile('test3.txt', 'hello world')}, instance=instance)
+ files={'file': SimpleUploadedFile('test3.txt', b'hello world')}, instance=instance)
self.assertEqual(f.is_valid(), True)
instance = f.save()
self.assertEqual(instance.file.name, 'tests/test3.txt')
@@ -1215,7 +1215,7 @@ class OldFormForXTests(TestCase):
f = TextFileForm(
data={'description': u'Assistance'},
- files={'file': SimpleUploadedFile('test3.txt', 'hello world')})
+ files={'file': SimpleUploadedFile('test3.txt', b'hello world')})
self.assertEqual(f.is_valid(), True)
instance = f.save()
self.assertEqual(instance.file.name, 'tests/test3.txt')
diff --git a/tests/modeltests/model_inheritance/tests.py b/tests/modeltests/model_inheritance/tests.py
index 2e1a7a5a9c..695d3f836c 100644
--- a/tests/modeltests/model_inheritance/tests.py
+++ b/tests/modeltests/model_inheritance/tests.py
@@ -275,3 +275,21 @@ class ModelInheritanceTests(TestCase):
def test_mixin_init(self):
m = MixinModel()
self.assertEqual(m.other_attr, 1)
+
+ def test_update_query_counts(self):
+ """
+ Test that update queries do not generate non-necessary queries.
+ Refs #18304.
+ """
+ c = Chef.objects.create(name="Albert")
+ ir = ItalianRestaurant.objects.create(
+ name="Ristorante Miron",
+ address="1234 W. Ash",
+ serves_hot_dogs=False,
+ serves_pizza=False,
+ serves_gnocchi=True,
+ rating=4,
+ chef=c
+ )
+ with self.assertNumQueries(6):
+ ir.save()
diff --git a/tests/modeltests/serializers/tests.py b/tests/modeltests/serializers/tests.py
index dac098763c..e792c944a1 100644
--- a/tests/modeltests/serializers/tests.py
+++ b/tests/modeltests/serializers/tests.py
@@ -113,8 +113,8 @@ class SerializersTestBase(object):
Tests the ability to create new objects by
modifying serialized content.
"""
- old_headline = "Poker has no place on ESPN"
- new_headline = "Poker has no place on television"
+ old_headline = b"Poker has no place on ESPN"
+ new_headline = b"Poker has no place on television"
serial_str = serializers.serialize(self.serializer_name,
Article.objects.all())
serial_str = serial_str.replace(old_headline, new_headline)
@@ -284,7 +284,7 @@ class SerializersTransactionTestBase(object):
class XmlSerializerTestCase(SerializersTestBase, TestCase):
serializer_name = "xml"
- pkless_str = """<?xml version="1.0" encoding="utf-8"?>
+ pkless_str = b"""<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
<object model="serializers.category">
<field type="CharField" name="name">Reference</field>
@@ -330,7 +330,7 @@ class XmlSerializerTestCase(SerializersTestBase, TestCase):
class XmlSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase):
serializer_name = "xml"
- fwd_ref_str = """<?xml version="1.0" encoding="utf-8"?>
+ fwd_ref_str = b"""<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
<object pk="1" model="serializers.article">
<field to="serializers.author" name="author" rel="ManyToOneRel">1</field>
@@ -350,7 +350,7 @@ class XmlSerializerTransactionTestCase(SerializersTransactionTestBase, Transacti
class JsonSerializerTestCase(SerializersTestBase, TestCase):
serializer_name = "json"
- pkless_str = """[{"pk": null, "model": "serializers.category", "fields": {"name": "Reference"}}]"""
+ pkless_str = b"""[{"pk": null, "model": "serializers.category", "fields": {"name": "Reference"}}]"""
@staticmethod
def _validate_output(serial_str):
@@ -380,7 +380,7 @@ class JsonSerializerTestCase(SerializersTestBase, TestCase):
class JsonSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase):
serializer_name = "json"
- fwd_ref_str = """[
+ fwd_ref_str = b"""[
{
"pk": 1,
"model": "serializers.article",
@@ -413,7 +413,7 @@ except ImportError:
else:
class YamlSerializerTestCase(SerializersTestBase, TestCase):
serializer_name = "yaml"
- fwd_ref_str = """- fields:
+ fwd_ref_str = b"""- fields:
headline: Forward references pose no problem
pub_date: 2006-06-16 15:00:00
categories: [1]
@@ -429,7 +429,7 @@ else:
pk: 1
model: serializers.author"""
- pkless_str = """- fields:
+ pkless_str = b"""- fields:
name: Reference
pk: null
model: serializers.category"""
@@ -469,7 +469,7 @@ else:
class YamlSerializerTransactionTestCase(SerializersTransactionTestBase, TransactionTestCase):
serializer_name = "yaml"
- fwd_ref_str = """- fields:
+ fwd_ref_str = b"""- fields:
headline: Forward references pose no problem
pub_date: 2006-06-16 15:00:00
categories: [1]
diff --git a/tests/modeltests/str/tests.py b/tests/modeltests/str/tests.py
index 9f6cf7ad96..1b0eb0972f 100644
--- a/tests/modeltests/str/tests.py
+++ b/tests/modeltests/str/tests.py
@@ -11,11 +11,11 @@ from .models import Article, InternationalArticle
class SimpleTests(TestCase):
def test_basic(self):
a = Article.objects.create(
- headline='Area man programs in Python',
+ headline=b'Area man programs in Python',
pub_date=datetime.datetime(2005, 7, 28)
)
- self.assertEqual(str(a), 'Area man programs in Python')
- self.assertEqual(repr(a), '<Article: Area man programs in Python>')
+ self.assertEqual(str(a), b'Area man programs in Python')
+ self.assertEqual(repr(a), b'<Article: Area man programs in Python>')
def test_international(self):
a = InternationalArticle.objects.create(
@@ -23,4 +23,4 @@ class SimpleTests(TestCase):
pub_date=datetime.datetime(2005, 7, 28)
)
# The default str() output will be the UTF-8 encoded output of __unicode__().
- self.assertEqual(str(a), 'Girl wins \xe2\x82\xac12.500 in lottery') \ No newline at end of file
+ self.assertEqual(str(a), b'Girl wins \xe2\x82\xac12.500 in lottery')
diff --git a/tests/modeltests/update_only_fields/tests.py b/tests/modeltests/update_only_fields/tests.py
index 8609821a44..e843bd7ab9 100644
--- a/tests/modeltests/update_only_fields/tests.py
+++ b/tests/modeltests/update_only_fields/tests.py
@@ -1,6 +1,6 @@
from __future__ import absolute_import
-from django.test import TestCase, skipUnlessDBFeature
+from django.test import TestCase
from django.db.models.signals import pre_save, post_save
from .models import Person, Employee, ProxyEmployee, Profile, Account
@@ -123,9 +123,6 @@ class UpdateOnlyFieldsTests(TestCase):
self.assertEqual(len(pre_save_data), 0)
self.assertEqual(len(post_save_data), 0)
- # A bug in SQLUpdateCompiler prevents this test from succeeding on MySQL
- # Require update_can_self_select for this test for now. Refs #18304.
- @skipUnlessDBFeature('update_can_self_select')
def test_num_queries_inheritance(self):
s = Employee.objects.create(name='Sara', gender='F')
s.employee_num = 1
diff --git a/tests/modeltests/user_commands/management/commands/dance.py b/tests/modeltests/user_commands/management/commands/dance.py
index 4ad5579e1e..911530d223 100644
--- a/tests/modeltests/user_commands/management/commands/dance.py
+++ b/tests/modeltests/user_commands/management/commands/dance.py
@@ -1,6 +1,6 @@
from optparse import make_option
-from django.core.management.base import BaseCommand
+from django.core.management.base import BaseCommand, CommandError
class Command(BaseCommand):
@@ -8,11 +8,13 @@ class Command(BaseCommand):
args = ''
requires_model_validation = True
- option_list =[
+ option_list = BaseCommand.option_list + (
make_option("-s", "--style", default="Rock'n'Roll"),
make_option("-x", "--example")
- ]
+ )
def handle(self, *args, **options):
example = options["example"]
+ if example == "raise":
+ raise CommandError()
self.stdout.write("I don't feel like dancing %s." % options["style"])
diff --git a/tests/modeltests/user_commands/tests.py b/tests/modeltests/user_commands/tests.py
index 896dd667ff..509f13f62f 100644
--- a/tests/modeltests/user_commands/tests.py
+++ b/tests/modeltests/user_commands/tests.py
@@ -1,3 +1,4 @@
+import sys
from StringIO import StringIO
from django.core import management
@@ -11,13 +12,13 @@ class CommandTests(TestCase):
out = StringIO()
management.call_command('dance', stdout=out)
self.assertEqual(out.getvalue(),
- "I don't feel like dancing Rock'n'Roll.")
+ "I don't feel like dancing Rock'n'Roll.\n")
def test_command_style(self):
out = StringIO()
management.call_command('dance', style='Jive', stdout=out)
self.assertEqual(out.getvalue(),
- "I don't feel like dancing Jive.")
+ "I don't feel like dancing Jive.\n")
def test_language_preserved(self):
out = StringIO()
@@ -26,4 +27,20 @@ class CommandTests(TestCase):
self.assertEqual(translation.get_language(), 'fr')
def test_explode(self):
+ """ Test that an unknown command raises CommandError """
self.assertRaises(CommandError, management.call_command, ('explode',))
+
+ def test_system_exit(self):
+ """ Exception raised in a command should raise CommandError with
+ call_command, but SystemExit when run from command line
+ """
+ with self.assertRaises(CommandError):
+ management.call_command('dance', example="raise")
+ old_stderr = sys.stderr
+ sys.stderr = err = StringIO()
+ try:
+ with self.assertRaises(SystemExit):
+ management.ManagementUtility(['manage.py', 'dance', '--example=raise']).execute()
+ finally:
+ sys.stderr = old_stderr
+ self.assertIn("CommandError", err.getvalue())
diff --git a/tests/modeltests/validation/test_error_messages.py b/tests/modeltests/validation/test_error_messages.py
index 04ad7aadf7..4aea3d52de 100644
--- a/tests/modeltests/validation/test_error_messages.py
+++ b/tests/modeltests/validation/test_error_messages.py
@@ -1,3 +1,4 @@
+# -*- encoding: utf-8 -*-
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.unittest import TestCase
@@ -5,142 +6,89 @@ from django.utils.unittest import TestCase
class ValidationMessagesTest(TestCase):
+ def _test_validation_messages(self, field, value, expected):
+ with self.assertRaises(ValidationError) as cm:
+ field.clean(value, None)
+ self.assertEqual(cm.exception.messages, expected)
+
def test_autofield_field_raises_error_message(self):
f = models.AutoField(primary_key=True)
- self.assertRaises(ValidationError, f.clean, 'foo', None)
- try:
- f.clean('foo', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [u"'foo' value must be an integer."])
+ self._test_validation_messages(f, u'fõo',
+ [u"'fõo' value must be an integer."])
# primary_key must be True. Refs #12467.
- self.assertRaises(AssertionError, models.AutoField, 'primary_key', False)
- try:
+ with self.assertRaisesRegexp(AssertionError,
+ "AutoFields must have primary_key=True."):
models.AutoField(primary_key=False)
- except AssertionError as e:
- self.assertEqual(str(e), "AutoFields must have primary_key=True.")
def test_integer_field_raises_error_message(self):
f = models.IntegerField()
- self.assertRaises(ValidationError, f.clean, 'foo', None)
- try:
- f.clean('foo', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [u"'foo' value must be an integer."])
+ self._test_validation_messages(f, u'fõo',
+ [u"'fõo' value must be an integer."])
def test_boolean_field_raises_error_message(self):
f = models.BooleanField()
- self.assertRaises(ValidationError, f.clean, 'foo', None)
- try:
- f.clean('foo', None)
- except ValidationError as e:
- self.assertEqual(e.messages,
- [u"'foo' value must be either True or False."])
+ self._test_validation_messages(f, u'fõo',
+ [u"'fõo' value must be either True or False."])
def test_float_field_raises_error_message(self):
f = models.FloatField()
- self.assertRaises(ValidationError, f.clean, 'foo', None)
- try:
- f.clean('foo', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [u"'foo' value must be a float."])
+ self._test_validation_messages(f, u'fõo',
+ [u"'fõo' value must be a float."])
def test_decimal_field_raises_error_message(self):
f = models.DecimalField()
- self.assertRaises(ValidationError, f.clean, 'foo', None)
- try:
- f.clean('foo', None)
- except ValidationError as e:
- self.assertEqual(e.messages,
- [u"'foo' value must be a decimal number."])
+ self._test_validation_messages(f, u'fõo',
+ [u"'fõo' value must be a decimal number."])
def test_null_boolean_field_raises_error_message(self):
f = models.NullBooleanField()
- self.assertRaises(ValidationError, f.clean, 'foo', None)
- try:
- f.clean('foo', None)
- except ValidationError as e:
- self.assertEqual(e.messages,
- [u"'foo' value must be either None, True or False."])
+ self._test_validation_messages(f, u'fõo',
+ [u"'fõo' value must be either None, True or False."])
def test_date_field_raises_error_message(self):
f = models.DateField()
- self.assertRaises(ValidationError, f.clean, 'foo', None)
- try:
- f.clean('foo', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [
- u"'foo' value has an invalid date format. "
- u"It must be in YYYY-MM-DD format."])
+ self._test_validation_messages(f, u'fõo',
+ [u"'fõo' value has an invalid date format. "
+ u"It must be in YYYY-MM-DD format."])
- self.assertRaises(ValidationError, f.clean, 'aaaa-10-10', None)
- try:
- f.clean('aaaa-10-10', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [
- u"'aaaa-10-10' value has an invalid date format. "
- u"It must be in YYYY-MM-DD format."])
+ self._test_validation_messages(f, 'aaaa-10-10',
+ [u"'aaaa-10-10' value has an invalid date format. "
+ u"It must be in YYYY-MM-DD format."])
- self.assertRaises(ValidationError, f.clean, '2011-13-10', None)
- try:
- f.clean('2011-13-10', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [
- u"'2011-13-10' value has the correct format (YYYY-MM-DD) "
- u"but it is an invalid date."])
+ self._test_validation_messages(f, '2011-13-10',
+ [u"'2011-13-10' value has the correct format (YYYY-MM-DD) "
+ u"but it is an invalid date."])
- self.assertRaises(ValidationError, f.clean, '2011-10-32', None)
- try:
- f.clean('2011-10-32', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [
- u"'2011-10-32' value has the correct format (YYYY-MM-DD) "
- u"but it is an invalid date."])
+ self._test_validation_messages(f, '2011-10-32',
+ [u"'2011-10-32' value has the correct format (YYYY-MM-DD) "
+ u"but it is an invalid date."])
def test_datetime_field_raises_error_message(self):
f = models.DateTimeField()
# Wrong format
- self.assertRaises(ValidationError, f.clean, 'foo', None)
- try:
- f.clean('foo', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [
- u"'foo' value has an invalid format. It must be "
- u"in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format."])
+ self._test_validation_messages(f, u'fõo',
+ [u"'fõo' value has an invalid format. It must be "
+ u"in YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format."])
# Correct format but invalid date
- self.assertRaises(ValidationError, f.clean, '2011-10-32', None)
- try:
- f.clean('2011-10-32', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [
- u"'2011-10-32' value has the correct format "
- u"(YYYY-MM-DD) but it is an invalid date."])
+ self._test_validation_messages(f, '2011-10-32',
+ [u"'2011-10-32' value has the correct format "
+ u"(YYYY-MM-DD) but it is an invalid date."])
# Correct format but invalid date/time
- self.assertRaises(ValidationError, f.clean, '2011-10-32 10:10', None)
- try:
- f.clean('2011-10-32 10:10', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [
- u"'2011-10-32 10:10' value has the correct format "
- u"(YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) "
- u"but it is an invalid date/time."])
+ self._test_validation_messages(f, '2011-10-32 10:10',
+ [u"'2011-10-32 10:10' value has the correct format "
+ u"(YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) "
+ u"but it is an invalid date/time."])
def test_time_field_raises_error_message(self):
f = models.TimeField()
# Wrong format
- self.assertRaises(ValidationError, f.clean, 'foo', None)
- try:
- f.clean('foo', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [
- u"'foo' value has an invalid format. It must be in "
- u"HH:MM[:ss[.uuuuuu]] format."])
+ self._test_validation_messages(f, u'fõo',
+ [u"'fõo' value has an invalid format. It must be in "
+ u"HH:MM[:ss[.uuuuuu]] format."])
+
# Correct format but invalid time
- self.assertRaises(ValidationError, f.clean, '25:50', None)
- try:
- f.clean('25:50', None)
- except ValidationError as e:
- self.assertEqual(e.messages, [
- u"'25:50' value has the correct format "
- u"(HH:MM[:ss[.uuuuuu]]) but it is an invalid time."])
+ self._test_validation_messages(f, '25:50',
+ [u"'25:50' value has the correct format "
+ u"(HH:MM[:ss[.uuuuuu]]) but it is an invalid time."])
diff --git a/tests/regressiontests/admin_scripts/tests.py b/tests/regressiontests/admin_scripts/tests.py
index 98492ffbdd..ecb16df53a 100644
--- a/tests/regressiontests/admin_scripts/tests.py
+++ b/tests/regressiontests/admin_scripts/tests.py
@@ -13,13 +13,12 @@ import sys
from django import conf, bin, get_version
from django.conf import settings
+from django.db import connection
from django.test.simple import DjangoTestSuiteRunner
from django.utils import unittest
from django.test import LiveServerTestCase
test_dir = os.path.dirname(os.path.dirname(__file__))
-expected_query_re = re.compile(r'CREATE TABLE [`"]admin_scripts_article[`"]', re.IGNORECASE)
-
class AdminScriptTestCase(unittest.TestCase):
def write_settings(self, filename, apps=None, is_dir=False, sdict=None):
@@ -859,14 +858,18 @@ class ManageAlternateSettings(AdminScriptTestCase):
"alternate: manage.py builtin commands work with settings provided as argument"
args = ['sqlall', '--settings=alternate_settings', 'admin_scripts']
out, err = self.run_manage(args)
- self.assertRegexpMatches(out, expected_query_re)
+ expected = ('create table %s'
+ % connection.ops.quote_name('admin_scripts_article'))
+ self.assertTrue(expected.lower() in out.lower())
self.assertNoOutput(err)
def test_builtin_with_environment(self):
"alternate: manage.py builtin commands work if settings are provided in the environment"
args = ['sqlall', 'admin_scripts']
out, err = self.run_manage(args, 'alternate_settings')
- self.assertRegexpMatches(out, expected_query_re)
+ expected = ('create table %s'
+ % connection.ops.quote_name('admin_scripts_article'))
+ self.assertTrue(expected.lower() in out.lower())
self.assertNoOutput(err)
def test_builtin_with_bad_settings(self):
diff --git a/tests/regressiontests/admin_util/tests.py b/tests/regressiontests/admin_util/tests.py
index 8113f2e16d..055f494dcd 100644
--- a/tests/regressiontests/admin_util/tests.py
+++ b/tests/regressiontests/admin_util/tests.py
@@ -170,7 +170,7 @@ class UtilTests(unittest.TestCase):
)
self.assertEqual(
label_for_field("__str__", Article),
- "article"
+ b"article"
)
self.assertRaises(
diff --git a/tests/regressiontests/admin_widgets/tests.py b/tests/regressiontests/admin_widgets/tests.py
index 8de68b2404..be1d294051 100644
--- a/tests/regressiontests/admin_widgets/tests.py
+++ b/tests/regressiontests/admin_widgets/tests.py
@@ -280,7 +280,7 @@ class AdminFileWidgetTest(DjangoTestCase):
)
self.assertHTMLEqual(
- conditional_escape(w.render('test', SimpleUploadedFile('test', 'content'))),
+ conditional_escape(w.render('test', SimpleUploadedFile('test', b'content'))),
'<input type="file" name="test" />',
)
diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
index eec817c5a2..109e1a5bcc 100644
--- a/tests/regressiontests/backends/tests.py
+++ b/tests/regressiontests/backends/tests.py
@@ -89,6 +89,12 @@ class MySQLTests(TestCase):
else:
self.assertFalse(found_reset)
+ @unittest.skipUnless(connection.vendor == 'mysql',
+ "Test valid only for MySQL")
+ def test_server_version_connections(self):
+ connection.close()
+ connection.mysql_version
+ self.assertTrue(connection.connection is None)
class DateQuotingTest(TestCase):
@@ -397,6 +403,12 @@ class BackendTestCase(TestCase):
self.assertTrue(hasattr(connection.ops, 'connection'))
self.assertEqual(connection, connection.ops.connection)
+ def test_supports_needed_confirm(self):
+ connection.features.confirm()
+ self.assertIn(connection.features.supports_transactions, (True, False))
+ self.assertIn(connection.features.supports_stddev, (True, False))
+ self.assertIn(connection.features.can_introspect_foreign_keys, (True, False))
+
def test_duplicate_table_error(self):
""" Test that creating an existing table returns a DatabaseError """
cursor = connection.cursor()
diff --git a/tests/regressiontests/cache/tests.py b/tests/regressiontests/cache/tests.py
index 780718b487..88fe5471cf 100644
--- a/tests/regressiontests/cache/tests.py
+++ b/tests/regressiontests/cache/tests.py
@@ -7,7 +7,6 @@ from __future__ import absolute_import
import hashlib
import os
import re
-import StringIO
import tempfile
import time
import warnings
@@ -820,9 +819,14 @@ class DBCacheTests(BaseCacheTests, TransactionTestCase):
self.perform_cull_test(50, 18)
def test_second_call_doesnt_crash(self):
- err = StringIO.StringIO()
- management.call_command('createcachetable', self._table_name, verbosity=0, interactive=False, stderr=err)
- self.assertTrue("Cache table 'test cache table' could not be created" in err.getvalue())
+ with self.assertRaisesRegexp(management.CommandError,
+ "Cache table 'test cache table' could not be created"):
+ management.call_command(
+ 'createcachetable',
+ self._table_name,
+ verbosity=0,
+ interactive=False
+ )
@override_settings(USE_TZ=True)
diff --git a/tests/regressiontests/conditional_processing/models.py b/tests/regressiontests/conditional_processing/models.py
index f7f48bc9c8..97aeff5eaa 100644
--- a/tests/regressiontests/conditional_processing/models.py
+++ b/tests/regressiontests/conditional_processing/models.py
@@ -63,10 +63,10 @@ class ConditionalGet(TestCase):
def testIfMatch(self):
self.client.defaults['HTTP_IF_MATCH'] = '"%s"' % ETAG
- response = self.client.put('/condition/etag/', {'data': ''})
+ response = self.client.put('/condition/etag/')
self.assertEqual(response.status_code, 200)
self.client.defaults['HTTP_IF_MATCH'] = '"%s"' % EXPIRED_ETAG
- response = self.client.put('/condition/etag/', {'data': ''})
+ response = self.client.put('/condition/etag/')
self.assertEqual(response.status_code, 412)
def testBothHeaders(self):
diff --git a/tests/regressiontests/csrf_tests/tests.py b/tests/regressiontests/csrf_tests/tests.py
index d403951ae2..2d9b4f755f 100644
--- a/tests/regressiontests/csrf_tests/tests.py
+++ b/tests/regressiontests/csrf_tests/tests.py
@@ -47,7 +47,7 @@ class TestingHttpRequest(HttpRequest):
class CsrfViewMiddlewareTest(TestCase):
# The csrf token is potentially from an untrusted source, so could have
# characters that need dealing with.
- _csrf_id_cookie = "<1>\xc2\xa1"
+ _csrf_id_cookie = b"<1>\xc2\xa1"
_csrf_id = "1"
def _get_GET_no_csrf_cookie_request(self):
diff --git a/tests/regressiontests/file_storage/tests.py b/tests/regressiontests/file_storage/tests.py
index ce64c5de23..87035d96d7 100644
--- a/tests/regressiontests/file_storage/tests.py
+++ b/tests/regressiontests/file_storage/tests.py
@@ -127,7 +127,7 @@ class FileStorageTests(unittest.TestCase):
"""
self.assertFalse(self.storage.exists('test.file'))
- f = ContentFile('custom contents')
+ f = ContentFile(b'custom contents')
f_name = self.storage.save('test.file', f)
atime = self.storage.accessed_time(f_name)
@@ -143,7 +143,7 @@ class FileStorageTests(unittest.TestCase):
"""
self.assertFalse(self.storage.exists('test.file'))
- f = ContentFile('custom contents')
+ f = ContentFile(b'custom contents')
f_name = self.storage.save('test.file', f)
ctime = self.storage.created_time(f_name)
@@ -160,7 +160,7 @@ class FileStorageTests(unittest.TestCase):
"""
self.assertFalse(self.storage.exists('test.file'))
- f = ContentFile('custom contents')
+ f = ContentFile(b'custom contents')
f_name = self.storage.save('test.file', f)
mtime = self.storage.modified_time(f_name)
@@ -177,7 +177,7 @@ class FileStorageTests(unittest.TestCase):
"""
self.assertFalse(self.storage.exists('test.file'))
- f = ContentFile('custom contents')
+ f = ContentFile(b'custom contents')
f.name = 'test.file'
storage_f_name = self.storage.save(None, f)
@@ -194,11 +194,11 @@ class FileStorageTests(unittest.TestCase):
"""
self.assertFalse(self.storage.exists('path/to'))
self.storage.save('path/to/test.file',
- ContentFile('file saved with path'))
+ ContentFile(b'file saved with path'))
self.assertTrue(self.storage.exists('path/to'))
self.assertEqual(self.storage.open('path/to/test.file').read(),
- 'file saved with path')
+ b'file saved with path')
self.assertTrue(os.path.exists(
os.path.join(self.temp_dir, 'path', 'to', 'test.file')))
@@ -211,7 +211,7 @@ class FileStorageTests(unittest.TestCase):
"""
self.assertFalse(self.storage.exists('test.file'))
- f = ContentFile('custom contents')
+ f = ContentFile(b'custom contents')
f_name = self.storage.save('test.file', f)
self.assertEqual(self.storage.path(f_name),
@@ -246,8 +246,8 @@ class FileStorageTests(unittest.TestCase):
self.assertFalse(self.storage.exists('storage_test_2'))
self.assertFalse(self.storage.exists('storage_dir_1'))
- f = self.storage.save('storage_test_1', ContentFile('custom content'))
- f = self.storage.save('storage_test_2', ContentFile('custom content'))
+ f = self.storage.save('storage_test_1', ContentFile(b'custom content'))
+ f = self.storage.save('storage_test_2', ContentFile(b'custom content'))
os.mkdir(os.path.join(self.temp_dir, 'storage_dir_1'))
dirs, files = self.storage.listdir('')
@@ -304,18 +304,18 @@ class FileStorageTests(unittest.TestCase):
os.makedirs = fake_makedirs
self.storage.save('normal/test.file',
- ContentFile('saved normally'))
+ ContentFile(b'saved normally'))
self.assertEqual(self.storage.open('normal/test.file').read(),
- 'saved normally')
+ b'saved normally')
self.storage.save('raced/test.file',
- ContentFile('saved with race'))
+ ContentFile(b'saved with race'))
self.assertEqual(self.storage.open('raced/test.file').read(),
- 'saved with race')
+ b'saved with race')
# Check that OSErrors aside from EEXIST are still raised.
self.assertRaises(OSError,
- self.storage.save, 'error/test.file', ContentFile('not saved'))
+ self.storage.save, 'error/test.file', ContentFile(b'not saved'))
finally:
os.makedirs = real_makedirs
@@ -341,16 +341,16 @@ class FileStorageTests(unittest.TestCase):
try:
os.remove = fake_remove
- self.storage.save('normal.file', ContentFile('delete normally'))
+ self.storage.save('normal.file', ContentFile(b'delete normally'))
self.storage.delete('normal.file')
self.assertFalse(self.storage.exists('normal.file'))
- self.storage.save('raced.file', ContentFile('delete with race'))
+ self.storage.save('raced.file', ContentFile(b'delete with race'))
self.storage.delete('raced.file')
self.assertFalse(self.storage.exists('normal.file'))
# Check that OSErrors aside from ENOENT are still raised.
- self.storage.save('error.file', ContentFile('delete with error'))
+ self.storage.save('error.file', ContentFile(b'delete with error'))
self.assertRaises(OSError, self.storage.delete, 'error.file')
finally:
os.remove = real_remove
@@ -374,9 +374,9 @@ class CustomStorageTests(FileStorageTests):
storage_class = CustomStorage
def test_custom_get_available_name(self):
- first = self.storage.save('custom_storage', ContentFile('custom contents'))
+ first = self.storage.save('custom_storage', ContentFile(b'custom contents'))
self.assertEqual(first, 'custom_storage')
- second = self.storage.save('custom_storage', ContentFile('more contents'))
+ second = self.storage.save('custom_storage', ContentFile(b'more contents'))
self.assertEqual(second, 'custom_storage.2')
self.storage.delete(first)
self.storage.delete(second)
@@ -410,7 +410,7 @@ class FileSaveRaceConditionTest(unittest.TestCase):
shutil.rmtree(self.storage_dir)
def save_file(self, name):
- name = self.storage.save(name, SlowFile("Data"))
+ name = self.storage.save(name, SlowFile(b"Data"))
def test_race_condition(self):
self.thread.start()
@@ -433,7 +433,7 @@ class FileStoragePermissions(unittest.TestCase):
shutil.rmtree(self.storage_dir)
def test_file_upload_permissions(self):
- name = self.storage.save("the_file", ContentFile("data"))
+ name = self.storage.save("the_file", ContentFile(b"data"))
actual_mode = os.stat(self.storage.path(name))[0] & 0777
self.assertEqual(actual_mode, 0666)
@@ -453,8 +453,8 @@ class FileStoragePathParsing(unittest.TestCase):
sure we still mangle the file name instead of the directory name.
"""
- self.storage.save('dotted.path/test', ContentFile("1"))
- self.storage.save('dotted.path/test', ContentFile("2"))
+ self.storage.save('dotted.path/test', ContentFile(b"1"))
+ self.storage.save('dotted.path/test', ContentFile(b"2"))
self.assertFalse(os.path.exists(os.path.join(self.storage_dir, 'dotted_.path')))
self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 'dotted.path/test')))
@@ -465,8 +465,8 @@ class FileStoragePathParsing(unittest.TestCase):
File names with a dot as their first character don't have an extension,
and the underscore should get added to the end.
"""
- self.storage.save('dotted.path/.test', ContentFile("1"))
- self.storage.save('dotted.path/.test', ContentFile("2"))
+ self.storage.save('dotted.path/.test', ContentFile(b"1"))
+ self.storage.save('dotted.path/.test', ContentFile(b"2"))
self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 'dotted.path/.test')))
self.assertTrue(os.path.exists(os.path.join(self.storage_dir, 'dotted.path/.test_1')))
@@ -542,11 +542,11 @@ class ContentFileTestCase(unittest.TestCase):
Test that the constructor of ContentFile accepts 'name' (#16590).
"""
def test_content_file_default_name(self):
- self.assertEqual(ContentFile("content").name, None)
+ self.assertEqual(ContentFile(b"content").name, None)
def test_content_file_custom_name(self):
name = "I can have a name too!"
- self.assertEqual(ContentFile("content", name=name).name, name)
+ self.assertEqual(ContentFile(b"content", name=name).name, name)
class NoNameFileTestCase(unittest.TestCase):
"""
diff --git a/tests/regressiontests/file_uploads/tests.py b/tests/regressiontests/file_uploads/tests.py
index de552d88ec..c8de8035f9 100644
--- a/tests/regressiontests/file_uploads/tests.py
+++ b/tests/regressiontests/file_uploads/tests.py
@@ -24,7 +24,7 @@ UNICODE_FILENAME = u'test-0123456789_中文_Orléans.jpg'
class FileUploadTests(TestCase):
def test_simple_upload(self):
- with open(__file__) as fp:
+ with open(__file__, 'rb') as fp:
post_data = {
'name': 'Ringo',
'file_field': fp,
@@ -36,11 +36,11 @@ class FileUploadTests(TestCase):
tdir = tempfile.gettempdir()
file1 = tempfile.NamedTemporaryFile(suffix=".file1", dir=tdir)
- file1.write('a' * (2 ** 21))
+ file1.write(b'a' * (2 ** 21))
file1.seek(0)
file2 = tempfile.NamedTemporaryFile(suffix=".file2", dir=tdir)
- file2.write('a' * (10 * 2 ** 20))
+ file2.write(b'a' * (10 * 2 ** 20))
file2.seek(0)
post_data = {
@@ -89,7 +89,7 @@ class FileUploadTests(TestCase):
# This file contains chinese symbols and an accented char in the name.
with open(os.path.join(tdir, UNICODE_FILENAME.encode('utf-8')), 'w+b') as file1:
- file1.write('b' * (2 ** 10))
+ file1.write(b'b' * (2 ** 10))
file1.seek(0)
post_data = {
@@ -214,7 +214,7 @@ class FileUploadTests(TestCase):
'CONTENT_TYPE': client.MULTIPART_CONTENT,
'PATH_INFO': '/file_uploads/echo/',
'REQUEST_METHOD': 'POST',
- 'wsgi.input': client.FakePayload(''),
+ 'wsgi.input': client.FakePayload(b''),
}
got = json.loads(self.client.request(**r).content)
self.assertEqual(got, {})
@@ -222,12 +222,12 @@ class FileUploadTests(TestCase):
def test_custom_upload_handler(self):
# A small file (under the 5M quota)
smallfile = tempfile.NamedTemporaryFile()
- smallfile.write('a' * (2 ** 21))
+ smallfile.write(b'a' * (2 ** 21))
smallfile.seek(0)
# A big file (over the quota)
bigfile = tempfile.NamedTemporaryFile()
- bigfile.write('a' * (10 * 2 ** 20))
+ bigfile.write(b'a' * (10 * 2 ** 20))
bigfile.seek(0)
# Small file posting should work.
@@ -242,7 +242,7 @@ class FileUploadTests(TestCase):
def test_broken_custom_upload_handler(self):
f = tempfile.NamedTemporaryFile()
- f.write('a' * (2 ** 21))
+ f.write(b'a' * (2 ** 21))
f.seek(0)
# AttributeError: You cannot alter upload handlers after the upload has been processed.
@@ -255,15 +255,15 @@ class FileUploadTests(TestCase):
def test_fileupload_getlist(self):
file1 = tempfile.NamedTemporaryFile()
- file1.write('a' * (2 ** 23))
+ file1.write(b'a' * (2 ** 23))
file1.seek(0)
file2 = tempfile.NamedTemporaryFile()
- file2.write('a' * (2 * 2 ** 18))
+ file2.write(b'a' * (2 * 2 ** 18))
file2.seek(0)
file2a = tempfile.NamedTemporaryFile()
- file2a.write('a' * (5 * 2 ** 20))
+ file2a.write(b'a' * (5 * 2 ** 20))
file2a.seek(0)
response = self.client.post('/file_uploads/getlist_count/', {
@@ -299,14 +299,14 @@ class FileUploadTests(TestCase):
# this test would fail. So we need to know exactly what kind of error
# it raises when there is an attempt to read more than the available bytes:
try:
- client.FakePayload('a').read(2)
+ client.FakePayload(b'a').read(2)
except Exception as reference_error:
pass
# install the custom handler that tries to access request.POST
self.client.handler = POSTAccessingHandler()
- with open(__file__) as fp:
+ with open(__file__, 'rb') as fp:
post_data = {
'name': 'Ringo',
'file_field': fp,
@@ -374,7 +374,7 @@ class DirectoryCreationTests(unittest.TestCase):
"""Permission errors are not swallowed"""
os.chmod(temp_storage.location, 0500)
try:
- self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', 'x'))
+ self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', b'x'))
except OSError as err:
self.assertEqual(err.errno, errno.EACCES)
except Exception:
@@ -383,9 +383,9 @@ class DirectoryCreationTests(unittest.TestCase):
def test_not_a_directory(self):
"""The correct IOError is raised when the upload directory name exists but isn't a directory"""
# Create a file with the upload directory name
- open(UPLOAD_TO, 'w').close()
+ open(UPLOAD_TO, 'wb').close()
try:
- self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', 'x'))
+ self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', b'x'))
except IOError as err:
# The test needs to be done on a specific string as IOError
# is raised even without the patch (just not early enough)
diff --git a/tests/regressiontests/fixtures_regress/tests.py b/tests/regressiontests/fixtures_regress/tests.py
index 5c6f758b66..0e2cc3a9b2 100644
--- a/tests/regressiontests/fixtures_regress/tests.py
+++ b/tests/regressiontests/fixtures_regress/tests.py
@@ -185,25 +185,6 @@ class TestFixtures(TestCase):
"No fixture data found for 'empty'. (File format may be invalid.)\n"
)
- def test_abort_loaddata_on_error(self):
- """
- Test for ticket #4371 -- If any of the fixtures contain an error,
- loading is aborted.
- Validate that error conditions are caught correctly
- """
- stderr = BytesIO()
- management.call_command(
- 'loaddata',
- 'empty',
- verbosity=0,
- commit=False,
- stderr=stderr,
- )
- self.assertEqual(
- stderr.getvalue(),
- "No fixture data found for 'empty'. (File format may be invalid.)\n"
- )
-
def test_error_message(self):
"""
(Regression for #9011 - error message is correct)
diff --git a/tests/regressiontests/forms/tests/fields.py b/tests/regressiontests/forms/tests/fields.py
index a7d98ec7d4..4d442de382 100644
--- a/tests/regressiontests/forms/tests/fields.py
+++ b/tests/regressiontests/forms/tests/fields.py
@@ -478,6 +478,14 @@ class FieldsTests(SimpleTestCase):
self.assertRaisesMessage(ValidationError, "[u'Ensure this value has at most 10 characters (it has 11).']", f.clean, '12345678901')
self.assertRaisesMessage(ValidationError, "[u'Enter a valid value.']", f.clean, '12345a')
+ def test_regexfield_6(self):
+ """
+ Ensure that it works with unicode characters.
+ Refs #.
+ """
+ f = RegexField('^\w+$')
+ self.assertEqual(u'éèøçÎÎ你好', f.clean(u'éèøçÎÎ你好'))
+
def test_change_regex_after_init(self):
f = RegexField('^[a-z]+$')
f.regex = '^\d+$'
@@ -540,27 +548,27 @@ class FieldsTests(SimpleTestCase):
self.assertRaisesMessage(ValidationError, "[u'This field is required.']", f.clean, None)
self.assertRaisesMessage(ValidationError, "[u'This field is required.']", f.clean, None, '')
self.assertEqual('files/test2.pdf', f.clean(None, 'files/test2.pdf'))
- self.assertRaisesMessage(ValidationError, "[u'No file was submitted. Check the encoding type on the form.']", f.clean, SimpleUploadedFile('', ''))
- self.assertRaisesMessage(ValidationError, "[u'No file was submitted. Check the encoding type on the form.']", f.clean, SimpleUploadedFile('', ''), '')
+ self.assertRaisesMessage(ValidationError, "[u'No file was submitted. Check the encoding type on the form.']", f.clean, SimpleUploadedFile('', b''))
+ self.assertRaisesMessage(ValidationError, "[u'No file was submitted. Check the encoding type on the form.']", f.clean, SimpleUploadedFile('', b''), '')
self.assertEqual('files/test3.pdf', f.clean(None, 'files/test3.pdf'))
self.assertRaisesMessage(ValidationError, "[u'No file was submitted. Check the encoding type on the form.']", f.clean, 'some content that is not a file')
self.assertRaisesMessage(ValidationError, "[u'The submitted file is empty.']", f.clean, SimpleUploadedFile('name', None))
- self.assertRaisesMessage(ValidationError, "[u'The submitted file is empty.']", f.clean, SimpleUploadedFile('name', ''))
- self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('name', 'Some File Content'))))
- self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', 'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह'))))
- self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('name', 'Some File Content'), 'files/test4.pdf')))
+ self.assertRaisesMessage(ValidationError, "[u'The submitted file is empty.']", f.clean, SimpleUploadedFile('name', b''))
+ self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('name', b'Some File Content'))))
+ self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', u'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह'.encode('utf-8')))))
+ self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('name', b'Some File Content'), 'files/test4.pdf')))
def test_filefield_2(self):
f = FileField(max_length = 5)
- self.assertRaisesMessage(ValidationError, "[u'Ensure this filename has at most 5 characters (it has 18).']", f.clean, SimpleUploadedFile('test_maxlength.txt', 'hello world'))
+ self.assertRaisesMessage(ValidationError, "[u'Ensure this filename has at most 5 characters (it has 18).']", f.clean, SimpleUploadedFile('test_maxlength.txt', b'hello world'))
self.assertEqual('files/test1.pdf', f.clean('', 'files/test1.pdf'))
self.assertEqual('files/test2.pdf', f.clean(None, 'files/test2.pdf'))
- self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('name', 'Some File Content'))))
+ self.assertEqual(SimpleUploadedFile, type(f.clean(SimpleUploadedFile('name', b'Some File Content'))))
def test_filefield_3(self):
f = FileField(allow_empty_file=True)
self.assertEqual(SimpleUploadedFile,
- type(f.clean(SimpleUploadedFile('name', ''))))
+ type(f.clean(SimpleUploadedFile('name', b''))))
# URLField ##################################################################
@@ -977,39 +985,30 @@ class FieldsTests(SimpleTestCase):
self.assertTrue(got[0].endswith(exp[0]))
def test_filepathfield_folders(self):
- path = forms.__file__
- path = os.path.dirname(path) + '/'
+ path = os.path.dirname(__file__) + '/filepath_test_files/'
f = FilePathField(path=path, allow_folders=True, allow_files=False)
f.choices.sort()
expected = [
- ('/django/forms/extras', 'extras'),
+ ('/tests/regressiontests/forms/tests/filepath_test_files/directory', 'directory'),
]
for exp, got in zip(expected, fix_os_paths(f.choices)):
self.assertEqual(exp[1], got[1])
- self.assert_(got[0].endswith(exp[0]))
+ self.assertTrue(got[0].endswith(exp[0]))
f = FilePathField(path=path, allow_folders=True, allow_files=True)
f.choices.sort()
expected = [
- ('/django/forms/__init__.py', '__init__.py'),
- ('/django/forms/__init__.pyc', '__init__.pyc'),
- ('/django/forms/extras', 'extras'),
- ('/django/forms/fields.py', 'fields.py'),
- ('/django/forms/fields.pyc', 'fields.pyc'),
- ('/django/forms/forms.py', 'forms.py'),
- ('/django/forms/forms.pyc', 'forms.pyc'),
- ('/django/forms/formsets.py', 'formsets.py'),
- ('/django/forms/formsets.pyc', 'formsets.pyc'),
- ('/django/forms/models.py', 'models.py'),
- ('/django/forms/models.pyc', 'models.pyc'),
- ('/django/forms/util.py', 'util.py'),
- ('/django/forms/util.pyc', 'util.pyc'),
- ('/django/forms/widgets.py', 'widgets.py'),
- ('/django/forms/widgets.pyc', 'widgets.pyc')
+ ('/tests/regressiontests/forms/tests/filepath_test_files/.dot-file', '.dot-file'),
+ ('/tests/regressiontests/forms/tests/filepath_test_files/directory', 'directory'),
+ ('/tests/regressiontests/forms/tests/filepath_test_files/fake-image.jpg', 'fake-image.jpg'),
+ ('/tests/regressiontests/forms/tests/filepath_test_files/real-text-file.txt', 'real-text-file.txt'),
]
- for exp, got in zip(expected, fix_os_paths(f.choices)):
- self.assertEqual(exp[1], got[1])
+
+ actual = fix_os_paths(f.choices)
+ self.assertEqual(len(expected), len(actual))
+ for exp, got in zip(expected, actual):
self.assertEqual(exp[1], got[1])
+ self.assertTrue(got[0].endswith(exp[0]))
# SplitDateTimeField ##########################################################
diff --git a/tests/regressiontests/forms/tests/filepath_test_files/.dot-file b/tests/regressiontests/forms/tests/filepath_test_files/.dot-file
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/forms/tests/filepath_test_files/.dot-file
diff --git a/tests/regressiontests/forms/tests/filepath_test_files/directory/.keep b/tests/regressiontests/forms/tests/filepath_test_files/directory/.keep
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/forms/tests/filepath_test_files/directory/.keep
diff --git a/tests/regressiontests/forms/tests/filepath_test_files/fake-image.jpg b/tests/regressiontests/forms/tests/filepath_test_files/fake-image.jpg
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/forms/tests/filepath_test_files/fake-image.jpg
diff --git a/tests/regressiontests/forms/tests/filepath_test_files/real-text-file.txt b/tests/regressiontests/forms/tests/filepath_test_files/real-text-file.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/regressiontests/forms/tests/filepath_test_files/real-text-file.txt
diff --git a/tests/regressiontests/forms/tests/forms.py b/tests/regressiontests/forms/tests/forms.py
index 3f529f23db..16cf46fc29 100644
--- a/tests/regressiontests/forms/tests/forms.py
+++ b/tests/regressiontests/forms/tests/forms.py
@@ -1463,17 +1463,17 @@ class FormsTestCase(TestCase):
f = FileForm(data={}, files={}, auto_id=False)
self.assertHTMLEqual(f.as_table(), '<tr><th>File1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="file" name="file1" /></td></tr>')
- f = FileForm(data={}, files={'file1': SimpleUploadedFile('name', '')}, auto_id=False)
+ f = FileForm(data={}, files={'file1': SimpleUploadedFile('name', b'')}, auto_id=False)
self.assertHTMLEqual(f.as_table(), '<tr><th>File1:</th><td><ul class="errorlist"><li>The submitted file is empty.</li></ul><input type="file" name="file1" /></td></tr>')
f = FileForm(data={}, files={'file1': 'something that is not a file'}, auto_id=False)
self.assertHTMLEqual(f.as_table(), '<tr><th>File1:</th><td><ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul><input type="file" name="file1" /></td></tr>')
- f = FileForm(data={}, files={'file1': SimpleUploadedFile('name', 'some content')}, auto_id=False)
+ f = FileForm(data={}, files={'file1': SimpleUploadedFile('name', b'some content')}, auto_id=False)
self.assertHTMLEqual(f.as_table(), '<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>')
self.assertTrue(f.is_valid())
- f = FileForm(data={}, files={'file1': SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', 'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह')}, auto_id=False)
+ f = FileForm(data={}, files={'file1': SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', u'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह'.encode('utf-8'))}, auto_id=False)
self.assertHTMLEqual(f.as_table(), '<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>')
def test_basic_processing_in_view(self):
diff --git a/tests/regressiontests/forms/tests/models.py b/tests/regressiontests/forms/tests/models.py
index 64cd18bde6..7f569651c7 100644
--- a/tests/regressiontests/forms/tests/models.py
+++ b/tests/regressiontests/forms/tests/models.py
@@ -106,7 +106,7 @@ class ModelFormCallableModelDefault(TestCase):
class FormsModelTestCase(TestCase):
def test_unicode_filename(self):
# FileModel with unicode filename and data #########################
- f = FileForm(data={}, files={'file1': SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', 'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह')}, auto_id=False)
+ f = FileForm(data={}, files={'file1': SimpleUploadedFile('我隻氣墊船裝滿晒鱔.txt', u'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह'.encode('utf-8'))}, auto_id=False)
self.assertTrue(f.is_valid())
self.assertTrue('file1' in f.cleaned_data)
m = FileModel.objects.create(file=f.cleaned_data['file1'])
@@ -177,7 +177,7 @@ class RelatedModelFormTests(TestCase):
class Meta:
model=A
- self.assertRaises(ValueError, ModelFormMetaclass, 'Form', (ModelForm,), {'Meta': Meta})
+ self.assertRaises(ValueError, ModelFormMetaclass, b'Form', (ModelForm,), {'Meta': Meta})
class B(models.Model):
pass
@@ -195,4 +195,4 @@ class RelatedModelFormTests(TestCase):
class Meta:
model=A
- self.assertTrue(issubclass(ModelFormMetaclass('Form', (ModelForm,), {'Meta': Meta}), ModelForm))
+ self.assertTrue(issubclass(ModelFormMetaclass(b'Form', (ModelForm,), {'Meta': Meta}), ModelForm))
diff --git a/tests/regressiontests/forms/tests/regressions.py b/tests/regressiontests/forms/tests/regressions.py
index 267ef300e6..20c11f99a8 100644
--- a/tests/regressiontests/forms/tests/regressions.py
+++ b/tests/regressiontests/forms/tests/regressions.py
@@ -54,10 +54,11 @@ class FormsRegressionsTestCase(TestCase):
# Testing choice validation with UTF-8 bytestrings as input (these are the
# Russian abbreviations "мес." and "шт.".
- UNITS = (('\xd0\xbc\xd0\xb5\xd1\x81.', '\xd0\xbc\xd0\xb5\xd1\x81.'), ('\xd1\x88\xd1\x82.', '\xd1\x88\xd1\x82.'))
+ UNITS = ((b'\xd0\xbc\xd0\xb5\xd1\x81.', b'\xd0\xbc\xd0\xb5\xd1\x81.'),
+ (b'\xd1\x88\xd1\x82.', b'\xd1\x88\xd1\x82.'))
f = ChoiceField(choices=UNITS)
self.assertEqual(f.clean(u'\u0448\u0442.'), u'\u0448\u0442.')
- self.assertEqual(f.clean('\xd1\x88\xd1\x82.'), u'\u0448\u0442.')
+ self.assertEqual(f.clean(b'\xd1\x88\xd1\x82.'), u'\u0448\u0442.')
# Translated error messages used to be buggy.
with override('ru'):
diff --git a/tests/regressiontests/forms/tests/widgets.py b/tests/regressiontests/forms/tests/widgets.py
index 2499b7a350..8630b45666 100644
--- a/tests/regressiontests/forms/tests/widgets.py
+++ b/tests/regressiontests/forms/tests/widgets.py
@@ -1182,7 +1182,7 @@ class ClearableFileInputTests(TestCase):
"""
widget = ClearableFileInput()
widget.is_required = True
- f = SimpleUploadedFile('something.txt', 'content')
+ f = SimpleUploadedFile('something.txt', b'content')
self.assertEqual(widget.value_from_datadict(
data={'myfile-clear': True},
files={'myfile': f},
diff --git a/tests/regressiontests/generic_views/base.py b/tests/regressiontests/generic_views/base.py
index e18ed2a2a7..fc3dc05fd7 100644
--- a/tests/regressiontests/generic_views/base.py
+++ b/tests/regressiontests/generic_views/base.py
@@ -173,6 +173,58 @@ class ViewTest(unittest.TestCase):
"""
self.assertTrue(DecoratedDispatchView.as_view().is_decorated)
+ def test_head_no_get(self):
+ """
+ Test that a view class with no get responds to a HEAD request with HTTP
+ 405.
+ """
+ request = self.rf.head('/')
+ view = PostOnlyView.as_view()
+ self.assertEqual(405, view(request).status_code)
+
+ def test_options(self):
+ """
+ Test that views respond to HTTP OPTIONS requests with an Allow header
+ appropriate for the methods implemented by the view class.
+ """
+ request = self.rf.options('/')
+ view = SimpleView.as_view()
+ response = view(request)
+ self.assertEqual(200, response.status_code)
+ self.assertTrue(response['Allow'])
+
+ def test_options_for_get_view(self):
+ """
+ Test that a view implementing GET allows GET and HEAD.
+ """
+ request = self.rf.options('/')
+ view = SimpleView.as_view()
+ response = view(request)
+ self._assert_allows(response, 'GET', 'HEAD')
+
+ def test_options_for_get_and_post_view(self):
+ """
+ Test that a view implementing GET and POST allows GET, HEAD, and POST.
+ """
+ request = self.rf.options('/')
+ view = SimplePostView.as_view()
+ response = view(request)
+ self._assert_allows(response, 'GET', 'HEAD', 'POST')
+
+ def test_options_for_post_view(self):
+ """
+ Test that a view implementing POST allows POST.
+ """
+ request = self.rf.options('/')
+ view = PostOnlyView.as_view()
+ response = view(request)
+ self._assert_allows(response, 'POST')
+
+ def _assert_allows(self, response, *expected_methods):
+ "Assert allowed HTTP methods reported in the Allow response header"
+ response_allows = set(response['Allow'].split(', '))
+ self.assertEqual(set(expected_methods + ('OPTIONS',)), response_allows)
+
class TemplateViewTest(TestCase):
urls = 'regressiontests.generic_views.urls'
diff --git a/tests/regressiontests/generic_views/dates.py b/tests/regressiontests/generic_views/dates.py
index 98c089f2b4..ad65fd9f10 100644
--- a/tests/regressiontests/generic_views/dates.py
+++ b/tests/regressiontests/generic_views/dates.py
@@ -86,10 +86,15 @@ class ArchiveIndexViewTests(TestCase):
# 1 query for years list + 1 query for books
with self.assertNumQueries(2):
self.client.get('/dates/books/')
- # same as above + 1 query to test if books exist
- with self.assertNumQueries(3):
+ # same as above + 1 query to test if books exist + 1 query to count them
+ with self.assertNumQueries(4):
self.client.get('/dates/books/paginated/')
+ def test_no_duplicate_query(self):
+ # Regression test for #18354
+ with self.assertNumQueries(2):
+ self.client.get('/dates/books/reverse/')
+
def test_datetime_archive_view(self):
BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0))
res = self.client.get('/dates/booksignings/')
@@ -110,9 +115,13 @@ class YearArchiveViewTests(TestCase):
res = self.client.get('/dates/books/2008/')
self.assertEqual(res.status_code, 200)
self.assertEqual(list(res.context['date_list']), [datetime.datetime(2008, 10, 1)])
- self.assertEqual(res.context['year'], '2008')
+ self.assertEqual(res.context['year'], datetime.date(2008, 1, 1))
self.assertTemplateUsed(res, 'generic_views/book_archive_year.html')
+ # Since allow_empty=False, next/prev years must be valid (#7164)
+ self.assertEqual(res.context['next_year'], None)
+ self.assertEqual(res.context['previous_year'], datetime.date(2006, 1, 1))
+
def test_year_view_make_object_list(self):
res = self.client.get('/dates/books/2006/make_object_list/')
self.assertEqual(res.status_code, 200)
@@ -129,6 +138,10 @@ class YearArchiveViewTests(TestCase):
self.assertEqual(list(res.context['date_list']), [])
self.assertEqual(list(res.context['book_list']), [])
+ # Since allow_empty=True, next/prev are allowed to be empty years (#7164)
+ self.assertEqual(res.context['next_year'], datetime.date(2000, 1, 1))
+ self.assertEqual(res.context['previous_year'], datetime.date(1998, 1, 1))
+
def test_year_view_allow_future(self):
# Create a new book in the future
year = datetime.date.today().year + 1
@@ -155,6 +168,11 @@ class YearArchiveViewTests(TestCase):
res = self.client.get('/dates/books/no_year/')
self.assertEqual(res.status_code, 404)
+ def test_no_duplicate_query(self):
+ # Regression test for #18354
+ with self.assertNumQueries(4):
+ self.client.get('/dates/books/2008/reverse/')
+
def test_datetime_year_view(self):
BookSigning.objects.create(event_date=datetime.datetime(2008, 4, 2, 12, 0))
res = self.client.get('/dates/booksignings/2008/')
@@ -446,6 +464,13 @@ class DayArchiveViewTests(TestCase):
self.assertEqual(res.context['next_day'], future)
self.assertEqual(res.context['previous_day'], datetime.date(2006, 5, 1))
+ # allow_future for yesterday, next_day is today (#17192)
+ today = datetime.date.today()
+ yesterday = today - datetime.timedelta(days=1)
+ res = self.client.get('/dates/books/%s/allow_empty_and_future/'
+ % yesterday.strftime('%Y/%b/%d').lower())
+ self.assertEqual(res.context['next_day'], today)
+
def test_day_view_paginated(self):
res = self.client.get('/dates/books/2008/oct/1/')
self.assertEqual(res.status_code, 200)
diff --git a/tests/regressiontests/generic_views/list.py b/tests/regressiontests/generic_views/list.py
index 9ad00edc3b..b925758524 100644
--- a/tests/regressiontests/generic_views/list.py
+++ b/tests/regressiontests/generic_views/list.py
@@ -159,6 +159,16 @@ class ListViewTests(TestCase):
def test_missing_items(self):
self.assertRaises(ImproperlyConfigured, self.client.get, '/list/authors/invalid/')
+ def test_paginated_list_view_does_not_load_entire_table(self):
+ # Regression test for #17535
+ self._make_authors(3)
+ # 1 query for authors
+ with self.assertNumQueries(1):
+ self.client.get('/list/authors/notempty/')
+ # same as above + 1 query to test if authors exist + 1 query for pagination
+ with self.assertNumQueries(3):
+ self.client.get('/list/authors/notempty/paginated/')
+
def _make_authors(self, n):
Author.objects.all().delete()
for i in range(n):
diff --git a/tests/regressiontests/generic_views/templates/generic_views/book_archive.html b/tests/regressiontests/generic_views/templates/generic_views/book_archive.html
index 5fc11149bd..03f45a38c2 100644
--- a/tests/regressiontests/generic_views/templates/generic_views/book_archive.html
+++ b/tests/regressiontests/generic_views/templates/generic_views/book_archive.html
@@ -1 +1 @@
-Archive of books from {{ date_list }}. \ No newline at end of file
+Archive of books from {{ date_list }}. {{ object_list|length }} books found.
diff --git a/tests/regressiontests/generic_views/templates/generic_views/book_archive_year.html b/tests/regressiontests/generic_views/templates/generic_views/book_archive_year.html
index 7705914e97..fde198dcaf 100644
--- a/tests/regressiontests/generic_views/templates/generic_views/book_archive_year.html
+++ b/tests/regressiontests/generic_views/templates/generic_views/book_archive_year.html
@@ -1 +1 @@
-Archive of books from {{ year }}. \ No newline at end of file
+Archive of books from {{ year }}. {{ object_list|length }} books found.
diff --git a/tests/regressiontests/generic_views/urls.py b/tests/regressiontests/generic_views/urls.py
index 9c47ab8d82..14d4f685a6 100644
--- a/tests/regressiontests/generic_views/urls.py
+++ b/tests/regressiontests/generic_views/urls.py
@@ -4,6 +4,7 @@ from django.conf.urls import patterns, url
from django.views.decorators.cache import cache_page
from django.views.generic import TemplateView
+from . import models
from . import views
@@ -108,6 +109,8 @@ urlpatterns = patterns('',
views.BookArchive.as_view(queryset=None)),
(r'^dates/books/paginated/$',
views.BookArchive.as_view(paginate_by=10)),
+ (r'^dates/books/reverse/$',
+ views.BookArchive.as_view(queryset=models.Book.objects.order_by('pubdate'))),
(r'^dates/booksignings/$',
views.BookSigningArchive.as_view()),
@@ -128,6 +131,8 @@ urlpatterns = patterns('',
views.AuthorList.as_view(paginate_by=30)),
(r'^list/authors/notempty/$',
views.AuthorList.as_view(allow_empty=False)),
+ (r'^list/authors/notempty/paginated/$',
+ views.AuthorList.as_view(allow_empty=False, paginate_by=2)),
(r'^list/authors/template_name/$',
views.AuthorList.as_view(template_name='generic_views/list.html')),
(r'^list/authors/template_name_suffix/$',
@@ -158,6 +163,8 @@ urlpatterns = patterns('',
views.BookYearArchive.as_view(make_object_list=True, paginate_by=30)),
(r'^dates/books/no_year/$',
views.BookYearArchive.as_view()),
+ (r'^dates/books/(?P<year>\d{4})/reverse/$',
+ views.BookYearArchive.as_view(queryset=models.Book.objects.order_by('pubdate'))),
(r'^dates/booksignings/(?P<year>\d{4})/$',
views.BookSigningYearArchive.as_view()),
@@ -202,6 +209,8 @@ urlpatterns = patterns('',
views.BookDayArchive.as_view(allow_empty=True)),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_future/$',
views.BookDayArchive.as_view(allow_future=True)),
+ (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_empty_and_future/$',
+ views.BookDayArchive.as_view(allow_empty=True, allow_future=True)),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/paginated/$',
views.BookDayArchive.as_view(paginate_by=True)),
(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/no_day/$',
diff --git a/tests/regressiontests/handlers/tests.py b/tests/regressiontests/handlers/tests.py
index 59d3d84528..ae2062c756 100644
--- a/tests/regressiontests/handlers/tests.py
+++ b/tests/regressiontests/handlers/tests.py
@@ -28,7 +28,7 @@ class HandlerTests(unittest.TestCase):
def test_bad_path_info(self):
"""Tests for bug #15672 ('request' referenced before assignment)"""
environ = RequestFactory().get('/').environ
- environ['PATH_INFO'] = '\xed'
+ environ['PATH_INFO'] = b'\xed'
handler = WSGIHandler()
response = handler(environ, lambda *a, **k: None)
self.assertEqual(response.status_code, 400)
diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py
index 6dd2128afd..218c5b5b3b 100644
--- a/tests/regressiontests/httpwrappers/tests.py
+++ b/tests/regressiontests/httpwrappers/tests.py
@@ -174,7 +174,7 @@ class QueryDictTests(unittest.TestCase):
QueryDicts must be able to handle invalid input encoding (in this
case, bad UTF-8 encoding).
"""
- q = QueryDict('foo=bar&foo=\xff')
+ q = QueryDict(b'foo=bar&foo=\xff')
self.assertEqual(q['foo'], u'\ufffd')
self.assertEqual(q.getlist('foo'), [u'bar', u'\ufffd'])
@@ -198,7 +198,7 @@ class QueryDictTests(unittest.TestCase):
def test_non_default_encoding(self):
"""#13572 - QueryDict with a non-default encoding"""
- q = QueryDict('sbb=one', encoding='rot_13')
+ q = QueryDict(b'sbb=one', encoding='rot_13')
self.assertEqual(q.encoding , 'rot_13' )
self.assertEqual(q.items() , [(u'foo', u'bar')] )
self.assertEqual(q.urlencode() , 'sbb=one' )
@@ -285,8 +285,8 @@ class HttpResponseTests(unittest.TestCase):
except StopIteration:
break
#'\xde\x9e' == unichr(1950).encode('utf-8')
- self.assertEqual(result, ['1', '2', '3', '\xde\x9e'])
- self.assertEqual(r.content, '123\xde\x9e')
+ self.assertEqual(result, ['1', '2', '3', b'\xde\x9e'])
+ self.assertEqual(r.content, b'123\xde\x9e')
#with Content-Encoding header
r = HttpResponse([1,1,2,4,8])
@@ -321,7 +321,7 @@ class CookieTests(unittest.TestCase):
Test that we haven't broken normal encoding
"""
c = SimpleCookie()
- c['test'] = "\xf0"
+ c['test'] = b"\xf0"
c2 = SimpleCookie()
c2.load(c.output())
self.assertEqual(c['test'].value, c2['test'].value)
diff --git a/tests/regressiontests/i18n/commands/compilation.py b/tests/regressiontests/i18n/commands/compilation.py
index 039e463d0b..d88e1feef6 100644
--- a/tests/regressiontests/i18n/commands/compilation.py
+++ b/tests/regressiontests/i18n/commands/compilation.py
@@ -1,8 +1,7 @@
import os
from io import BytesIO
-from django.core.management import CommandError
-from django.core.management.commands.compilemessages import compile_messages
+from django.core.management import call_command, CommandError
from django.test import TestCase
from django.test.utils import override_settings
from django.utils import translation
@@ -25,11 +24,9 @@ class PoFileTests(MessageCompilationTests):
def test_bom_rejection(self):
os.chdir(test_dir)
- # We don't use the django.core.management infrastructure (call_command()
- # et al) because CommandError's cause exit(1) there. We test the
- # underlying compile_messages function instead
- out = BytesIO()
- self.assertRaises(CommandError, compile_messages, out, locale=self.LOCALE)
+ with self.assertRaisesRegexp(CommandError,
+ "file has a BOM \(Byte Order Mark\)"):
+ call_command('compilemessages', locale=self.LOCALE, stderr=BytesIO())
self.assertFalse(os.path.exists(self.MO_FILE))
@@ -45,11 +42,7 @@ class PoFileContentsTests(MessageCompilationTests):
def test_percent_symbol_in_po_file(self):
os.chdir(test_dir)
- # We don't use the django.core.management infrastructure (call_command()
- # et al) because CommandError's cause exit(1) there. We test the
- # underlying compile_messages function instead
- out = BytesIO()
- compile_messages(out, locale=self.LOCALE)
+ call_command('compilemessages', locale=self.LOCALE, stderr=BytesIO())
self.assertTrue(os.path.exists(self.MO_FILE))
@@ -64,11 +57,7 @@ class PercentRenderingTests(MessageCompilationTests):
def test_percent_symbol_escaping(self):
from django.template import Template, Context
os.chdir(test_dir)
- # We don't use the django.core.management infrastructure (call_command()
- # et al) because CommandError's cause exit(1) there. We test the
- # underlying compile_messages function instead
- out = BytesIO()
- compile_messages(out, locale=self.LOCALE)
+ call_command('compilemessages', locale=self.LOCALE, stderr=BytesIO())
with translation.override(self.LOCALE):
t = Template('{% load i18n %}{% trans "Looks like a str fmt spec %% o but shouldn\'t be interpreted as such" %}')
rendered = t.render(Context({}))
diff --git a/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mo b/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mo
index f0a2179767..478338bc88 100644
--- a/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mo
+++ b/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.mo
Binary files differ
diff --git a/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po b/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po
index 8e9b9e1034..dafb6139ae 100644
--- a/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po
+++ b/tests/regressiontests/i18n/other/locale/fr/LC_MESSAGES/django.po
@@ -17,5 +17,11 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: template.html:3
+# Note: Intentional: variable name is translated.
msgid "My name is %(person)s."
msgstr "Mon nom est %(personne)s."
+
+#: template.html:3
+# Note: Intentional: the variable name is badly formatted (missing 's' at the end)
+msgid "My other name is %(person)s."
+msgstr "Mon autre nom est %(person)." \ No newline at end of file
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index faed4e55c7..78e41321af 100644
--- a/tests/regressiontests/i18n/tests.py
+++ b/tests/regressiontests/i18n/tests.py
@@ -230,7 +230,7 @@ class TranslationTests(TestCase):
"""
Translating a string requiring no auto-escaping shouldn't change the "safe" status.
"""
- s = mark_safe('Password')
+ s = mark_safe(b'Password')
self.assertEqual(SafeString, type(s))
with translation.override('de', deactivate=True):
self.assertEqual(SafeUnicode, type(ugettext(s)))
@@ -270,10 +270,11 @@ class TranslationTests(TestCase):
self.assertEqual(to_language('sr_Lat'), 'sr-lat')
@override_settings(LOCALE_PATHS=(os.path.join(here, 'other', 'locale'),))
- def test_bad_placeholder(self):
+ def test_bad_placeholder_1(self):
"""
Error in translation file should not crash template rendering
(%(person)s is translated as %(personne)s in fr.po)
+ Refs #16516.
"""
from django.template import Template, Context
with translation.override('fr'):
@@ -281,6 +282,19 @@ class TranslationTests(TestCase):
rendered = t.render(Context({'person': 'James'}))
self.assertEqual(rendered, 'My name is James.')
+ @override_settings(LOCALE_PATHS=(os.path.join(here, 'other', 'locale'),))
+ def test_bad_placeholder_2(self):
+ """
+ Error in translation file should not crash template rendering
+ (%(person) misses a 's' in fr.po, causing the string formatting to fail)
+ Refs #18393.
+ """
+ from django.template import Template, Context
+ with translation.override('fr'):
+ t = Template('{% load i18n %}{% blocktrans %}My other name is {{ person }}.{% endblocktrans %}')
+ rendered = t.render(Context({'person': 'James'}))
+ self.assertEqual(rendered, 'My other name is James.')
+
class FormattingTests(TestCase):
diff --git a/tests/regressiontests/inspectdb/tests.py b/tests/regressiontests/inspectdb/tests.py
index 6896bf9126..29435b8375 100644
--- a/tests/regressiontests/inspectdb/tests.py
+++ b/tests/regressiontests/inspectdb/tests.py
@@ -6,10 +6,28 @@ from django.test import TestCase, skipUnlessDBFeature
class InspectDBTestCase(TestCase):
+ def test_stealth_table_name_filter_option(self):
+ out = StringIO()
+ # Lets limit the introspection to tables created for models of this
+ # application
+ call_command('inspectdb',
+ table_name_filter=lambda tn:tn.startswith('inspectdb_'),
+ stdout=out)
+ error_message = "inspectdb has examined a table that should have been filtered out."
+ # contrib.contenttypes is one of the apps always installed when running
+ # the Django test suite, check that one of its tables hasn't been
+ # inspected
+ self.assertNotIn("class DjangoContentType(models.Model):", out.getvalue(), msg=error_message)
+ out.close()
+
@skipUnlessDBFeature('can_introspect_foreign_keys')
def test_attribute_name_not_python_keyword(self):
out = StringIO()
- call_command('inspectdb', stdout=out)
+ # Lets limit the introspection to tables created for models of this
+ # application
+ call_command('inspectdb',
+ table_name_filter=lambda tn:tn.startswith('inspectdb_'),
+ stdout=out)
error_message = "inspectdb generated an attribute name which is a python keyword"
self.assertNotIn("from = models.ForeignKey(InspectdbPeople)", out.getvalue(), msg=error_message)
# As InspectdbPeople model is defined after InspectdbMessage, it should be quoted
@@ -23,7 +41,11 @@ class InspectDBTestCase(TestCase):
def test_digits_column_name_introspection(self):
"""Introspection of column names consist/start with digits (#16536/#17676)"""
out = StringIO()
- call_command('inspectdb', stdout=out)
+ # Lets limit the introspection to tables created for models of this
+ # application
+ call_command('inspectdb',
+ table_name_filter=lambda tn:tn.startswith('inspectdb_'),
+ stdout=out)
error_message = "inspectdb generated a model field name which is a number"
self.assertNotIn(" 123 = models.CharField", out.getvalue(), msg=error_message)
self.assertIn("number_123 = models.CharField", out.getvalue())
diff --git a/tests/regressiontests/localflavor/es/tests.py b/tests/regressiontests/localflavor/es/tests.py
index c989e3e9ca..c13eac6d61 100644
--- a/tests/regressiontests/localflavor/es/tests.py
+++ b/tests/regressiontests/localflavor/es/tests.py
@@ -31,7 +31,7 @@ class ESLocalFlavorTests(SimpleTestCase):
def test_ESProvinceSelect(self):
f = ESProvinceSelect()
out = u'''<select name="provinces">
-<option value="01">Arava</option>
+<option value="01">Araba</option>
<option value="02">Albacete</option>
<option value="03">Alacant</option>
<option value="04">Almeria</option>
diff --git a/tests/regressiontests/localflavor/mk/tests.py b/tests/regressiontests/localflavor/mk/tests.py
index f78dbdd440..3a8add6e34 100644
--- a/tests/regressiontests/localflavor/mk/tests.py
+++ b/tests/regressiontests/localflavor/mk/tests.py
@@ -92,7 +92,7 @@ class MKLocalFlavorTests(SimpleTestCase):
"""
Test that the empty option is there.
"""
- municipality_select_html = """\
+ municipality_select_html = b"""\
<select name="municipality" id="id_municipality">
<option value="">---------</option>
<option value="AD">Aerodrom</option>
diff --git a/tests/regressiontests/mail/tests.py b/tests/regressiontests/mail/tests.py
index a4cefd8322..85e73c197f 100644
--- a/tests/regressiontests/mail/tests.py
+++ b/tests/regressiontests/mail/tests.py
@@ -86,7 +86,7 @@ class MailTests(TestCase):
"""
headers = {"date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"}
email = EmailMessage('subject', 'content', 'from@example.com', ['to@example.com'], headers=headers)
- self.assertEqual(email.message().as_string(), 'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: 7bit\nSubject: subject\nFrom: from@example.com\nTo: to@example.com\ndate: Fri, 09 Nov 2001 01:08:47 -0000\nMessage-ID: foo\n\ncontent')
+ self.assertEqual(email.message().as_string(), b'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: 7bit\nSubject: subject\nFrom: from@example.com\nTo: to@example.com\ndate: Fri, 09 Nov 2001 01:08:47 -0000\nMessage-ID: foo\n\ncontent')
def test_from_header(self):
"""
@@ -168,7 +168,7 @@ class MailTests(TestCase):
email = EmailMessage('Subject', 'Firstname Sürname is a great guy.', 'from@example.com', ['other@example.com'])
email.encoding = 'iso-8859-1'
message = email.message()
- self.assertTrue(message.as_string().startswith('Content-Type: text/plain; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\nSubject: Subject\nFrom: from@example.com\nTo: other@example.com'))
+ self.assertTrue(message.as_string().startswith(b'Content-Type: text/plain; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\nSubject: Subject\nFrom: from@example.com\nTo: other@example.com'))
self.assertEqual(message.get_payload(), 'Firstname S=FCrname is a great guy.')
# Make sure MIME attachments also works correctly with other encodings than utf-8
@@ -177,8 +177,8 @@ class MailTests(TestCase):
msg = EmailMultiAlternatives('Subject', text_content, 'from@example.com', ['to@example.com'])
msg.encoding = 'iso-8859-1'
msg.attach_alternative(html_content, "text/html")
- self.assertEqual(msg.message().get_payload(0).as_string(), 'Content-Type: text/plain; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\nFirstname S=FCrname is a great guy.')
- self.assertEqual(msg.message().get_payload(1).as_string(), 'Content-Type: text/html; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\n<p>Firstname S=FCrname is a <strong>great</strong> guy.</p>')
+ self.assertEqual(msg.message().get_payload(0).as_string(), b'Content-Type: text/plain; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\nFirstname S=FCrname is a great guy.')
+ self.assertEqual(msg.message().get_payload(1).as_string(), b'Content-Type: text/html; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\n<p>Firstname S=FCrname is a <strong>great</strong> guy.</p>')
def test_attachments(self):
"""Regression test for #9367"""
@@ -188,7 +188,7 @@ class MailTests(TestCase):
html_content = '<p>This is an <strong>important</strong> message.</p>'
msg = EmailMultiAlternatives(subject, text_content, from_email, [to], headers=headers)
msg.attach_alternative(html_content, "text/html")
- msg.attach("an attachment.pdf", "%PDF-1.4.%...", mimetype="application/pdf")
+ msg.attach("an attachment.pdf", b"%PDF-1.4.%...", mimetype="application/pdf")
msg_str = msg.message().as_string()
message = email.message_from_string(msg_str)
self.assertTrue(message.is_multipart())
@@ -205,7 +205,7 @@ class MailTests(TestCase):
content = 'This is the message.'
msg = EmailMessage(subject, content, from_email, [to], headers=headers)
# Unicode in file name
- msg.attach(u"une pièce jointe.pdf", "%PDF-1.4.%...", mimetype="application/pdf")
+ msg.attach(u"une pièce jointe.pdf", b"%PDF-1.4.%...", mimetype="application/pdf")
msg_str = msg.message().as_string()
message = email.message_from_string(msg_str)
payload = message.get_payload()
@@ -289,31 +289,31 @@ class MailTests(TestCase):
# Regression for #13433 - Make sure that EmailMessage doesn't mangle
# 'From ' in message body.
email = EmailMessage('Subject', 'From the future', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'})
- self.assertFalse('>From the future' in email.message().as_string())
+ self.assertFalse(b'>From the future' in email.message().as_string())
def test_dont_base64_encode(self):
# Ticket #3472
# Shouldn't use Base64 encoding at all
msg = EmailMessage('Subject', 'UTF-8 encoded body', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'})
- self.assertFalse('Content-Transfer-Encoding: base64' in msg.message().as_string())
+ self.assertFalse(b'Content-Transfer-Encoding: base64' in msg.message().as_string())
# Ticket #11212
# Shouldn't use quoted printable, should detect it can represent content with 7 bit data
msg = EmailMessage('Subject', 'Body with only ASCII characters.', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'})
s = msg.message().as_string()
- self.assertFalse('Content-Transfer-Encoding: quoted-printable' in s)
- self.assertTrue('Content-Transfer-Encoding: 7bit' in s)
+ self.assertFalse(b'Content-Transfer-Encoding: quoted-printable' in s)
+ self.assertTrue(b'Content-Transfer-Encoding: 7bit' in s)
# Shouldn't use quoted printable, should detect it can represent content with 8 bit data
msg = EmailMessage('Subject', 'Body with latin characters: àáä.', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'})
s = msg.message().as_string()
- self.assertFalse('Content-Transfer-Encoding: quoted-printable' in s)
- self.assertTrue('Content-Transfer-Encoding: 8bit' in s)
+ self.assertFalse(b'Content-Transfer-Encoding: quoted-printable' in s)
+ self.assertTrue(b'Content-Transfer-Encoding: 8bit' in s)
msg = EmailMessage('Subject', u'Body with non latin characters: А Б В Г Д Е Ж Ѕ З И І К Л М Н О П.', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'})
s = msg.message().as_string()
- self.assertFalse('Content-Transfer-Encoding: quoted-printable' in s)
- self.assertTrue('Content-Transfer-Encoding: 8bit' in s)
+ self.assertFalse(b'Content-Transfer-Encoding: quoted-printable' in s)
+ self.assertTrue(b'Content-Transfer-Encoding: 8bit' in s)
class BaseEmailBackendTests(object):
@@ -438,7 +438,7 @@ class BaseEmailBackendTests(object):
email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com'], cc=['cc@example.com'])
mail.get_connection().send_messages([email])
message = self.get_the_message()
- self.assertStartsWith(message.as_string(), 'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: 7bit\nSubject: Subject\nFrom: from@example.com\nTo: to@example.com\nCc: cc@example.com\nDate: ')
+ self.assertStartsWith(message.as_string(), b'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: 7bit\nSubject: Subject\nFrom: from@example.com\nTo: to@example.com\nCc: cc@example.com\nDate: ')
def test_idn_send(self):
"""
@@ -500,14 +500,14 @@ class FileBackendTests(BaseEmailBackendTests, TestCase):
email_backend = 'django.core.mail.backends.filebased.EmailBackend'
def setUp(self):
+ super(FileBackendTests, self).setUp()
self.tmp_dir = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, self.tmp_dir)
- self.settings_override = override_settings(EMAIL_FILE_PATH=self.tmp_dir)
- self.settings_override.enable()
- super(FileBackendTests, self).setUp()
+ self._settings_override = override_settings(EMAIL_FILE_PATH=self.tmp_dir)
+ self._settings_override.enable()
def tearDown(self):
- self.settings_override.disable()
+ self._settings_override.disable()
super(FileBackendTests, self).tearDown()
def flush_mailbox(self):
@@ -517,8 +517,8 @@ class FileBackendTests(BaseEmailBackendTests, TestCase):
def get_mailbox_content(self):
messages = []
for filename in os.listdir(self.tmp_dir):
- with open(os.path.join(self.tmp_dir, filename)) as fp:
- session = fp.read().split('\n' + ('-' * 79) + '\n')
+ with open(os.path.join(self.tmp_dir, filename), 'rb') as fp:
+ session = fp.read().split(b'\n' + (b'-' * 79) + b'\n')
messages.extend(email.message_from_string(m) for m in session if m)
return messages
@@ -569,7 +569,7 @@ class ConsoleBackendTests(BaseEmailBackendTests, TestCase):
self.stream = sys.stdout = StringIO()
def get_mailbox_content(self):
- messages = self.stream.getvalue().split('\n' + ('-' * 79) + '\n')
+ messages = self.stream.getvalue().split(b'\n' + (b'-' * 79) + b'\n')
return [email.message_from_string(m) for m in messages if m]
def test_console_stream_kwarg(self):
@@ -644,15 +644,15 @@ class SMTPBackendTests(BaseEmailBackendTests, TestCase):
@classmethod
def setUpClass(cls):
cls.server = FakeSMTPServer(('127.0.0.1', 0), None)
- cls.settings_override = override_settings(
+ cls._settings_override = override_settings(
EMAIL_HOST="127.0.0.1",
EMAIL_PORT=cls.server.socket.getsockname()[1])
- cls.settings_override.enable()
+ cls._settings_override.enable()
cls.server.start()
@classmethod
def tearDownClass(cls):
- cls.settings_override.disable()
+ cls._settings_override.disable()
cls.server.stop()
def setUp(self):
diff --git a/tests/regressiontests/model_fields/tests.py b/tests/regressiontests/model_fields/tests.py
index ea1e1c7d99..9c0f888a99 100644
--- a/tests/regressiontests/model_fields/tests.py
+++ b/tests/regressiontests/model_fields/tests.py
@@ -208,7 +208,7 @@ class BooleanFieldTests(unittest.TestCase):
# Verify that when an extra clause exists, the boolean
# conversions are applied with an offset
b5 = BooleanModel.objects.all().extra(
- select={'string_length': 'LENGTH(string)'})[0]
+ select={'string_col': 'string'})[0]
self.assertFalse(isinstance(b5.pk, bool))
class ChoicesTests(test.TestCase):
@@ -365,3 +365,15 @@ class FileFieldTests(unittest.TestCase):
field = d._meta.get_field('myfile')
field.save_form_data(d, 'else.txt')
self.assertEqual(d.myfile, 'else.txt')
+
+ def test_max_length(self):
+ """
+ Test that FileField validates the length of the generated file name
+ that will be stored in the database. Regression for #9893.
+
+ """
+ # upload_to = 'unused', so file names are saved as 'unused/xxxxx'.
+ # max_length = 100, so names longer than 93 characters are rejected.
+ Document(myfile=93 * 'x').full_clean()
+ with self.assertRaises(ValidationError):
+ Document(myfile=94 * 'x').full_clean()
diff --git a/tests/regressiontests/model_forms_regress/tests.py b/tests/regressiontests/model_forms_regress/tests.py
index 09da9737a8..d33f52af9a 100644
--- a/tests/regressiontests/model_forms_regress/tests.py
+++ b/tests/regressiontests/model_forms_regress/tests.py
@@ -394,7 +394,7 @@ class FileFieldTests(unittest.TestCase):
form = DocumentForm()
self.assertTrue('name="myfile"' in unicode(form))
self.assertTrue('myfile-clear' not in unicode(form))
- form = DocumentForm(files={'myfile': SimpleUploadedFile('something.txt', 'content')})
+ form = DocumentForm(files={'myfile': SimpleUploadedFile('something.txt', b'content')})
self.assertTrue(form.is_valid())
doc = form.save(commit=False)
self.assertEqual(doc.myfile.name, 'something.txt')
@@ -411,11 +411,11 @@ class FileFieldTests(unittest.TestCase):
includes the current file and the clear checkbox.
"""
- form = DocumentForm(files={'myfile': SimpleUploadedFile('something.txt', 'content')})
+ form = DocumentForm(files={'myfile': SimpleUploadedFile('something.txt', b'content')})
self.assertTrue(form.is_valid())
doc = form.save(commit=False)
form = DocumentForm(instance=doc,
- files={'myfile': SimpleUploadedFile('something.txt', 'content')},
+ files={'myfile': SimpleUploadedFile('something.txt', b'content')},
data={'myfile-clear': 'true'})
self.assertTrue(not form.is_valid())
self.assertEqual(form.errors['myfile'],
diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py
index 07aa6db67b..e4ce9d7b60 100644
--- a/tests/regressiontests/queries/models.py
+++ b/tests/regressiontests/queries/models.py
@@ -264,7 +264,7 @@ class SingleObject(models.Model):
return self.name
class RelatedObject(models.Model):
- single = models.ForeignKey(SingleObject)
+ single = models.ForeignKey(SingleObject, null=True)
class Meta:
ordering = ['single']
diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py
index 14a693f2c5..1035a38840 100644
--- a/tests/regressiontests/queries/tests.py
+++ b/tests/regressiontests/queries/tests.py
@@ -19,7 +19,8 @@ from .models import (Annotation, Article, Author, Celebrity, Child, Cover,
ManagedModel, Member, NamedCategory, Note, Number, Plaything, PointerA,
Ranking, Related, Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten,
Node, ObjectA, ObjectB, ObjectC, CategoryItem, SimpleCategory,
- SpecialCategory, OneToOneCategory, NullableName, ProxyCategory)
+ SpecialCategory, OneToOneCategory, NullableName, ProxyCategory,
+ SingleObject, RelatedObject)
class BaseQuerysetTest(TestCase):
@@ -843,6 +844,39 @@ class Queries1Tests(BaseQuerysetTest):
)
Tag._meta.ordering = original_ordering
+ def test_exclude(self):
+ self.assertQuerysetEqual(
+ Item.objects.exclude(tags__name='t4'),
+ [repr(i) for i in Item.objects.filter(~Q(tags__name='t4'))])
+ self.assertQuerysetEqual(
+ Item.objects.exclude(Q(tags__name='t4')|Q(tags__name='t3')),
+ [repr(i) for i in Item.objects.filter(~(Q(tags__name='t4')|Q(tags__name='t3')))])
+ self.assertQuerysetEqual(
+ Item.objects.exclude(Q(tags__name='t4')|~Q(tags__name='t3')),
+ [repr(i) for i in Item.objects.filter(~(Q(tags__name='t4')|~Q(tags__name='t3')))])
+
+ def test_nested_exclude(self):
+ self.assertQuerysetEqual(
+ Item.objects.exclude(~Q(tags__name='t4')),
+ [repr(i) for i in Item.objects.filter(~~Q(tags__name='t4'))])
+
+ def test_double_exclude(self):
+ self.assertQuerysetEqual(
+ Item.objects.filter(Q(tags__name='t4')),
+ [repr(i) for i in Item.objects.filter(~~Q(tags__name='t4'))])
+ self.assertQuerysetEqual(
+ Item.objects.filter(Q(tags__name='t4')),
+ [repr(i) for i in Item.objects.filter(~Q(~Q(tags__name='t4')))])
+
+ @unittest.expectedFailure
+ def test_exclude_in(self):
+ self.assertQuerysetEqual(
+ Item.objects.exclude(Q(tags__name__in=['t4', 't3'])),
+ [repr(i) for i in Item.objects.filter(~Q(tags__name__in=['t4', 't3']))])
+ self.assertQuerysetEqual(
+ Item.objects.filter(Q(tags__name__in=['t4', 't3'])),
+ [repr(i) for i in Item.objects.filter(~~Q(tags__name__in=['t4', 't3']))])
+
class Queries2Tests(TestCase):
def setUp(self):
Number.objects.create(num=4)
@@ -1321,12 +1355,33 @@ class NullableRelOrderingTests(TestCase):
def test_ticket10028(self):
# Ordering by model related to nullable relations(!) should use outer
# joins, so that all results are included.
- _ = Plaything.objects.create(name="p1")
+ Plaything.objects.create(name="p1")
self.assertQuerysetEqual(
Plaything.objects.all(),
['<Plaything: p1>']
)
+ def test_join_already_in_query(self):
+ # Ordering by model related to nullable relations should not change
+ # the join type of already existing joins.
+ Plaything.objects.create(name="p1")
+ s = SingleObject.objects.create(name='s')
+ r = RelatedObject.objects.create(single=s)
+ Plaything.objects.create(name="p2", others=r)
+ qs = Plaything.objects.all().filter(others__isnull=False).order_by('pk')
+ self.assertTrue('INNER' in str(qs.query))
+ qs = qs.order_by('others__single__name')
+ # The ordering by others__single__pk will add one new join (to single)
+ # and that join must be LEFT join. The already existing join to related
+ # objects must be kept INNER. So, we have both a INNER and a LEFT join
+ # in the query.
+ self.assertTrue('LEFT' in str(qs.query))
+ self.assertTrue('INNER' in str(qs.query))
+ self.assertQuerysetEqual(
+ qs,
+ ['<Plaything: p2>']
+ )
+
class DisjunctiveFilterTests(TestCase):
def setUp(self):
diff --git a/tests/regressiontests/requests/tests.py b/tests/regressiontests/requests/tests.py
index 5c49afbc35..3d2b196194 100644
--- a/tests/regressiontests/requests/tests.py
+++ b/tests/regressiontests/requests/tests.py
@@ -204,91 +204,91 @@ class RequestsTests(unittest.TestCase):
def test_limited_stream(self):
# Read all of a limited stream
- stream = LimitedStream(StringIO('test'), 2)
- self.assertEqual(stream.read(), 'te')
+ stream = LimitedStream(StringIO(b'test'), 2)
+ self.assertEqual(stream.read(), b'te')
# Reading again returns nothing.
- self.assertEqual(stream.read(), '')
+ self.assertEqual(stream.read(), b'')
# Read a number of characters greater than the stream has to offer
- stream = LimitedStream(StringIO('test'), 2)
- self.assertEqual(stream.read(5), 'te')
+ stream = LimitedStream(StringIO(b'test'), 2)
+ self.assertEqual(stream.read(5), b'te')
# Reading again returns nothing.
- self.assertEqual(stream.readline(5), '')
+ self.assertEqual(stream.readline(5), b'')
# Read sequentially from a stream
- stream = LimitedStream(StringIO('12345678'), 8)
- self.assertEqual(stream.read(5), '12345')
- self.assertEqual(stream.read(5), '678')
+ stream = LimitedStream(StringIO(b'12345678'), 8)
+ self.assertEqual(stream.read(5), b'12345')
+ self.assertEqual(stream.read(5), b'678')
# Reading again returns nothing.
- self.assertEqual(stream.readline(5), '')
+ self.assertEqual(stream.readline(5), b'')
# Read lines from a stream
- stream = LimitedStream(StringIO('1234\n5678\nabcd\nefgh\nijkl'), 24)
+ stream = LimitedStream(StringIO(b'1234\n5678\nabcd\nefgh\nijkl'), 24)
# Read a full line, unconditionally
- self.assertEqual(stream.readline(), '1234\n')
+ self.assertEqual(stream.readline(), b'1234\n')
# Read a number of characters less than a line
- self.assertEqual(stream.readline(2), '56')
+ self.assertEqual(stream.readline(2), b'56')
# Read the rest of the partial line
- self.assertEqual(stream.readline(), '78\n')
+ self.assertEqual(stream.readline(), b'78\n')
# Read a full line, with a character limit greater than the line length
- self.assertEqual(stream.readline(6), 'abcd\n')
+ self.assertEqual(stream.readline(6), b'abcd\n')
# Read the next line, deliberately terminated at the line end
- self.assertEqual(stream.readline(4), 'efgh')
+ self.assertEqual(stream.readline(4), b'efgh')
# Read the next line... just the line end
- self.assertEqual(stream.readline(), '\n')
+ self.assertEqual(stream.readline(), b'\n')
# Read everything else.
- self.assertEqual(stream.readline(), 'ijkl')
+ self.assertEqual(stream.readline(), b'ijkl')
# Regression for #15018
# If a stream contains a newline, but the provided length
# is less than the number of provided characters, the newline
# doesn't reset the available character count
- stream = LimitedStream(StringIO('1234\nabcdef'), 9)
- self.assertEqual(stream.readline(10), '1234\n')
- self.assertEqual(stream.readline(3), 'abc')
+ stream = LimitedStream(StringIO(b'1234\nabcdef'), 9)
+ self.assertEqual(stream.readline(10), b'1234\n')
+ self.assertEqual(stream.readline(3), b'abc')
# Now expire the available characters
- self.assertEqual(stream.readline(3), 'd')
+ self.assertEqual(stream.readline(3), b'd')
# Reading again returns nothing.
- self.assertEqual(stream.readline(2), '')
+ self.assertEqual(stream.readline(2), b'')
# Same test, but with read, not readline.
- stream = LimitedStream(StringIO('1234\nabcdef'), 9)
- self.assertEqual(stream.read(6), '1234\na')
- self.assertEqual(stream.read(2), 'bc')
- self.assertEqual(stream.read(2), 'd')
- self.assertEqual(stream.read(2), '')
- self.assertEqual(stream.read(), '')
+ stream = LimitedStream(StringIO(b'1234\nabcdef'), 9)
+ self.assertEqual(stream.read(6), b'1234\na')
+ self.assertEqual(stream.read(2), b'bc')
+ self.assertEqual(stream.read(2), b'd')
+ self.assertEqual(stream.read(2), b'')
+ self.assertEqual(stream.read(), b'')
def test_stream(self):
- payload = 'name=value'
+ payload = b'name=value'
request = WSGIRequest({'REQUEST_METHOD': 'POST',
'CONTENT_LENGTH': len(payload),
'wsgi.input': StringIO(payload)})
- self.assertEqual(request.read(), 'name=value')
+ self.assertEqual(request.read(), b'name=value')
def test_read_after_value(self):
"""
Reading from request is allowed after accessing request contents as
POST or body.
"""
- payload = 'name=value'
+ payload = b'name=value'
request = WSGIRequest({'REQUEST_METHOD': 'POST',
'CONTENT_LENGTH': len(payload),
'wsgi.input': StringIO(payload)})
self.assertEqual(request.POST, {u'name': [u'value']})
- self.assertEqual(request.body, 'name=value')
- self.assertEqual(request.read(), 'name=value')
+ self.assertEqual(request.body, b'name=value')
+ self.assertEqual(request.read(), b'name=value')
def test_value_after_read(self):
"""
Construction of POST or body is not allowed after reading
from request.
"""
- payload = 'name=value'
+ payload = b'name=value'
request = WSGIRequest({'REQUEST_METHOD': 'POST',
'CONTENT_LENGTH': len(payload),
'wsgi.input': StringIO(payload)})
- self.assertEqual(request.read(2), 'na')
+ self.assertEqual(request.read(2), b'na')
self.assertRaises(Exception, lambda: request.body)
self.assertEqual(request.POST, {})
@@ -335,17 +335,17 @@ class RequestsTests(unittest.TestCase):
self.assertEqual(request.POST, {})
def test_read_by_lines(self):
- payload = 'name=value'
+ payload = b'name=value'
request = WSGIRequest({'REQUEST_METHOD': 'POST',
'CONTENT_LENGTH': len(payload),
'wsgi.input': StringIO(payload)})
- self.assertEqual(list(request), ['name=value'])
+ self.assertEqual(list(request), [b'name=value'])
def test_POST_after_body_read(self):
"""
POST should be populated even if body is read first
"""
- payload = 'name=value'
+ payload = b'name=value'
request = WSGIRequest({'REQUEST_METHOD': 'POST',
'CONTENT_LENGTH': len(payload),
'wsgi.input': StringIO(payload)})
@@ -357,12 +357,12 @@ class RequestsTests(unittest.TestCase):
POST should be populated even if body is read first, and then
the stream is read second.
"""
- payload = 'name=value'
+ payload = b'name=value'
request = WSGIRequest({'REQUEST_METHOD': 'POST',
'CONTENT_LENGTH': len(payload),
'wsgi.input': StringIO(payload)})
raw_data = request.body
- self.assertEqual(request.read(1), u'n')
+ self.assertEqual(request.read(1), b'n')
self.assertEqual(request.POST, {u'name': [u'value']})
def test_POST_after_body_read_and_stream_read_multipart(self):
@@ -383,14 +383,14 @@ class RequestsTests(unittest.TestCase):
'wsgi.input': StringIO(payload)})
raw_data = request.body
# Consume enough data to mess up the parsing:
- self.assertEqual(request.read(13), u'--boundary\r\nC')
+ self.assertEqual(request.read(13), b'--boundary\r\nC')
self.assertEqual(request.POST, {u'name': [u'value']})
def test_raw_post_data_returns_body(self):
"""
HttpRequest.raw_post_body should be the same as HttpRequest.body
"""
- payload = 'Hello There!'
+ payload = b'Hello There!'
request = WSGIRequest({
'REQUEST_METHOD': 'POST',
'CONTENT_LENGTH': len(payload),
@@ -409,7 +409,7 @@ class RequestsTests(unittest.TestCase):
def read(self, len=0):
raise IOError("kaboom!")
- payload = 'name=value'
+ payload = b'name=value'
request = WSGIRequest({'REQUEST_METHOD': 'POST',
'CONTENT_LENGTH': len(payload),
'wsgi.input': ExplodingStringIO(payload)})
diff --git a/tests/regressiontests/servers/tests.py b/tests/regressiontests/servers/tests.py
index 5d287a195b..9537e1feb3 100644
--- a/tests/regressiontests/servers/tests.py
+++ b/tests/regressiontests/servers/tests.py
@@ -113,7 +113,7 @@ class LiveServerViews(LiveServerBase):
Refs #2879.
"""
f = self.urlopen('/example_view/')
- self.assertEqual(f.read(), 'example view')
+ self.assertEqual(f.read(), b'example view')
def test_static_files(self):
"""
@@ -121,7 +121,7 @@ class LiveServerViews(LiveServerBase):
Refs #2879.
"""
f = self.urlopen('/static/example_static_file.txt')
- self.assertEqual(f.read(), 'example static file\n')
+ self.assertEqual(f.read().rstrip(b'\r\n'), b'example static file')
def test_media_files(self):
"""
@@ -129,7 +129,7 @@ class LiveServerViews(LiveServerBase):
Refs #2879.
"""
f = self.urlopen('/media/example_media_file.txt')
- self.assertEqual(f.read(), 'example media file\n')
+ self.assertEqual(f.read().rstrip(b'\r\n'), b'example media file')
class LiveServerDatabase(LiveServerBase):
diff --git a/tests/regressiontests/signing/tests.py b/tests/regressiontests/signing/tests.py
index 54bc302454..1da3345806 100644
--- a/tests/regressiontests/signing/tests.py
+++ b/tests/regressiontests/signing/tests.py
@@ -12,8 +12,8 @@ class TestSigner(TestCase):
signer = signing.Signer('predictable-secret')
signer2 = signing.Signer('predictable-secret2')
for s in (
- 'hello',
- '3098247:529:087:',
+ b'hello',
+ b'3098247:529:087:',
u'\u2019'.encode('utf-8'),
):
self.assertEqual(
@@ -69,7 +69,7 @@ class TestSigner(TestCase):
"dumps and loads be reversible for any JSON serializable object"
objects = (
['a', 'list'],
- 'a string',
+ b'a string',
u'a unicode string \u2019',
{'a': 'dictionary'},
)
diff --git a/tests/regressiontests/staticfiles_tests/storage.py b/tests/regressiontests/staticfiles_tests/storage.py
index 8358f833c8..4d49e6fbb2 100644
--- a/tests/regressiontests/staticfiles_tests/storage.py
+++ b/tests/regressiontests/staticfiles_tests/storage.py
@@ -1,5 +1,6 @@
from datetime import datetime
from django.core.files import storage
+from django.contrib.staticfiles.storage import CachedStaticFilesStorage
class DummyStorage(storage.Storage):
"""
@@ -17,3 +18,9 @@ class DummyStorage(storage.Storage):
def modified_time(self, name):
return datetime.date(1970, 1, 1)
+
+
+class SimpleCachedStaticFilesStorage(CachedStaticFilesStorage):
+
+ def file_hash(self, name, content=None):
+ return 'deploy12345'
diff --git a/tests/regressiontests/staticfiles_tests/tests.py b/tests/regressiontests/staticfiles_tests/tests.py
index 7f30cb987a..3711d92448 100644
--- a/tests/regressiontests/staticfiles_tests/tests.py
+++ b/tests/regressiontests/staticfiles_tests/tests.py
@@ -6,11 +6,11 @@ import posixpath
import shutil
import sys
import tempfile
-from StringIO import StringIO
+from io import BytesIO
from django.template import loader, Context
from django.conf import settings
-from django.core.cache.backends.base import BaseCache, CacheKeyWarning
+from django.core.cache.backends.base import BaseCache
from django.core.exceptions import ImproperlyConfigured
from django.core.files.storage import default_storage
from django.core.management import call_command
@@ -187,30 +187,22 @@ class TestFindStatic(CollectionTestCase, TestDefaults):
Test ``findstatic`` management command.
"""
def _get_file(self, filepath):
- _stdout = sys.stdout
- sys.stdout = StringIO()
- try:
- call_command('findstatic', filepath, all=False, verbosity='0')
- sys.stdout.seek(0)
- lines = [l.strip() for l in sys.stdout.readlines()]
- contents = codecs.open(
- smart_unicode(lines[1].strip()), "r", "utf-8").read()
- finally:
- sys.stdout = _stdout
+ out = BytesIO()
+ call_command('findstatic', filepath, all=False, verbosity=0, stdout=out)
+ out.seek(0)
+ lines = [l.strip() for l in out.readlines()]
+ contents = codecs.open(
+ smart_unicode(lines[1].strip()), "r", "utf-8").read()
return contents
def test_all_files(self):
"""
Test that findstatic returns all candidate files if run without --first.
"""
- _stdout = sys.stdout
- sys.stdout = StringIO()
- try:
- call_command('findstatic', 'test/file.txt', verbosity='0')
- sys.stdout.seek(0)
- lines = [l.strip() for l in sys.stdout.readlines()]
- finally:
- sys.stdout = _stdout
+ out = BytesIO()
+ call_command('findstatic', 'test/file.txt', verbosity=0, stdout=out)
+ out.seek(0)
+ lines = [l.strip() for l in out.readlines()]
self.assertEqual(len(lines), 3) # three because there is also the "Found <file> here" line
self.assertIn('project', lines[1])
self.assertIn('apps', lines[2])
@@ -387,8 +379,8 @@ class TestCollectionCachedStorage(BaseCollectionTestCase,
self.assertEqual(relpath, "cached/styles.93b1147e8552.css")
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
- self.assertNotIn("cached/other.css", content)
- self.assertIn("other.d41d8cd98f00.css", content)
+ self.assertNotIn(b"cached/other.css", content)
+ self.assertIn(b"other.d41d8cd98f00.css", content)
def test_path_with_querystring(self):
relpath = self.cached_file_path("cached/styles.css?spam=eggs")
@@ -397,8 +389,8 @@ class TestCollectionCachedStorage(BaseCollectionTestCase,
with storage.staticfiles_storage.open(
"cached/styles.93b1147e8552.css") as relfile:
content = relfile.read()
- self.assertNotIn("cached/other.css", content)
- self.assertIn("other.d41d8cd98f00.css", content)
+ self.assertNotIn(b"cached/other.css", content)
+ self.assertIn(b"other.d41d8cd98f00.css", content)
def test_path_with_fragment(self):
relpath = self.cached_file_path("cached/styles.css#eggs")
@@ -406,62 +398,62 @@ class TestCollectionCachedStorage(BaseCollectionTestCase,
with storage.staticfiles_storage.open(
"cached/styles.93b1147e8552.css") as relfile:
content = relfile.read()
- self.assertNotIn("cached/other.css", content)
- self.assertIn("other.d41d8cd98f00.css", content)
+ self.assertNotIn(b"cached/other.css", content)
+ self.assertIn(b"other.d41d8cd98f00.css", content)
def test_path_with_querystring_and_fragment(self):
relpath = self.cached_file_path("cached/css/fragments.css")
self.assertEqual(relpath, "cached/css/fragments.75433540b096.css")
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
- self.assertIn('fonts/font.a4b0478549d0.eot?#iefix', content)
- self.assertIn('fonts/font.b8d603e42714.svg#webfontIyfZbseF', content)
- self.assertIn('data:font/woff;charset=utf-8;base64,d09GRgABAAAAADJoAA0AAAAAR2QAAQAAAAAAAAAAAAA', content)
- self.assertIn('#default#VML', content)
+ self.assertIn(b'fonts/font.a4b0478549d0.eot?#iefix', content)
+ self.assertIn(b'fonts/font.b8d603e42714.svg#webfontIyfZbseF', content)
+ self.assertIn(b'data:font/woff;charset=utf-8;base64,d09GRgABAAAAADJoAA0AAAAAR2QAAQAAAAAAAAAAAAA', content)
+ self.assertIn(b'#default#VML', content)
def test_template_tag_absolute(self):
relpath = self.cached_file_path("cached/absolute.css")
self.assertEqual(relpath, "cached/absolute.23f087ad823a.css")
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
- self.assertNotIn("/static/cached/styles.css", content)
- self.assertIn("/static/cached/styles.93b1147e8552.css", content)
- self.assertIn('/static/cached/img/relative.acae32e4532b.png', content)
+ self.assertNotIn(b"/static/cached/styles.css", content)
+ self.assertIn(b"/static/cached/styles.93b1147e8552.css", content)
+ self.assertIn(b'/static/cached/img/relative.acae32e4532b.png', content)
def test_template_tag_denorm(self):
relpath = self.cached_file_path("cached/denorm.css")
self.assertEqual(relpath, "cached/denorm.c5bd139ad821.css")
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
- self.assertNotIn("..//cached///styles.css", content)
- self.assertIn("../cached/styles.93b1147e8552.css", content)
- self.assertNotIn("url(img/relative.png )", content)
- self.assertIn('url("img/relative.acae32e4532b.png', content)
+ self.assertNotIn(b"..//cached///styles.css", content)
+ self.assertIn(b"../cached/styles.93b1147e8552.css", content)
+ self.assertNotIn(b"url(img/relative.png )", content)
+ self.assertIn(b'url("img/relative.acae32e4532b.png', content)
def test_template_tag_relative(self):
relpath = self.cached_file_path("cached/relative.css")
self.assertEqual(relpath, "cached/relative.2217ea7273c2.css")
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
- self.assertNotIn("../cached/styles.css", content)
- self.assertNotIn('@import "styles.css"', content)
- self.assertNotIn('url(img/relative.png)', content)
- self.assertIn('url("img/relative.acae32e4532b.png")', content)
- self.assertIn("../cached/styles.93b1147e8552.css", content)
+ self.assertNotIn(b"../cached/styles.css", content)
+ self.assertNotIn(b'@import "styles.css"', content)
+ self.assertNotIn(b'url(img/relative.png)', content)
+ self.assertIn(b'url("img/relative.acae32e4532b.png")', content)
+ self.assertIn(b"../cached/styles.93b1147e8552.css", content)
def test_template_tag_deep_relative(self):
relpath = self.cached_file_path("cached/css/window.css")
self.assertEqual(relpath, "cached/css/window.9db38d5169f3.css")
with storage.staticfiles_storage.open(relpath) as relfile:
content = relfile.read()
- self.assertNotIn('url(img/window.png)', content)
- self.assertIn('url("img/window.acae32e4532b.png")', content)
+ self.assertNotIn(b'url(img/window.png)', content)
+ self.assertIn(b'url("img/window.acae32e4532b.png")', content)
def test_template_tag_url(self):
relpath = self.cached_file_path("cached/url.css")
self.assertEqual(relpath, "cached/url.615e21601e4b.css")
with storage.staticfiles_storage.open(relpath) as relfile:
- self.assertIn("https://", relfile.read())
+ self.assertIn(b"https://", relfile.read())
def test_cache_invalidation(self):
name = "cached/styles.css"
@@ -508,13 +500,51 @@ class TestCollectionCachedStorage(BaseCollectionTestCase,
"""
Handle cache key creation correctly, see #17861.
"""
- name = "/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/" + chr(22) + chr(180)
+ name = b"/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/long filename/ with spaces Here and ?#%#$/other/stuff/some crazy/" + chr(22) + chr(180)
cache_key = storage.staticfiles_storage.cache_key(name)
cache_validator = BaseCache({})
cache_validator.validate_key(cache_key)
self.assertEqual(cache_key, 'staticfiles:e95bbc36387084582df2a70750d7b351')
+# we set DEBUG to False here since the template tag wouldn't work otherwise
+@override_settings(**dict(TEST_SETTINGS,
+ STATICFILES_STORAGE='regressiontests.staticfiles_tests.storage.SimpleCachedStaticFilesStorage',
+ DEBUG=False,
+))
+class TestCollectionSimpleCachedStorage(BaseCollectionTestCase,
+ BaseStaticFilesTestCase, TestCase):
+ """
+ Tests for the Cache busting storage
+ """
+ def cached_file_path(self, path):
+ fullpath = self.render_template(self.static_template_snippet(path))
+ return fullpath.replace(settings.STATIC_URL, '')
+
+ def test_template_tag_return(self):
+ """
+ Test the CachedStaticFilesStorage backend.
+ """
+ self.assertStaticRaises(ValueError,
+ "does/not/exist.png",
+ "/static/does/not/exist.png")
+ self.assertStaticRenders("test/file.txt",
+ "/static/test/file.deploy12345.txt")
+ self.assertStaticRenders("cached/styles.css",
+ "/static/cached/styles.deploy12345.css")
+ self.assertStaticRenders("path/",
+ "/static/path/")
+ self.assertStaticRenders("path/?query",
+ "/static/path/?query")
+
+ def test_template_tag_simple_content(self):
+ relpath = self.cached_file_path("cached/styles.css")
+ self.assertEqual(relpath, "cached/styles.deploy12345.css")
+ with storage.staticfiles_storage.open(relpath) as relfile:
+ content = relfile.read()
+ self.assertNotIn("cached/other.css", content)
+ self.assertIn("other.deploy12345.css", content)
+
if sys.platform != 'win32':
class TestCollectionLinks(CollectionTestCase, TestDefaults):
diff --git a/tests/regressiontests/string_lookup/tests.py b/tests/regressiontests/string_lookup/tests.py
index f5ae73a6ca..b3f90169ca 100644
--- a/tests/regressiontests/string_lookup/tests.py
+++ b/tests/regressiontests/string_lookup/tests.py
@@ -54,7 +54,7 @@ class StringLookupTests(TestCase):
self.assertEqual(Foo.objects.get(friend__contains=u'\xe7'), fx)
# We can also do the above query using UTF-8 strings.
- self.assertEqual(Foo.objects.get(friend__contains='\xc3\xa7'), fx)
+ self.assertEqual(Foo.objects.get(friend__contains=b'\xc3\xa7'), fx)
def test_queries_on_textfields(self):
"""
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index d4ef2aa574..8590dd25af 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -192,17 +192,17 @@ class Templates(unittest.TestCase):
test_template_sources('../dir1blah', template_dirs, [])
# UTF-8 bytestrings are permitted.
- test_template_sources('\xc3\x85ngstr\xc3\xb6m', template_dirs,
+ test_template_sources(b'\xc3\x85ngstr\xc3\xb6m', template_dirs,
[u'/dir1/Ångström', u'/dir2/Ångström'])
# Unicode strings are permitted.
test_template_sources(u'Ångström', template_dirs,
[u'/dir1/Ångström', u'/dir2/Ångström'])
- test_template_sources(u'Ångström', ['/Straße'], [u'/Straße/Ångström'])
- test_template_sources('\xc3\x85ngstr\xc3\xb6m', ['/Straße'],
+ test_template_sources(u'Ångström', [b'/Stra\xc3\x9fe'], [u'/Straße/Ångström'])
+ test_template_sources(b'\xc3\x85ngstr\xc3\xb6m', [b'/Stra\xc3\x9fe'],
[u'/Straße/Ångström'])
# Invalid UTF-8 encoding in bytestrings is not. Should raise a
# semi-useful error message.
- test_template_sources('\xc3\xc3', template_dirs, UnicodeDecodeError)
+ test_template_sources(b'\xc3\xc3', template_dirs, UnicodeDecodeError)
# Case insensitive tests (for win32). Not run unless we're on
# a case insensitive operating system.
@@ -1239,11 +1239,11 @@ class Templates(unittest.TestCase):
'i18n02': ('{% load i18n %}{% trans "xxxyyyxxx" %}', {}, "xxxyyyxxx"),
# simple translation of a variable
- 'i18n03': ('{% load i18n %}{% blocktrans %}{{ anton }}{% endblocktrans %}', {'anton': '\xc3\x85'}, u"Å"),
+ 'i18n03': ('{% load i18n %}{% blocktrans %}{{ anton }}{% endblocktrans %}', {'anton': b'\xc3\x85'}, u"Å"),
# simple translation of a variable and filter
- 'i18n04': ('{% load i18n %}{% blocktrans with berta=anton|lower %}{{ berta }}{% endblocktrans %}', {'anton': '\xc3\x85'}, u'å'),
- 'legacyi18n04': ('{% load i18n %}{% blocktrans with anton|lower as berta %}{{ berta }}{% endblocktrans %}', {'anton': '\xc3\x85'}, u'å'),
+ 'i18n04': ('{% load i18n %}{% blocktrans with berta=anton|lower %}{{ berta }}{% endblocktrans %}', {'anton': b'\xc3\x85'}, u'å'),
+ 'legacyi18n04': ('{% load i18n %}{% blocktrans with anton|lower as berta %}{{ berta }}{% endblocktrans %}', {'anton': b'\xc3\x85'}, u'å'),
# simple translation of a string with interpolation
'i18n05': ('{% load i18n %}{% blocktrans %}xxx{{ anton }}xxx{% endblocktrans %}', {'anton': 'yyy'}, "xxxyyyxxx"),
diff --git a/tests/regressiontests/templates/unicode.py b/tests/regressiontests/templates/unicode.py
index c8d7309ad7..0e0cefeb8e 100644
--- a/tests/regressiontests/templates/unicode.py
+++ b/tests/regressiontests/templates/unicode.py
@@ -10,16 +10,16 @@ class UnicodeTests(TestCase):
t1 = Template(u'ŠĐĆŽćžšđ {{ var }}')
# Templates can also be created from bytestrings. These are assumed to
# be encoded using UTF-8.
- s = '\xc5\xa0\xc4\x90\xc4\x86\xc5\xbd\xc4\x87\xc5\xbe\xc5\xa1\xc4\x91 {{ var }}'
+ s = b'\xc5\xa0\xc4\x90\xc4\x86\xc5\xbd\xc4\x87\xc5\xbe\xc5\xa1\xc4\x91 {{ var }}'
t2 = Template(s)
- s = '\x80\xc5\xc0'
+ s = b'\x80\xc5\xc0'
self.assertRaises(TemplateEncodingError, Template, s)
# Contexts can be constructed from unicode or UTF-8 bytestrings.
- c1 = Context({"var": "foo"})
- c2 = Context({u"var": "foo"})
- c3 = Context({"var": u"Đđ"})
- c4 = Context({u"var": "\xc4\x90\xc4\x91"})
+ c1 = Context({b"var": b"foo"})
+ c2 = Context({u"var": b"foo"})
+ c3 = Context({b"var": u"Đđ"})
+ c4 = Context({u"var": b"\xc4\x90\xc4\x91"})
# Since both templates and all four contexts represent the same thing,
# they all render the same (and are returned as unicode objects and
diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py
index 4f057b934c..e69de29bb2 100644
--- a/tests/regressiontests/test_client_regress/models.py
+++ b/tests/regressiontests/test_client_regress/models.py
@@ -1,1034 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-Regression tests for the Test Client, especially the customized assertions.
-"""
-import os
-
-from django.conf import settings
-from django.core.exceptions import SuspiciousOperation
-from django.core.urlresolvers import reverse
-from django.template import (TemplateDoesNotExist, TemplateSyntaxError,
- Context, Template, loader)
-import django.template.context
-from django.test import Client, TestCase
-from django.test.client import encode_file, RequestFactory
-from django.test.utils import ContextList, override_settings
-from django.template.response import SimpleTemplateResponse
-from django.http import HttpResponse
-
-
-class AssertContainsTests(TestCase):
- def setUp(self):
- self.old_templates = settings.TEMPLATE_DIRS
- settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), 'templates'),)
-
- def tearDown(self):
- settings.TEMPLATE_DIRS = self.old_templates
-
- def test_contains(self):
- "Responses can be inspected for content, including counting repeated substrings"
- response = self.client.get('/test_client_regress/no_template_view/')
-
- self.assertNotContains(response, 'never')
- self.assertContains(response, 'never', 0)
- self.assertContains(response, 'once')
- self.assertContains(response, 'once', 1)
- self.assertContains(response, 'twice')
- self.assertContains(response, 'twice', 2)
-
- try:
- self.assertContains(response, 'text', status_code=999)
- except AssertionError as e:
- self.assertIn("Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
- try:
- self.assertContains(response, 'text', status_code=999, msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
-
- try:
- self.assertNotContains(response, 'text', status_code=999)
- except AssertionError as e:
- self.assertIn("Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
- try:
- self.assertNotContains(response, 'text', status_code=999, msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
-
- try:
- self.assertNotContains(response, 'once')
- except AssertionError as e:
- self.assertIn("Response should not contain 'once'", str(e))
- try:
- self.assertNotContains(response, 'once', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Response should not contain 'once'", str(e))
-
- try:
- self.assertContains(response, 'never', 1)
- except AssertionError as e:
- self.assertIn("Found 0 instances of 'never' in response (expected 1)", str(e))
- try:
- self.assertContains(response, 'never', 1, msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Found 0 instances of 'never' in response (expected 1)", str(e))
-
- try:
- self.assertContains(response, 'once', 0)
- except AssertionError as e:
- self.assertIn("Found 1 instances of 'once' in response (expected 0)", str(e))
- try:
- self.assertContains(response, 'once', 0, msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Found 1 instances of 'once' in response (expected 0)", str(e))
-
- try:
- self.assertContains(response, 'once', 2)
- except AssertionError as e:
- self.assertIn("Found 1 instances of 'once' in response (expected 2)", str(e))
- try:
- self.assertContains(response, 'once', 2, msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Found 1 instances of 'once' in response (expected 2)", str(e))
-
- try:
- self.assertContains(response, 'twice', 1)
- except AssertionError as e:
- self.assertIn("Found 2 instances of 'twice' in response (expected 1)", str(e))
- try:
- self.assertContains(response, 'twice', 1, msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Found 2 instances of 'twice' in response (expected 1)", str(e))
-
- try:
- self.assertContains(response, 'thrice')
- except AssertionError as e:
- self.assertIn("Couldn't find 'thrice' in response", str(e))
- try:
- self.assertContains(response, 'thrice', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Couldn't find 'thrice' in response", str(e))
-
- try:
- self.assertContains(response, 'thrice', 3)
- except AssertionError as e:
- self.assertIn("Found 0 instances of 'thrice' in response (expected 3)", str(e))
- try:
- self.assertContains(response, 'thrice', 3, msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Found 0 instances of 'thrice' in response (expected 3)", str(e))
-
- def test_unicode_contains(self):
- "Unicode characters can be found in template context"
- #Regression test for #10183
- r = self.client.get('/test_client_regress/check_unicode/')
- self.assertContains(r, u'さかき')
- self.assertContains(r, '\xe5\xb3\xa0'.decode('utf-8'))
-
- def test_unicode_not_contains(self):
- "Unicode characters can be searched for, and not found in template context"
- #Regression test for #10183
- r = self.client.get('/test_client_regress/check_unicode/')
- self.assertNotContains(r, u'はたけ')
- self.assertNotContains(r, '\xe3\x81\xaf\xe3\x81\x9f\xe3\x81\x91'.decode('utf-8'))
-
- def test_assert_contains_renders_template_response(self):
- """ Test that we can pass in an unrendered SimpleTemplateReponse
- without throwing an error.
- Refs #15826.
- """
- response = SimpleTemplateResponse(Template('Hello'), status=200)
- self.assertContains(response, 'Hello')
-
- def test_assert_contains_using_non_template_response(self):
- """ Test that auto-rendering does not affect responses that aren't
- instances (or subclasses) of SimpleTemplateResponse.
- Refs #15826.
- """
- response = HttpResponse('Hello')
- self.assertContains(response, 'Hello')
-
- def test_assert_not_contains_renders_template_response(self):
- """ Test that we can pass in an unrendered SimpleTemplateReponse
- without throwing an error.
- Refs #15826.
- """
- response = SimpleTemplateResponse(Template('Hello'), status=200)
- self.assertNotContains(response, 'Bye')
-
- def test_assert_not_contains_using_non_template_response(self):
- """ Test that auto-rendering does not affect responses that aren't
- instances (or subclasses) of SimpleTemplateResponse.
- Refs #15826.
- """
- response = HttpResponse('Hello')
- self.assertNotContains(response, 'Bye')
-
-@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
-class AssertTemplateUsedTests(TestCase):
- fixtures = ['testdata.json']
-
- def test_no_context(self):
- "Template usage assertions work then templates aren't in use"
- response = self.client.get('/test_client_regress/no_template_view/')
-
- # Check that the no template case doesn't mess with the template assertions
- self.assertTemplateNotUsed(response, 'GET Template')
-
- try:
- self.assertTemplateUsed(response, 'GET Template')
- except AssertionError as e:
- self.assertIn("No templates used to render the response", str(e))
-
- try:
- self.assertTemplateUsed(response, 'GET Template', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: No templates used to render the response", str(e))
-
- def test_single_context(self):
- "Template assertions work when there is a single context"
- response = self.client.get('/test_client/post_view/', {})
-
- try:
- self.assertTemplateNotUsed(response, 'Empty GET Template')
- except AssertionError as e:
- self.assertIn("Template 'Empty GET Template' was used unexpectedly in rendering the response", str(e))
-
- try:
- self.assertTemplateNotUsed(response, 'Empty GET Template', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Template 'Empty GET Template' was used unexpectedly in rendering the response", str(e))
-
- try:
- self.assertTemplateUsed(response, 'Empty POST Template')
- except AssertionError as e:
- self.assertIn("Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template", str(e))
-
- try:
- self.assertTemplateUsed(response, 'Empty POST Template', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template", str(e))
-
- def test_multiple_context(self):
- "Template assertions work when there are multiple contexts"
- post_data = {
- 'text': 'Hello World',
- 'email': 'foo@example.com',
- 'value': 37,
- 'single': 'b',
- 'multi': ('b','c','e')
- }
- response = self.client.post('/test_client/form_view_with_template/', post_data)
- self.assertContains(response, 'POST data OK')
- try:
- self.assertTemplateNotUsed(response, "form_view.html")
- except AssertionError as e:
- self.assertIn("Template 'form_view.html' was used unexpectedly in rendering the response", str(e))
-
- try:
- self.assertTemplateNotUsed(response, 'base.html')
- except AssertionError as e:
- self.assertIn("Template 'base.html' was used unexpectedly in rendering the response", str(e))
-
- try:
- self.assertTemplateUsed(response, "Valid POST Template")
- except AssertionError as e:
- self.assertIn("Template 'Valid POST Template' was not a template used to render the response. Actual template(s) used: form_view.html, base.html", str(e))
-
-class AssertRedirectsTests(TestCase):
- def test_redirect_page(self):
- "An assertion is raised if the original page couldn't be retrieved as expected"
- # This page will redirect with code 301, not 302
- response = self.client.get('/test_client/permanent_redirect_view/')
- try:
- self.assertRedirects(response, '/test_client/get_view/')
- except AssertionError as e:
- self.assertIn("Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
-
- try:
- self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
-
- def test_lost_query(self):
- "An assertion is raised if the redirect location doesn't preserve GET parameters"
- response = self.client.get('/test_client/redirect_view/', {'var': 'value'})
- try:
- self.assertRedirects(response, '/test_client/get_view/')
- except AssertionError as e:
- self.assertIn("Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'", str(e))
-
- try:
- self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'", str(e))
-
- def test_incorrect_target(self):
- "An assertion is raised if the response redirects to another target"
- response = self.client.get('/test_client/permanent_redirect_view/')
- try:
- # Should redirect to get_view
- self.assertRedirects(response, '/test_client/some_view/')
- except AssertionError as e:
- self.assertIn("Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
-
- def test_target_page(self):
- "An assertion is raised if the response redirect target cannot be retrieved as expected"
- response = self.client.get('/test_client/double_redirect_view/')
- try:
- # The redirect target responds with a 301 code, not 200
- self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/')
- except AssertionError as e:
- self.assertIn("Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)", str(e))
-
- try:
- # The redirect target responds with a 301 code, not 200
- self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)", str(e))
-
- def test_redirect_chain(self):
- "You can follow a redirect chain of multiple redirects"
- response = self.client.get('/test_client_regress/redirects/further/more/', {}, follow=True)
- self.assertRedirects(response, '/test_client_regress/no_template_view/',
- status_code=301, target_status_code=200)
-
- self.assertEqual(len(response.redirect_chain), 1)
- self.assertEqual(response.redirect_chain[0], ('http://testserver/test_client_regress/no_template_view/', 301))
-
- def test_multiple_redirect_chain(self):
- "You can follow a redirect chain of multiple redirects"
- response = self.client.get('/test_client_regress/redirects/', {}, follow=True)
- self.assertRedirects(response, '/test_client_regress/no_template_view/',
- status_code=301, target_status_code=200)
-
- self.assertEqual(len(response.redirect_chain), 3)
- self.assertEqual(response.redirect_chain[0], ('http://testserver/test_client_regress/redirects/further/', 301))
- self.assertEqual(response.redirect_chain[1], ('http://testserver/test_client_regress/redirects/further/more/', 301))
- self.assertEqual(response.redirect_chain[2], ('http://testserver/test_client_regress/no_template_view/', 301))
-
- def test_redirect_chain_to_non_existent(self):
- "You can follow a chain to a non-existent view"
- response = self.client.get('/test_client_regress/redirect_to_non_existent_view2/', {}, follow=True)
- self.assertRedirects(response, '/test_client_regress/non_existent_view/',
- status_code=301, target_status_code=404)
-
- def test_redirect_chain_to_self(self):
- "Redirections to self are caught and escaped"
- response = self.client.get('/test_client_regress/redirect_to_self/', {}, follow=True)
- # The chain of redirects stops once the cycle is detected.
- self.assertRedirects(response, '/test_client_regress/redirect_to_self/',
- status_code=301, target_status_code=301)
- self.assertEqual(len(response.redirect_chain), 2)
-
- def test_circular_redirect(self):
- "Circular redirect chains are caught and escaped"
- response = self.client.get('/test_client_regress/circular_redirect_1/', {}, follow=True)
- # The chain of redirects will get back to the starting point, but stop there.
- self.assertRedirects(response, '/test_client_regress/circular_redirect_2/',
- status_code=301, target_status_code=301)
- self.assertEqual(len(response.redirect_chain), 4)
-
- def test_redirect_chain_post(self):
- "A redirect chain will be followed from an initial POST post"
- response = self.client.post('/test_client_regress/redirects/',
- {'nothing': 'to_send'}, follow=True)
- self.assertRedirects(response,
- '/test_client_regress/no_template_view/', 301, 200)
- self.assertEqual(len(response.redirect_chain), 3)
-
- def test_redirect_chain_head(self):
- "A redirect chain will be followed from an initial HEAD request"
- response = self.client.head('/test_client_regress/redirects/',
- {'nothing': 'to_send'}, follow=True)
- self.assertRedirects(response,
- '/test_client_regress/no_template_view/', 301, 200)
- self.assertEqual(len(response.redirect_chain), 3)
-
- def test_redirect_chain_options(self):
- "A redirect chain will be followed from an initial OPTIONS request"
- response = self.client.options('/test_client_regress/redirects/',
- {'nothing': 'to_send'}, follow=True)
- self.assertRedirects(response,
- '/test_client_regress/no_template_view/', 301, 200)
- self.assertEqual(len(response.redirect_chain), 3)
-
- def test_redirect_chain_put(self):
- "A redirect chain will be followed from an initial PUT request"
- response = self.client.put('/test_client_regress/redirects/',
- {'nothing': 'to_send'}, follow=True)
- self.assertRedirects(response,
- '/test_client_regress/no_template_view/', 301, 200)
- self.assertEqual(len(response.redirect_chain), 3)
-
- def test_redirect_chain_delete(self):
- "A redirect chain will be followed from an initial DELETE request"
- response = self.client.delete('/test_client_regress/redirects/',
- {'nothing': 'to_send'}, follow=True)
- self.assertRedirects(response,
- '/test_client_regress/no_template_view/', 301, 200)
- self.assertEqual(len(response.redirect_chain), 3)
-
- def test_redirect_to_different_host(self):
- "The test client will preserve scheme, host and port changes"
- response = self.client.get('/test_client_regress/redirect_other_host/', follow=True)
- self.assertRedirects(response,
- 'https://otherserver:8443/test_client_regress/no_template_view/',
- status_code=301, target_status_code=200)
- # We can't use is_secure() or get_host()
- # because response.request is a dictionary, not an HttpRequest
- self.assertEqual(response.request.get('wsgi.url_scheme'), 'https')
- self.assertEqual(response.request.get('SERVER_NAME'), 'otherserver')
- self.assertEqual(response.request.get('SERVER_PORT'), '8443')
-
- def test_redirect_chain_on_non_redirect_page(self):
- "An assertion is raised if the original page couldn't be retrieved as expected"
- # This page will redirect with code 301, not 302
- response = self.client.get('/test_client/get_view/', follow=True)
- try:
- self.assertRedirects(response, '/test_client/get_view/')
- except AssertionError as e:
- self.assertIn("Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
-
- try:
- self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
-
- def test_redirect_on_non_redirect_page(self):
- "An assertion is raised if the original page couldn't be retrieved as expected"
- # This page will redirect with code 301, not 302
- response = self.client.get('/test_client/get_view/')
- try:
- self.assertRedirects(response, '/test_client/get_view/')
- except AssertionError as e:
- self.assertIn("Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
-
- try:
- self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
-
-
-class AssertFormErrorTests(TestCase):
- def test_unknown_form(self):
- "An assertion is raised if the form name is unknown"
- post_data = {
- 'text': 'Hello World',
- 'email': 'not an email address',
- 'value': 37,
- 'single': 'b',
- 'multi': ('b','c','e')
- }
- response = self.client.post('/test_client/form_view/', post_data)
- self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, "Invalid POST Template")
-
- try:
- self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.')
- except AssertionError as e:
- self.assertIn("The form 'wrong_form' was not used to render the response", str(e))
- try:
- self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: The form 'wrong_form' was not used to render the response", str(e))
-
- def test_unknown_field(self):
- "An assertion is raised if the field name is unknown"
- post_data = {
- 'text': 'Hello World',
- 'email': 'not an email address',
- 'value': 37,
- 'single': 'b',
- 'multi': ('b','c','e')
- }
- response = self.client.post('/test_client/form_view/', post_data)
- self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, "Invalid POST Template")
-
- try:
- self.assertFormError(response, 'form', 'some_field', 'Some error.')
- except AssertionError as e:
- self.assertIn("The form 'form' in context 0 does not contain the field 'some_field'", str(e))
- try:
- self.assertFormError(response, 'form', 'some_field', 'Some error.', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: The form 'form' in context 0 does not contain the field 'some_field'", str(e))
-
- def test_noerror_field(self):
- "An assertion is raised if the field doesn't have any errors"
- post_data = {
- 'text': 'Hello World',
- 'email': 'not an email address',
- 'value': 37,
- 'single': 'b',
- 'multi': ('b','c','e')
- }
- response = self.client.post('/test_client/form_view/', post_data)
- self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, "Invalid POST Template")
-
- try:
- self.assertFormError(response, 'form', 'value', 'Some error.')
- except AssertionError as e:
- self.assertIn("The field 'value' on form 'form' in context 0 contains no errors", str(e))
- try:
- self.assertFormError(response, 'form', 'value', 'Some error.', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: The field 'value' on form 'form' in context 0 contains no errors", str(e))
-
- def test_unknown_error(self):
- "An assertion is raised if the field doesn't contain the provided error"
- post_data = {
- 'text': 'Hello World',
- 'email': 'not an email address',
- 'value': 37,
- 'single': 'b',
- 'multi': ('b','c','e')
- }
- response = self.client.post('/test_client/form_view/', post_data)
- self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, "Invalid POST Template")
-
- try:
- self.assertFormError(response, 'form', 'email', 'Some error.')
- except AssertionError as e:
- self.assertIn("The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])", str(e))
- try:
- self.assertFormError(response, 'form', 'email', 'Some error.', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])", str(e))
-
- def test_unknown_nonfield_error(self):
- """
- Checks that an assertion is raised if the form's non field errors
- doesn't contain the provided error.
- """
- post_data = {
- 'text': 'Hello World',
- 'email': 'not an email address',
- 'value': 37,
- 'single': 'b',
- 'multi': ('b','c','e')
- }
- response = self.client.post('/test_client/form_view/', post_data)
- self.assertEqual(response.status_code, 200)
- self.assertTemplateUsed(response, "Invalid POST Template")
-
- try:
- self.assertFormError(response, 'form', None, 'Some error.')
- except AssertionError as e:
- self.assertIn("The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )", str(e))
- try:
- self.assertFormError(response, 'form', None, 'Some error.', msg_prefix='abc')
- except AssertionError as e:
- self.assertIn("abc: The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )", str(e))
-
-@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
-class LoginTests(TestCase):
- fixtures = ['testdata']
-
- def test_login_different_client(self):
- "Check that using a different test client doesn't violate authentication"
-
- # Create a second client, and log in.
- c = Client()
- login = c.login(username='testclient', password='password')
- self.assertTrue(login, 'Could not log in')
-
- # Get a redirection page with the second client.
- response = c.get("/test_client_regress/login_protected_redirect_view/")
-
- # At this points, the self.client isn't logged in.
- # Check that assertRedirects uses the original client, not the
- # default client.
- self.assertRedirects(response, "http://testserver/test_client_regress/get_view/")
-
-
-@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
-class SessionEngineTests(TestCase):
- fixtures = ['testdata']
-
- def setUp(self):
- self.old_SESSION_ENGINE = settings.SESSION_ENGINE
- settings.SESSION_ENGINE = 'regressiontests.test_client_regress.session'
-
- def tearDown(self):
- settings.SESSION_ENGINE = self.old_SESSION_ENGINE
-
- def test_login(self):
- "A session engine that modifies the session key can be used to log in"
- login = self.client.login(username='testclient', password='password')
- self.assertTrue(login, 'Could not log in')
-
- # Try to access a login protected page.
- response = self.client.get("/test_client/login_protected_view/")
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.context['user'].username, 'testclient')
-
-
-class URLEscapingTests(TestCase):
- def test_simple_argument_get(self):
- "Get a view that has a simple string argument"
- response = self.client.get(reverse('arg_view', args=['Slartibartfast']))
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'Howdy, Slartibartfast')
-
- def test_argument_with_space_get(self):
- "Get a view that has a string argument that requires escaping"
- response = self.client.get(reverse('arg_view', args=['Arthur Dent']))
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'Hi, Arthur')
-
- def test_simple_argument_post(self):
- "Post for a view that has a simple string argument"
- response = self.client.post(reverse('arg_view', args=['Slartibartfast']))
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'Howdy, Slartibartfast')
-
- def test_argument_with_space_post(self):
- "Post for a view that has a string argument that requires escaping"
- response = self.client.post(reverse('arg_view', args=['Arthur Dent']))
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'Hi, Arthur')
-
-@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
-class ExceptionTests(TestCase):
- fixtures = ['testdata.json']
-
- def test_exception_cleared(self):
- "#5836 - A stale user exception isn't re-raised by the test client."
-
- login = self.client.login(username='testclient',password='password')
- self.assertTrue(login, 'Could not log in')
- try:
- response = self.client.get("/test_client_regress/staff_only/")
- self.fail("General users should not be able to visit this page")
- except SuspiciousOperation:
- pass
-
- # At this point, an exception has been raised, and should be cleared.
-
- # This next operation should be successful; if it isn't we have a problem.
- login = self.client.login(username='staff', password='password')
- self.assertTrue(login, 'Could not log in')
- try:
- self.client.get("/test_client_regress/staff_only/")
- except SuspiciousOperation:
- self.fail("Staff should be able to visit this page")
-
-class TemplateExceptionTests(TestCase):
- def setUp(self):
- # Reset the loaders so they don't try to render cached templates.
- if loader.template_source_loaders is not None:
- for template_loader in loader.template_source_loaders:
- if hasattr(template_loader, 'reset'):
- template_loader.reset()
- self.old_templates = settings.TEMPLATE_DIRS
- settings.TEMPLATE_DIRS = ()
-
- def tearDown(self):
- settings.TEMPLATE_DIRS = self.old_templates
-
- def test_no_404_template(self):
- "Missing templates are correctly reported by test client"
- try:
- response = self.client.get("/no_such_view/")
- self.fail("Should get error about missing template")
- except TemplateDoesNotExist:
- pass
-
- def test_bad_404_template(self):
- "Errors found when rendering 404 error templates are re-raised"
- settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), 'bad_templates'),)
- try:
- response = self.client.get("/no_such_view/")
- self.fail("Should get error about syntax error in template")
- except TemplateSyntaxError:
- pass
-
-# We need two different tests to check URLconf substitution - one to check
-# it was changed, and another one (without self.urls) to check it was reverted on
-# teardown. This pair of tests relies upon the alphabetical ordering of test execution.
-class UrlconfSubstitutionTests(TestCase):
- urls = 'regressiontests.test_client_regress.urls'
-
- def test_urlconf_was_changed(self):
- "TestCase can enforce a custom URLconf on a per-test basis"
- url = reverse('arg_view', args=['somename'])
- self.assertEqual(url, '/arg_view/somename/')
-
-# This test needs to run *after* UrlconfSubstitutionTests; the zz prefix in the
-# name is to ensure alphabetical ordering.
-class zzUrlconfSubstitutionTests(TestCase):
- def test_urlconf_was_reverted(self):
- "URLconf is reverted to original value after modification in a TestCase"
- url = reverse('arg_view', args=['somename'])
- self.assertEqual(url, '/test_client_regress/arg_view/somename/')
-
-@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
-class ContextTests(TestCase):
- fixtures = ['testdata']
-
- def test_single_context(self):
- "Context variables can be retrieved from a single context"
- response = self.client.get("/test_client_regress/request_data/", data={'foo':'whiz'})
- self.assertEqual(response.context.__class__, Context)
- self.assertTrue('get-foo' in response.context)
- self.assertEqual(response.context['get-foo'], 'whiz')
- self.assertEqual(response.context['request-foo'], 'whiz')
- self.assertEqual(response.context['data'], 'sausage')
-
- try:
- response.context['does-not-exist']
- self.fail('Should not be able to retrieve non-existent key')
- except KeyError as e:
- self.assertEqual(e.args[0], 'does-not-exist')
-
- def test_inherited_context(self):
- "Context variables can be retrieved from a list of contexts"
- response = self.client.get("/test_client_regress/request_data_extended/", data={'foo':'whiz'})
- self.assertEqual(response.context.__class__, ContextList)
- self.assertEqual(len(response.context), 2)
- self.assertTrue('get-foo' in response.context)
- self.assertEqual(response.context['get-foo'], 'whiz')
- self.assertEqual(response.context['request-foo'], 'whiz')
- self.assertEqual(response.context['data'], 'bacon')
-
- try:
- response.context['does-not-exist']
- self.fail('Should not be able to retrieve non-existent key')
- except KeyError as e:
- self.assertEqual(e.args[0], 'does-not-exist')
-
- def test_15368(self):
- # Need to insert a context processor that assumes certain things about
- # the request instance. This triggers a bug caused by some ways of
- # copying RequestContext.
- try:
- django.template.context._standard_context_processors = (lambda request: {'path': request.special_path},)
- response = self.client.get("/test_client_regress/request_context_view/")
- self.assertContains(response, 'Path: /test_client_regress/request_context_view/')
- finally:
- django.template.context._standard_context_processors = None
-
-
-@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
-class SessionTests(TestCase):
- fixtures = ['testdata.json']
-
- def test_session(self):
- "The session isn't lost if a user logs in"
- # The session doesn't exist to start.
- response = self.client.get('/test_client_regress/check_session/')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'NO')
-
- # This request sets a session variable.
- response = self.client.get('/test_client_regress/set_session/')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'set_session')
-
- # Check that the session has been modified
- response = self.client.get('/test_client_regress/check_session/')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'YES')
-
- # Log in
- login = self.client.login(username='testclient',password='password')
- self.assertTrue(login, 'Could not log in')
-
- # Session should still contain the modified value
- response = self.client.get('/test_client_regress/check_session/')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'YES')
-
- def test_logout(self):
- """Logout should work whether the user is logged in or not (#9978)."""
- self.client.logout()
- login = self.client.login(username='testclient',password='password')
- self.assertTrue(login, 'Could not log in')
- self.client.logout()
- self.client.logout()
-
-class RequestMethodTests(TestCase):
- def test_get(self):
- "Request a view via request method GET"
- response = self.client.get('/test_client_regress/request_methods/')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'request method: GET')
-
- def test_post(self):
- "Request a view via request method POST"
- response = self.client.post('/test_client_regress/request_methods/')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'request method: POST')
-
- def test_head(self):
- "Request a view via request method HEAD"
- response = self.client.head('/test_client_regress/request_methods/')
- self.assertEqual(response.status_code, 200)
- # A HEAD request doesn't return any content.
- self.assertNotEqual(response.content, 'request method: HEAD')
- self.assertEqual(response.content, '')
-
- def test_options(self):
- "Request a view via request method OPTIONS"
- response = self.client.options('/test_client_regress/request_methods/')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'request method: OPTIONS')
-
- def test_put(self):
- "Request a view via request method PUT"
- response = self.client.put('/test_client_regress/request_methods/')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'request method: PUT')
-
- def test_delete(self):
- "Request a view via request method DELETE"
- response = self.client.delete('/test_client_regress/request_methods/')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'request method: DELETE')
-
-class RequestMethodStringDataTests(TestCase):
- def test_post(self):
- "Request a view with string data via request method POST"
- # Regression test for #11371
- data = u'{"test": "json"}'
- response = self.client.post('/test_client_regress/request_methods/', data=data, content_type='application/json')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'request method: POST')
-
- def test_put(self):
- "Request a view with string data via request method PUT"
- # Regression test for #11371
- data = u'{"test": "json"}'
- response = self.client.put('/test_client_regress/request_methods/', data=data, content_type='application/json')
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.content, 'request method: PUT')
-
-class QueryStringTests(TestCase):
- def test_get_like_requests(self):
- # See: https://code.djangoproject.com/ticket/10571.
- # Removed 'put' and 'delete' here as they are 'GET-like requests'
- for method_name in ('get','head','options'):
- # A GET-like request can pass a query string as data
- method = getattr(self.client, method_name)
- response = method("/test_client_regress/request_data/", data={'foo':'whiz'})
- self.assertEqual(response.context['get-foo'], 'whiz')
- self.assertEqual(response.context['request-foo'], 'whiz')
-
- # A GET-like request can pass a query string as part of the URL
- response = method("/test_client_regress/request_data/?foo=whiz")
- self.assertEqual(response.context['get-foo'], 'whiz')
- self.assertEqual(response.context['request-foo'], 'whiz')
-
- # Data provided in the URL to a GET-like request is overridden by actual form data
- response = method("/test_client_regress/request_data/?foo=whiz", data={'foo':'bang'})
- self.assertEqual(response.context['get-foo'], 'bang')
- self.assertEqual(response.context['request-foo'], 'bang')
-
- response = method("/test_client_regress/request_data/?foo=whiz", data={'bar':'bang'})
- self.assertEqual(response.context['get-foo'], None)
- self.assertEqual(response.context['get-bar'], 'bang')
- self.assertEqual(response.context['request-foo'], None)
- self.assertEqual(response.context['request-bar'], 'bang')
-
- def test_post_like_requests(self):
- # A POST-like request can pass a query string as data
- response = self.client.post("/test_client_regress/request_data/", data={'foo':'whiz'})
- self.assertEqual(response.context['get-foo'], None)
- self.assertEqual(response.context['post-foo'], 'whiz')
-
- # A POST-like request can pass a query string as part of the URL
- response = self.client.post("/test_client_regress/request_data/?foo=whiz")
- self.assertEqual(response.context['get-foo'], 'whiz')
- self.assertEqual(response.context['post-foo'], None)
- self.assertEqual(response.context['request-foo'], 'whiz')
-
- # POST data provided in the URL augments actual form data
- response = self.client.post("/test_client_regress/request_data/?foo=whiz", data={'foo':'bang'})
- self.assertEqual(response.context['get-foo'], 'whiz')
- self.assertEqual(response.context['post-foo'], 'bang')
- self.assertEqual(response.context['request-foo'], 'bang')
-
- response = self.client.post("/test_client_regress/request_data/?foo=whiz", data={'bar':'bang'})
- self.assertEqual(response.context['get-foo'], 'whiz')
- self.assertEqual(response.context['get-bar'], None)
- self.assertEqual(response.context['post-foo'], None)
- self.assertEqual(response.context['post-bar'], 'bang')
- self.assertEqual(response.context['request-foo'], 'whiz')
- self.assertEqual(response.context['request-bar'], 'bang')
-
-class UnicodePayloadTests(TestCase):
- def test_simple_unicode_payload(self):
- "A simple ASCII-only unicode JSON document can be POSTed"
- # Regression test for #10571
- json = u'{"english": "mountain pass"}'
- response = self.client.post("/test_client_regress/parse_unicode_json/", json,
- content_type="application/json")
- self.assertEqual(response.content, json)
- response = self.client.put("/test_client_regress/parse_unicode_json/", json,
- content_type="application/json")
- self.assertEqual(response.content, json)
-
- def test_unicode_payload_utf8(self):
- "A non-ASCII unicode data encoded as UTF-8 can be POSTed"
- # Regression test for #10571
- json = u'{"dog": "собака"}'
- response = self.client.post("/test_client_regress/parse_unicode_json/", json,
- content_type="application/json; charset=utf-8")
- self.assertEqual(response.content, json.encode('utf-8'))
- response = self.client.put("/test_client_regress/parse_unicode_json/", json,
- content_type="application/json; charset=utf-8")
- self.assertEqual(response.content, json.encode('utf-8'))
-
- def test_unicode_payload_utf16(self):
- "A non-ASCII unicode data encoded as UTF-16 can be POSTed"
- # Regression test for #10571
- json = u'{"dog": "собака"}'
- response = self.client.post("/test_client_regress/parse_unicode_json/", json,
- content_type="application/json; charset=utf-16")
- self.assertEqual(response.content, json.encode('utf-16'))
- response = self.client.put("/test_client_regress/parse_unicode_json/", json,
- content_type="application/json; charset=utf-16")
- self.assertEqual(response.content, json.encode('utf-16'))
-
- def test_unicode_payload_non_utf(self):
- "A non-ASCII unicode data as a non-UTF based encoding can be POSTed"
- #Regression test for #10571
- json = u'{"dog": "собака"}'
- response = self.client.post("/test_client_regress/parse_unicode_json/", json,
- content_type="application/json; charset=koi8-r")
- self.assertEqual(response.content, json.encode('koi8-r'))
- response = self.client.put("/test_client_regress/parse_unicode_json/", json,
- content_type="application/json; charset=koi8-r")
- self.assertEqual(response.content, json.encode('koi8-r'))
-
-class DummyFile(object):
- def __init__(self, filename):
- self.name = filename
- def read(self):
- return 'TEST_FILE_CONTENT'
-
-class UploadedFileEncodingTest(TestCase):
- def test_file_encoding(self):
- encoded_file = encode_file('TEST_BOUNDARY', 'TEST_KEY', DummyFile('test_name.bin'))
- self.assertEqual('--TEST_BOUNDARY', encoded_file[0])
- self.assertEqual('Content-Disposition: form-data; name="TEST_KEY"; filename="test_name.bin"', encoded_file[1])
- self.assertEqual('TEST_FILE_CONTENT', encoded_file[-1])
-
- def test_guesses_content_type_on_file_encoding(self):
- self.assertEqual('Content-Type: application/octet-stream',
- encode_file('IGNORE', 'IGNORE', DummyFile("file.bin"))[2])
- self.assertEqual('Content-Type: text/plain',
- encode_file('IGNORE', 'IGNORE', DummyFile("file.txt"))[2])
- self.assertIn(encode_file('IGNORE', 'IGNORE', DummyFile("file.zip"))[2], (
- 'Content-Type: application/x-compress',
- 'Content-Type: application/x-zip',
- 'Content-Type: application/x-zip-compressed',
- 'Content-Type: application/zip',))
- self.assertEqual('Content-Type: application/octet-stream',
- encode_file('IGNORE', 'IGNORE', DummyFile("file.unknown"))[2])
-
-class RequestHeadersTest(TestCase):
- def test_client_headers(self):
- "A test client can receive custom headers"
- response = self.client.get("/test_client_regress/check_headers/", HTTP_X_ARG_CHECK='Testing 123')
- self.assertEqual(response.content, "HTTP_X_ARG_CHECK: Testing 123")
- self.assertEqual(response.status_code, 200)
-
- def test_client_headers_redirect(self):
- "Test client headers are preserved through redirects"
- response = self.client.get("/test_client_regress/check_headers_redirect/", follow=True, HTTP_X_ARG_CHECK='Testing 123')
- self.assertEqual(response.content, "HTTP_X_ARG_CHECK: Testing 123")
- self.assertRedirects(response, '/test_client_regress/check_headers/',
- status_code=301, target_status_code=200)
-
-
-class ReadLimitedStreamTest(TestCase):
- """
- Tests that ensure that HttpRequest.body, HttpRequest.read() and
- HttpRequest.read(BUFFER) have proper LimitedStream behavior.
-
- Refs #14753, #15785
- """
-
- def test_body_from_empty_request(self):
- """HttpRequest.body on a test client GET request should return
- the empty string."""
- self.assertEqual(self.client.get("/test_client_regress/body/").content, '')
-
- def test_read_from_empty_request(self):
- """HttpRequest.read() on a test client GET request should return the
- empty string."""
- self.assertEqual(self.client.get("/test_client_regress/read_all/").content, '')
-
- def test_read_numbytes_from_empty_request(self):
- """HttpRequest.read(LARGE_BUFFER) on a test client GET request should
- return the empty string."""
- self.assertEqual(self.client.get("/test_client_regress/read_buffer/").content, '')
-
- def test_read_from_nonempty_request(self):
- """HttpRequest.read() on a test client PUT request with some payload
- should return that payload."""
- payload = 'foobar'
- self.assertEqual(self.client.put("/test_client_regress/read_all/",
- data=payload,
- content_type='text/plain').content, payload)
-
- def test_read_numbytes_from_nonempty_request(self):
- """HttpRequest.read(LARGE_BUFFER) on a test client PUT request with
- some payload should return that payload."""
- payload = 'foobar'
- self.assertEqual(self.client.put("/test_client_regress/read_buffer/",
- data=payload,
- content_type='text/plain').content, payload)
-
-
-class RequestFactoryStateTest(TestCase):
- """Regression tests for #15929."""
- # These tests are checking that certain middleware don't change certain
- # global state. Alternatively, from the point of view of a test, they are
- # ensuring test isolation behavior. So, unusually, it doesn't make sense to
- # run the tests individually, and if any are failing it is confusing to run
- # them with any other set of tests.
-
- def setUp(self):
- self.factory = RequestFactory()
-
- def common_test_that_should_always_pass(self):
- request = self.factory.get('/')
- request.session = {}
- self.assertFalse(hasattr(request, 'user'))
-
- def test_request(self):
- self.common_test_that_should_always_pass()
-
- def test_request_after_client(self):
- # apart from the next line the three tests are identical
- self.client.get('/')
- self.common_test_that_should_always_pass()
-
- def test_request_after_client_2(self):
- # This test is executed after the previous one
- self.common_test_that_should_always_pass()
-
-
-class RequestFactoryEnvironmentTests(TestCase):
- """
- Regression tests for #8551 and #17067: ensure that environment variables
- are set correctly in RequestFactory.
- """
-
- def setUp(self):
- self.factory = RequestFactory()
-
- def test_should_set_correct_env_variables(self):
- request = self.factory.get('/path/')
-
- self.assertEqual(request.META.get('REMOTE_ADDR'), '127.0.0.1')
- self.assertEqual(request.META.get('SERVER_NAME'), 'testserver')
- self.assertEqual(request.META.get('SERVER_PORT'), '80')
- self.assertEqual(request.META.get('SERVER_PROTOCOL'), 'HTTP/1.1')
- self.assertEqual(request.META.get('SCRIPT_NAME') +
- request.META.get('PATH_INFO'), '/path/')
diff --git a/tests/regressiontests/test_client_regress/tests.py b/tests/regressiontests/test_client_regress/tests.py
new file mode 100644
index 0000000000..ece487a211
--- /dev/null
+++ b/tests/regressiontests/test_client_regress/tests.py
@@ -0,0 +1,1006 @@
+# -*- coding: utf-8 -*-
+"""
+Regression tests for the Test Client, especially the customized assertions.
+"""
+import os
+
+from django.conf import settings
+from django.core.exceptions import SuspiciousOperation
+from django.core.urlresolvers import reverse
+from django.template import (TemplateDoesNotExist, TemplateSyntaxError,
+ Context, Template, loader)
+import django.template.context
+from django.test import Client, TestCase
+from django.test.client import encode_file, RequestFactory
+from django.test.utils import ContextList, override_settings
+from django.template.response import SimpleTemplateResponse
+from django.http import HttpResponse
+
+
+@override_settings(
+ TEMPLATE_DIRS=(os.path.join(os.path.dirname(__file__), 'templates'),)
+)
+class AssertContainsTests(TestCase):
+ def test_contains(self):
+ "Responses can be inspected for content, including counting repeated substrings"
+ response = self.client.get('/test_client_regress/no_template_view/')
+
+ self.assertNotContains(response, 'never')
+ self.assertContains(response, 'never', 0)
+ self.assertContains(response, 'once')
+ self.assertContains(response, 'once', 1)
+ self.assertContains(response, 'twice')
+ self.assertContains(response, 'twice', 2)
+
+ try:
+ self.assertContains(response, 'text', status_code=999)
+ except AssertionError as e:
+ self.assertIn("Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
+ try:
+ self.assertContains(response, 'text', status_code=999, msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
+
+ try:
+ self.assertNotContains(response, 'text', status_code=999)
+ except AssertionError as e:
+ self.assertIn("Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
+ try:
+ self.assertNotContains(response, 'text', status_code=999, msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
+
+ try:
+ self.assertNotContains(response, 'once')
+ except AssertionError as e:
+ self.assertIn("Response should not contain 'once'", str(e))
+ try:
+ self.assertNotContains(response, 'once', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Response should not contain 'once'", str(e))
+
+ try:
+ self.assertContains(response, 'never', 1)
+ except AssertionError as e:
+ self.assertIn("Found 0 instances of 'never' in response (expected 1)", str(e))
+ try:
+ self.assertContains(response, 'never', 1, msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Found 0 instances of 'never' in response (expected 1)", str(e))
+
+ try:
+ self.assertContains(response, 'once', 0)
+ except AssertionError as e:
+ self.assertIn("Found 1 instances of 'once' in response (expected 0)", str(e))
+ try:
+ self.assertContains(response, 'once', 0, msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Found 1 instances of 'once' in response (expected 0)", str(e))
+
+ try:
+ self.assertContains(response, 'once', 2)
+ except AssertionError as e:
+ self.assertIn("Found 1 instances of 'once' in response (expected 2)", str(e))
+ try:
+ self.assertContains(response, 'once', 2, msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Found 1 instances of 'once' in response (expected 2)", str(e))
+
+ try:
+ self.assertContains(response, 'twice', 1)
+ except AssertionError as e:
+ self.assertIn("Found 2 instances of 'twice' in response (expected 1)", str(e))
+ try:
+ self.assertContains(response, 'twice', 1, msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Found 2 instances of 'twice' in response (expected 1)", str(e))
+
+ try:
+ self.assertContains(response, 'thrice')
+ except AssertionError as e:
+ self.assertIn("Couldn't find 'thrice' in response", str(e))
+ try:
+ self.assertContains(response, 'thrice', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Couldn't find 'thrice' in response", str(e))
+
+ try:
+ self.assertContains(response, 'thrice', 3)
+ except AssertionError as e:
+ self.assertIn("Found 0 instances of 'thrice' in response (expected 3)", str(e))
+ try:
+ self.assertContains(response, 'thrice', 3, msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Found 0 instances of 'thrice' in response (expected 3)", str(e))
+
+ def test_unicode_contains(self):
+ "Unicode characters can be found in template context"
+ #Regression test for #10183
+ r = self.client.get('/test_client_regress/check_unicode/')
+ self.assertContains(r, u'さかき')
+ self.assertContains(r, b'\xe5\xb3\xa0'.decode('utf-8'))
+
+ def test_unicode_not_contains(self):
+ "Unicode characters can be searched for, and not found in template context"
+ #Regression test for #10183
+ r = self.client.get('/test_client_regress/check_unicode/')
+ self.assertNotContains(r, u'はたけ')
+ self.assertNotContains(r, b'\xe3\x81\xaf\xe3\x81\x9f\xe3\x81\x91'.decode('utf-8'))
+
+ def test_assert_contains_renders_template_response(self):
+ """ Test that we can pass in an unrendered SimpleTemplateReponse
+ without throwing an error.
+ Refs #15826.
+ """
+ response = SimpleTemplateResponse(Template('Hello'), status=200)
+ self.assertContains(response, 'Hello')
+
+ def test_assert_contains_using_non_template_response(self):
+ """ Test that auto-rendering does not affect responses that aren't
+ instances (or subclasses) of SimpleTemplateResponse.
+ Refs #15826.
+ """
+ response = HttpResponse('Hello')
+ self.assertContains(response, 'Hello')
+
+ def test_assert_not_contains_renders_template_response(self):
+ """ Test that we can pass in an unrendered SimpleTemplateReponse
+ without throwing an error.
+ Refs #15826.
+ """
+ response = SimpleTemplateResponse(Template('Hello'), status=200)
+ self.assertNotContains(response, 'Bye')
+
+ def test_assert_not_contains_using_non_template_response(self):
+ """ Test that auto-rendering does not affect responses that aren't
+ instances (or subclasses) of SimpleTemplateResponse.
+ Refs #15826.
+ """
+ response = HttpResponse('Hello')
+ self.assertNotContains(response, 'Bye')
+
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
+class AssertTemplateUsedTests(TestCase):
+ fixtures = ['testdata.json']
+
+ def test_no_context(self):
+ "Template usage assertions work then templates aren't in use"
+ response = self.client.get('/test_client_regress/no_template_view/')
+
+ # Check that the no template case doesn't mess with the template assertions
+ self.assertTemplateNotUsed(response, 'GET Template')
+
+ try:
+ self.assertTemplateUsed(response, 'GET Template')
+ except AssertionError as e:
+ self.assertIn("No templates used to render the response", str(e))
+
+ try:
+ self.assertTemplateUsed(response, 'GET Template', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: No templates used to render the response", str(e))
+
+ def test_single_context(self):
+ "Template assertions work when there is a single context"
+ response = self.client.get('/test_client/post_view/', {})
+
+ try:
+ self.assertTemplateNotUsed(response, 'Empty GET Template')
+ except AssertionError as e:
+ self.assertIn("Template 'Empty GET Template' was used unexpectedly in rendering the response", str(e))
+
+ try:
+ self.assertTemplateNotUsed(response, 'Empty GET Template', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Template 'Empty GET Template' was used unexpectedly in rendering the response", str(e))
+
+ try:
+ self.assertTemplateUsed(response, 'Empty POST Template')
+ except AssertionError as e:
+ self.assertIn("Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template", str(e))
+
+ try:
+ self.assertTemplateUsed(response, 'Empty POST Template', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template", str(e))
+
+ def test_multiple_context(self):
+ "Template assertions work when there are multiple contexts"
+ post_data = {
+ 'text': 'Hello World',
+ 'email': 'foo@example.com',
+ 'value': 37,
+ 'single': 'b',
+ 'multi': ('b','c','e')
+ }
+ response = self.client.post('/test_client/form_view_with_template/', post_data)
+ self.assertContains(response, 'POST data OK')
+ try:
+ self.assertTemplateNotUsed(response, "form_view.html")
+ except AssertionError as e:
+ self.assertIn("Template 'form_view.html' was used unexpectedly in rendering the response", str(e))
+
+ try:
+ self.assertTemplateNotUsed(response, 'base.html')
+ except AssertionError as e:
+ self.assertIn("Template 'base.html' was used unexpectedly in rendering the response", str(e))
+
+ try:
+ self.assertTemplateUsed(response, "Valid POST Template")
+ except AssertionError as e:
+ self.assertIn("Template 'Valid POST Template' was not a template used to render the response. Actual template(s) used: form_view.html, base.html", str(e))
+
+class AssertRedirectsTests(TestCase):
+ def test_redirect_page(self):
+ "An assertion is raised if the original page couldn't be retrieved as expected"
+ # This page will redirect with code 301, not 302
+ response = self.client.get('/test_client/permanent_redirect_view/')
+ try:
+ self.assertRedirects(response, '/test_client/get_view/')
+ except AssertionError as e:
+ self.assertIn("Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
+
+ try:
+ self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
+
+ def test_lost_query(self):
+ "An assertion is raised if the redirect location doesn't preserve GET parameters"
+ response = self.client.get('/test_client/redirect_view/', {'var': 'value'})
+ try:
+ self.assertRedirects(response, '/test_client/get_view/')
+ except AssertionError as e:
+ self.assertIn("Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'", str(e))
+
+ try:
+ self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'", str(e))
+
+ def test_incorrect_target(self):
+ "An assertion is raised if the response redirects to another target"
+ response = self.client.get('/test_client/permanent_redirect_view/')
+ try:
+ # Should redirect to get_view
+ self.assertRedirects(response, '/test_client/some_view/')
+ except AssertionError as e:
+ self.assertIn("Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
+
+ def test_target_page(self):
+ "An assertion is raised if the response redirect target cannot be retrieved as expected"
+ response = self.client.get('/test_client/double_redirect_view/')
+ try:
+ # The redirect target responds with a 301 code, not 200
+ self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/')
+ except AssertionError as e:
+ self.assertIn("Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)", str(e))
+
+ try:
+ # The redirect target responds with a 301 code, not 200
+ self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)", str(e))
+
+ def test_redirect_chain(self):
+ "You can follow a redirect chain of multiple redirects"
+ response = self.client.get('/test_client_regress/redirects/further/more/', {}, follow=True)
+ self.assertRedirects(response, '/test_client_regress/no_template_view/',
+ status_code=301, target_status_code=200)
+
+ self.assertEqual(len(response.redirect_chain), 1)
+ self.assertEqual(response.redirect_chain[0], ('http://testserver/test_client_regress/no_template_view/', 301))
+
+ def test_multiple_redirect_chain(self):
+ "You can follow a redirect chain of multiple redirects"
+ response = self.client.get('/test_client_regress/redirects/', {}, follow=True)
+ self.assertRedirects(response, '/test_client_regress/no_template_view/',
+ status_code=301, target_status_code=200)
+
+ self.assertEqual(len(response.redirect_chain), 3)
+ self.assertEqual(response.redirect_chain[0], ('http://testserver/test_client_regress/redirects/further/', 301))
+ self.assertEqual(response.redirect_chain[1], ('http://testserver/test_client_regress/redirects/further/more/', 301))
+ self.assertEqual(response.redirect_chain[2], ('http://testserver/test_client_regress/no_template_view/', 301))
+
+ def test_redirect_chain_to_non_existent(self):
+ "You can follow a chain to a non-existent view"
+ response = self.client.get('/test_client_regress/redirect_to_non_existent_view2/', {}, follow=True)
+ self.assertRedirects(response, '/test_client_regress/non_existent_view/',
+ status_code=301, target_status_code=404)
+
+ def test_redirect_chain_to_self(self):
+ "Redirections to self are caught and escaped"
+ response = self.client.get('/test_client_regress/redirect_to_self/', {}, follow=True)
+ # The chain of redirects stops once the cycle is detected.
+ self.assertRedirects(response, '/test_client_regress/redirect_to_self/',
+ status_code=301, target_status_code=301)
+ self.assertEqual(len(response.redirect_chain), 2)
+
+ def test_circular_redirect(self):
+ "Circular redirect chains are caught and escaped"
+ response = self.client.get('/test_client_regress/circular_redirect_1/', {}, follow=True)
+ # The chain of redirects will get back to the starting point, but stop there.
+ self.assertRedirects(response, '/test_client_regress/circular_redirect_2/',
+ status_code=301, target_status_code=301)
+ self.assertEqual(len(response.redirect_chain), 4)
+
+ def test_redirect_chain_post(self):
+ "A redirect chain will be followed from an initial POST post"
+ response = self.client.post('/test_client_regress/redirects/',
+ {'nothing': 'to_send'}, follow=True)
+ self.assertRedirects(response,
+ '/test_client_regress/no_template_view/', 301, 200)
+ self.assertEqual(len(response.redirect_chain), 3)
+
+ def test_redirect_chain_head(self):
+ "A redirect chain will be followed from an initial HEAD request"
+ response = self.client.head('/test_client_regress/redirects/',
+ {'nothing': 'to_send'}, follow=True)
+ self.assertRedirects(response,
+ '/test_client_regress/no_template_view/', 301, 200)
+ self.assertEqual(len(response.redirect_chain), 3)
+
+ def test_redirect_chain_options(self):
+ "A redirect chain will be followed from an initial OPTIONS request"
+ response = self.client.options('/test_client_regress/redirects/',
+ follow=True)
+ self.assertRedirects(response,
+ '/test_client_regress/no_template_view/', 301, 200)
+ self.assertEqual(len(response.redirect_chain), 3)
+
+ def test_redirect_chain_put(self):
+ "A redirect chain will be followed from an initial PUT request"
+ response = self.client.put('/test_client_regress/redirects/',
+ follow=True)
+ self.assertRedirects(response,
+ '/test_client_regress/no_template_view/', 301, 200)
+ self.assertEqual(len(response.redirect_chain), 3)
+
+ def test_redirect_chain_delete(self):
+ "A redirect chain will be followed from an initial DELETE request"
+ response = self.client.delete('/test_client_regress/redirects/',
+ follow=True)
+ self.assertRedirects(response,
+ '/test_client_regress/no_template_view/', 301, 200)
+ self.assertEqual(len(response.redirect_chain), 3)
+
+ def test_redirect_to_different_host(self):
+ "The test client will preserve scheme, host and port changes"
+ response = self.client.get('/test_client_regress/redirect_other_host/', follow=True)
+ self.assertRedirects(response,
+ 'https://otherserver:8443/test_client_regress/no_template_view/',
+ status_code=301, target_status_code=200)
+ # We can't use is_secure() or get_host()
+ # because response.request is a dictionary, not an HttpRequest
+ self.assertEqual(response.request.get('wsgi.url_scheme'), 'https')
+ self.assertEqual(response.request.get('SERVER_NAME'), 'otherserver')
+ self.assertEqual(response.request.get('SERVER_PORT'), '8443')
+
+ def test_redirect_chain_on_non_redirect_page(self):
+ "An assertion is raised if the original page couldn't be retrieved as expected"
+ # This page will redirect with code 301, not 302
+ response = self.client.get('/test_client/get_view/', follow=True)
+ try:
+ self.assertRedirects(response, '/test_client/get_view/')
+ except AssertionError as e:
+ self.assertIn("Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
+
+ try:
+ self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
+
+ def test_redirect_on_non_redirect_page(self):
+ "An assertion is raised if the original page couldn't be retrieved as expected"
+ # This page will redirect with code 301, not 302
+ response = self.client.get('/test_client/get_view/')
+ try:
+ self.assertRedirects(response, '/test_client/get_view/')
+ except AssertionError as e:
+ self.assertIn("Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
+
+ try:
+ self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
+
+
+class AssertFormErrorTests(TestCase):
+ def test_unknown_form(self):
+ "An assertion is raised if the form name is unknown"
+ post_data = {
+ 'text': 'Hello World',
+ 'email': 'not an email address',
+ 'value': 37,
+ 'single': 'b',
+ 'multi': ('b','c','e')
+ }
+ response = self.client.post('/test_client/form_view/', post_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, "Invalid POST Template")
+
+ try:
+ self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.')
+ except AssertionError as e:
+ self.assertIn("The form 'wrong_form' was not used to render the response", str(e))
+ try:
+ self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: The form 'wrong_form' was not used to render the response", str(e))
+
+ def test_unknown_field(self):
+ "An assertion is raised if the field name is unknown"
+ post_data = {
+ 'text': 'Hello World',
+ 'email': 'not an email address',
+ 'value': 37,
+ 'single': 'b',
+ 'multi': ('b','c','e')
+ }
+ response = self.client.post('/test_client/form_view/', post_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, "Invalid POST Template")
+
+ try:
+ self.assertFormError(response, 'form', 'some_field', 'Some error.')
+ except AssertionError as e:
+ self.assertIn("The form 'form' in context 0 does not contain the field 'some_field'", str(e))
+ try:
+ self.assertFormError(response, 'form', 'some_field', 'Some error.', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: The form 'form' in context 0 does not contain the field 'some_field'", str(e))
+
+ def test_noerror_field(self):
+ "An assertion is raised if the field doesn't have any errors"
+ post_data = {
+ 'text': 'Hello World',
+ 'email': 'not an email address',
+ 'value': 37,
+ 'single': 'b',
+ 'multi': ('b','c','e')
+ }
+ response = self.client.post('/test_client/form_view/', post_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, "Invalid POST Template")
+
+ try:
+ self.assertFormError(response, 'form', 'value', 'Some error.')
+ except AssertionError as e:
+ self.assertIn("The field 'value' on form 'form' in context 0 contains no errors", str(e))
+ try:
+ self.assertFormError(response, 'form', 'value', 'Some error.', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: The field 'value' on form 'form' in context 0 contains no errors", str(e))
+
+ def test_unknown_error(self):
+ "An assertion is raised if the field doesn't contain the provided error"
+ post_data = {
+ 'text': 'Hello World',
+ 'email': 'not an email address',
+ 'value': 37,
+ 'single': 'b',
+ 'multi': ('b','c','e')
+ }
+ response = self.client.post('/test_client/form_view/', post_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, "Invalid POST Template")
+
+ try:
+ self.assertFormError(response, 'form', 'email', 'Some error.')
+ except AssertionError as e:
+ self.assertIn("The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])", str(e))
+ try:
+ self.assertFormError(response, 'form', 'email', 'Some error.', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])", str(e))
+
+ def test_unknown_nonfield_error(self):
+ """
+ Checks that an assertion is raised if the form's non field errors
+ doesn't contain the provided error.
+ """
+ post_data = {
+ 'text': 'Hello World',
+ 'email': 'not an email address',
+ 'value': 37,
+ 'single': 'b',
+ 'multi': ('b','c','e')
+ }
+ response = self.client.post('/test_client/form_view/', post_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, "Invalid POST Template")
+
+ try:
+ self.assertFormError(response, 'form', None, 'Some error.')
+ except AssertionError as e:
+ self.assertIn("The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )", str(e))
+ try:
+ self.assertFormError(response, 'form', None, 'Some error.', msg_prefix='abc')
+ except AssertionError as e:
+ self.assertIn("abc: The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )", str(e))
+
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
+class LoginTests(TestCase):
+ fixtures = ['testdata']
+
+ def test_login_different_client(self):
+ "Check that using a different test client doesn't violate authentication"
+
+ # Create a second client, and log in.
+ c = Client()
+ login = c.login(username='testclient', password='password')
+ self.assertTrue(login, 'Could not log in')
+
+ # Get a redirection page with the second client.
+ response = c.get("/test_client_regress/login_protected_redirect_view/")
+
+ # At this points, the self.client isn't logged in.
+ # Check that assertRedirects uses the original client, not the
+ # default client.
+ self.assertRedirects(response, "http://testserver/test_client_regress/get_view/")
+
+
+@override_settings(
+ PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',),
+ SESSION_ENGINE='regressiontests.test_client_regress.session'
+)
+class SessionEngineTests(TestCase):
+ fixtures = ['testdata']
+
+ def test_login(self):
+ "A session engine that modifies the session key can be used to log in"
+ login = self.client.login(username='testclient', password='password')
+ self.assertTrue(login, 'Could not log in')
+
+ # Try to access a login protected page.
+ response = self.client.get("/test_client/login_protected_view/")
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.context['user'].username, 'testclient')
+
+
+class URLEscapingTests(TestCase):
+ def test_simple_argument_get(self):
+ "Get a view that has a simple string argument"
+ response = self.client.get(reverse('arg_view', args=['Slartibartfast']))
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'Howdy, Slartibartfast')
+
+ def test_argument_with_space_get(self):
+ "Get a view that has a string argument that requires escaping"
+ response = self.client.get(reverse('arg_view', args=['Arthur Dent']))
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'Hi, Arthur')
+
+ def test_simple_argument_post(self):
+ "Post for a view that has a simple string argument"
+ response = self.client.post(reverse('arg_view', args=['Slartibartfast']))
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'Howdy, Slartibartfast')
+
+ def test_argument_with_space_post(self):
+ "Post for a view that has a string argument that requires escaping"
+ response = self.client.post(reverse('arg_view', args=['Arthur Dent']))
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'Hi, Arthur')
+
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
+class ExceptionTests(TestCase):
+ fixtures = ['testdata.json']
+
+ def test_exception_cleared(self):
+ "#5836 - A stale user exception isn't re-raised by the test client."
+
+ login = self.client.login(username='testclient',password='password')
+ self.assertTrue(login, 'Could not log in')
+ try:
+ response = self.client.get("/test_client_regress/staff_only/")
+ self.fail("General users should not be able to visit this page")
+ except SuspiciousOperation:
+ pass
+
+ # At this point, an exception has been raised, and should be cleared.
+
+ # This next operation should be successful; if it isn't we have a problem.
+ login = self.client.login(username='staff', password='password')
+ self.assertTrue(login, 'Could not log in')
+ try:
+ self.client.get("/test_client_regress/staff_only/")
+ except SuspiciousOperation:
+ self.fail("Staff should be able to visit this page")
+
+
+class TemplateExceptionTests(TestCase):
+ def setUp(self):
+ # Reset the loaders so they don't try to render cached templates.
+ if loader.template_source_loaders is not None:
+ for template_loader in loader.template_source_loaders:
+ if hasattr(template_loader, 'reset'):
+ template_loader.reset()
+
+ @override_settings(TEMPLATE_DIRS=(),)
+ def test_no_404_template(self):
+ "Missing templates are correctly reported by test client"
+ try:
+ response = self.client.get("/no_such_view/")
+ self.fail("Should get error about missing template")
+ except TemplateDoesNotExist:
+ pass
+
+ @override_settings(
+ TEMPLATE_DIRS=(os.path.join(os.path.dirname(__file__), 'bad_templates'),)
+ )
+ def test_bad_404_template(self):
+ "Errors found when rendering 404 error templates are re-raised"
+ try:
+ response = self.client.get("/no_such_view/")
+ self.fail("Should get error about syntax error in template")
+ except TemplateSyntaxError:
+ pass
+
+# We need two different tests to check URLconf substitution - one to check
+# it was changed, and another one (without self.urls) to check it was reverted on
+# teardown. This pair of tests relies upon the alphabetical ordering of test execution.
+class UrlconfSubstitutionTests(TestCase):
+ urls = 'regressiontests.test_client_regress.urls'
+
+ def test_urlconf_was_changed(self):
+ "TestCase can enforce a custom URLconf on a per-test basis"
+ url = reverse('arg_view', args=['somename'])
+ self.assertEqual(url, '/arg_view/somename/')
+
+# This test needs to run *after* UrlconfSubstitutionTests; the zz prefix in the
+# name is to ensure alphabetical ordering.
+class zzUrlconfSubstitutionTests(TestCase):
+ def test_urlconf_was_reverted(self):
+ "URLconf is reverted to original value after modification in a TestCase"
+ url = reverse('arg_view', args=['somename'])
+ self.assertEqual(url, '/test_client_regress/arg_view/somename/')
+
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
+class ContextTests(TestCase):
+ fixtures = ['testdata']
+
+ def test_single_context(self):
+ "Context variables can be retrieved from a single context"
+ response = self.client.get("/test_client_regress/request_data/", data={'foo':'whiz'})
+ self.assertEqual(response.context.__class__, Context)
+ self.assertTrue('get-foo' in response.context)
+ self.assertEqual(response.context['get-foo'], 'whiz')
+ self.assertEqual(response.context['request-foo'], 'whiz')
+ self.assertEqual(response.context['data'], 'sausage')
+
+ try:
+ response.context['does-not-exist']
+ self.fail('Should not be able to retrieve non-existent key')
+ except KeyError as e:
+ self.assertEqual(e.args[0], 'does-not-exist')
+
+ def test_inherited_context(self):
+ "Context variables can be retrieved from a list of contexts"
+ response = self.client.get("/test_client_regress/request_data_extended/", data={'foo':'whiz'})
+ self.assertEqual(response.context.__class__, ContextList)
+ self.assertEqual(len(response.context), 2)
+ self.assertTrue('get-foo' in response.context)
+ self.assertEqual(response.context['get-foo'], 'whiz')
+ self.assertEqual(response.context['request-foo'], 'whiz')
+ self.assertEqual(response.context['data'], 'bacon')
+
+ try:
+ response.context['does-not-exist']
+ self.fail('Should not be able to retrieve non-existent key')
+ except KeyError as e:
+ self.assertEqual(e.args[0], 'does-not-exist')
+
+ def test_15368(self):
+ # Need to insert a context processor that assumes certain things about
+ # the request instance. This triggers a bug caused by some ways of
+ # copying RequestContext.
+ try:
+ django.template.context._standard_context_processors = (lambda request: {'path': request.special_path},)
+ response = self.client.get("/test_client_regress/request_context_view/")
+ self.assertContains(response, 'Path: /test_client_regress/request_context_view/')
+ finally:
+ django.template.context._standard_context_processors = None
+
+
+@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
+class SessionTests(TestCase):
+ fixtures = ['testdata.json']
+
+ def test_session(self):
+ "The session isn't lost if a user logs in"
+ # The session doesn't exist to start.
+ response = self.client.get('/test_client_regress/check_session/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'NO')
+
+ # This request sets a session variable.
+ response = self.client.get('/test_client_regress/set_session/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'set_session')
+
+ # Check that the session has been modified
+ response = self.client.get('/test_client_regress/check_session/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'YES')
+
+ # Log in
+ login = self.client.login(username='testclient',password='password')
+ self.assertTrue(login, 'Could not log in')
+
+ # Session should still contain the modified value
+ response = self.client.get('/test_client_regress/check_session/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'YES')
+
+ def test_logout(self):
+ """Logout should work whether the user is logged in or not (#9978)."""
+ self.client.logout()
+ login = self.client.login(username='testclient',password='password')
+ self.assertTrue(login, 'Could not log in')
+ self.client.logout()
+ self.client.logout()
+
+class RequestMethodTests(TestCase):
+ def test_get(self):
+ "Request a view via request method GET"
+ response = self.client.get('/test_client_regress/request_methods/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'request method: GET')
+
+ def test_post(self):
+ "Request a view via request method POST"
+ response = self.client.post('/test_client_regress/request_methods/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'request method: POST')
+
+ def test_head(self):
+ "Request a view via request method HEAD"
+ response = self.client.head('/test_client_regress/request_methods/')
+ self.assertEqual(response.status_code, 200)
+ # A HEAD request doesn't return any content.
+ self.assertNotEqual(response.content, b'request method: HEAD')
+ self.assertEqual(response.content, b'')
+
+ def test_options(self):
+ "Request a view via request method OPTIONS"
+ response = self.client.options('/test_client_regress/request_methods/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'request method: OPTIONS')
+
+ def test_put(self):
+ "Request a view via request method PUT"
+ response = self.client.put('/test_client_regress/request_methods/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'request method: PUT')
+
+ def test_delete(self):
+ "Request a view via request method DELETE"
+ response = self.client.delete('/test_client_regress/request_methods/')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'request method: DELETE')
+
+class RequestMethodStringDataTests(TestCase):
+ def test_post(self):
+ "Request a view with string data via request method POST"
+ # Regression test for #11371
+ data = u'{"test": "json"}'
+ response = self.client.post('/test_client_regress/request_methods/', data=data, content_type='application/json')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'request method: POST')
+
+ def test_put(self):
+ "Request a view with string data via request method PUT"
+ # Regression test for #11371
+ data = u'{"test": "json"}'
+ response = self.client.put('/test_client_regress/request_methods/', data=data, content_type='application/json')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.content, b'request method: PUT')
+
+class QueryStringTests(TestCase):
+ def test_get_like_requests(self):
+ # See: https://code.djangoproject.com/ticket/10571.
+ for method_name in ('get', 'head'):
+ # A GET-like request can pass a query string as data
+ method = getattr(self.client, method_name)
+ response = method("/test_client_regress/request_data/", data={'foo':'whiz'})
+ self.assertEqual(response.context['get-foo'], 'whiz')
+ self.assertEqual(response.context['request-foo'], 'whiz')
+
+ # A GET-like request can pass a query string as part of the URL
+ response = method("/test_client_regress/request_data/?foo=whiz")
+ self.assertEqual(response.context['get-foo'], 'whiz')
+ self.assertEqual(response.context['request-foo'], 'whiz')
+
+ # Data provided in the URL to a GET-like request is overridden by actual form data
+ response = method("/test_client_regress/request_data/?foo=whiz", data={'foo':'bang'})
+ self.assertEqual(response.context['get-foo'], 'bang')
+ self.assertEqual(response.context['request-foo'], 'bang')
+
+ response = method("/test_client_regress/request_data/?foo=whiz", data={'bar':'bang'})
+ self.assertEqual(response.context['get-foo'], None)
+ self.assertEqual(response.context['get-bar'], 'bang')
+ self.assertEqual(response.context['request-foo'], None)
+ self.assertEqual(response.context['request-bar'], 'bang')
+
+ def test_post_like_requests(self):
+ # A POST-like request can pass a query string as data
+ response = self.client.post("/test_client_regress/request_data/", data={'foo':'whiz'})
+ self.assertEqual(response.context['get-foo'], None)
+ self.assertEqual(response.context['post-foo'], 'whiz')
+
+ # A POST-like request can pass a query string as part of the URL
+ response = self.client.post("/test_client_regress/request_data/?foo=whiz")
+ self.assertEqual(response.context['get-foo'], 'whiz')
+ self.assertEqual(response.context['post-foo'], None)
+ self.assertEqual(response.context['request-foo'], 'whiz')
+
+ # POST data provided in the URL augments actual form data
+ response = self.client.post("/test_client_regress/request_data/?foo=whiz", data={'foo':'bang'})
+ self.assertEqual(response.context['get-foo'], 'whiz')
+ self.assertEqual(response.context['post-foo'], 'bang')
+ self.assertEqual(response.context['request-foo'], 'bang')
+
+ response = self.client.post("/test_client_regress/request_data/?foo=whiz", data={'bar':'bang'})
+ self.assertEqual(response.context['get-foo'], 'whiz')
+ self.assertEqual(response.context['get-bar'], None)
+ self.assertEqual(response.context['post-foo'], None)
+ self.assertEqual(response.context['post-bar'], 'bang')
+ self.assertEqual(response.context['request-foo'], 'whiz')
+ self.assertEqual(response.context['request-bar'], 'bang')
+
+class UnicodePayloadTests(TestCase):
+ def test_simple_unicode_payload(self):
+ "A simple ASCII-only unicode JSON document can be POSTed"
+ # Regression test for #10571
+ json = u'{"english": "mountain pass"}'
+ response = self.client.post("/test_client_regress/parse_unicode_json/", json,
+ content_type="application/json")
+ self.assertEqual(response.content, json)
+
+ def test_unicode_payload_utf8(self):
+ "A non-ASCII unicode data encoded as UTF-8 can be POSTed"
+ # Regression test for #10571
+ json = u'{"dog": "собака"}'
+ response = self.client.post("/test_client_regress/parse_unicode_json/", json,
+ content_type="application/json; charset=utf-8")
+ self.assertEqual(response.content, json.encode('utf-8'))
+
+ def test_unicode_payload_utf16(self):
+ "A non-ASCII unicode data encoded as UTF-16 can be POSTed"
+ # Regression test for #10571
+ json = u'{"dog": "собака"}'
+ response = self.client.post("/test_client_regress/parse_unicode_json/", json,
+ content_type="application/json; charset=utf-16")
+ self.assertEqual(response.content, json.encode('utf-16'))
+
+ def test_unicode_payload_non_utf(self):
+ "A non-ASCII unicode data as a non-UTF based encoding can be POSTed"
+ #Regression test for #10571
+ json = u'{"dog": "собака"}'
+ response = self.client.post("/test_client_regress/parse_unicode_json/", json,
+ content_type="application/json; charset=koi8-r")
+ self.assertEqual(response.content, json.encode('koi8-r'))
+
+class DummyFile(object):
+ def __init__(self, filename):
+ self.name = filename
+ def read(self):
+ return 'TEST_FILE_CONTENT'
+
+class UploadedFileEncodingTest(TestCase):
+ def test_file_encoding(self):
+ encoded_file = encode_file('TEST_BOUNDARY', 'TEST_KEY', DummyFile('test_name.bin'))
+ self.assertEqual(b'--TEST_BOUNDARY', encoded_file[0])
+ self.assertEqual(b'Content-Disposition: form-data; name="TEST_KEY"; filename="test_name.bin"', encoded_file[1])
+ self.assertEqual(b'TEST_FILE_CONTENT', encoded_file[-1])
+
+ def test_guesses_content_type_on_file_encoding(self):
+ self.assertEqual(b'Content-Type: application/octet-stream',
+ encode_file('IGNORE', 'IGNORE', DummyFile("file.bin"))[2])
+ self.assertEqual(b'Content-Type: text/plain',
+ encode_file('IGNORE', 'IGNORE', DummyFile("file.txt"))[2])
+ self.assertIn(encode_file('IGNORE', 'IGNORE', DummyFile("file.zip"))[2], (
+ b'Content-Type: application/x-compress',
+ b'Content-Type: application/x-zip',
+ b'Content-Type: application/x-zip-compressed',
+ b'Content-Type: application/zip',))
+ self.assertEqual(b'Content-Type: application/octet-stream',
+ encode_file('IGNORE', 'IGNORE', DummyFile("file.unknown"))[2])
+
+class RequestHeadersTest(TestCase):
+ def test_client_headers(self):
+ "A test client can receive custom headers"
+ response = self.client.get("/test_client_regress/check_headers/", HTTP_X_ARG_CHECK='Testing 123')
+ self.assertEqual(response.content, b"HTTP_X_ARG_CHECK: Testing 123")
+ self.assertEqual(response.status_code, 200)
+
+ def test_client_headers_redirect(self):
+ "Test client headers are preserved through redirects"
+ response = self.client.get("/test_client_regress/check_headers_redirect/", follow=True, HTTP_X_ARG_CHECK='Testing 123')
+ self.assertEqual(response.content, b"HTTP_X_ARG_CHECK: Testing 123")
+ self.assertRedirects(response, '/test_client_regress/check_headers/',
+ status_code=301, target_status_code=200)
+
+
+class ReadLimitedStreamTest(TestCase):
+ """
+ Tests that ensure that HttpRequest.body, HttpRequest.read() and
+ HttpRequest.read(BUFFER) have proper LimitedStream behavior.
+
+ Refs #14753, #15785
+ """
+
+ def test_body_from_empty_request(self):
+ """HttpRequest.body on a test client GET request should return
+ the empty string."""
+ self.assertEqual(self.client.get("/test_client_regress/body/").content, b'')
+
+ def test_read_from_empty_request(self):
+ """HttpRequest.read() on a test client GET request should return the
+ empty string."""
+ self.assertEqual(self.client.get("/test_client_regress/read_all/").content, b'')
+
+ def test_read_numbytes_from_empty_request(self):
+ """HttpRequest.read(LARGE_BUFFER) on a test client GET request should
+ return the empty string."""
+ self.assertEqual(self.client.get("/test_client_regress/read_buffer/").content, b'')
+
+ def test_read_from_nonempty_request(self):
+ """HttpRequest.read() on a test client PUT request with some payload
+ should return that payload."""
+ payload = b'foobar'
+ self.assertEqual(self.client.put("/test_client_regress/read_all/",
+ data=payload,
+ content_type='text/plain').content, payload)
+
+ def test_read_numbytes_from_nonempty_request(self):
+ """HttpRequest.read(LARGE_BUFFER) on a test client PUT request with
+ some payload should return that payload."""
+ payload = b'foobar'
+ self.assertEqual(self.client.put("/test_client_regress/read_buffer/",
+ data=payload,
+ content_type='text/plain').content, payload)
+
+
+class RequestFactoryStateTest(TestCase):
+ """Regression tests for #15929."""
+ # These tests are checking that certain middleware don't change certain
+ # global state. Alternatively, from the point of view of a test, they are
+ # ensuring test isolation behavior. So, unusually, it doesn't make sense to
+ # run the tests individually, and if any are failing it is confusing to run
+ # them with any other set of tests.
+
+ def common_test_that_should_always_pass(self):
+ request = RequestFactory().get('/')
+ request.session = {}
+ self.assertFalse(hasattr(request, 'user'))
+
+ def test_request(self):
+ self.common_test_that_should_always_pass()
+
+ def test_request_after_client(self):
+ # apart from the next line the three tests are identical
+ self.client.get('/')
+ self.common_test_that_should_always_pass()
+
+ def test_request_after_client_2(self):
+ # This test is executed after the previous one
+ self.common_test_that_should_always_pass()
+
+
+class RequestFactoryEnvironmentTests(TestCase):
+ """
+ Regression tests for #8551 and #17067: ensure that environment variables
+ are set correctly in RequestFactory.
+ """
+
+ def test_should_set_correct_env_variables(self):
+ request = RequestFactory().get('/path/')
+
+ self.assertEqual(request.META.get('REMOTE_ADDR'), '127.0.0.1')
+ self.assertEqual(request.META.get('SERVER_NAME'), 'testserver')
+ self.assertEqual(request.META.get('SERVER_PORT'), '80')
+ self.assertEqual(request.META.get('SERVER_PROTOCOL'), 'HTTP/1.1')
+ self.assertEqual(request.META.get('SCRIPT_NAME') +
+ request.META.get('PATH_INFO'), '/path/')
diff --git a/tests/regressiontests/test_client_regress/views.py b/tests/regressiontests/test_client_regress/views.py
index ab625a90dc..3a934ea047 100644
--- a/tests/regressiontests/test_client_regress/views.py
+++ b/tests/regressiontests/test_client_regress/views.py
@@ -5,7 +5,6 @@ from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseRedirect
from django.core.exceptions import SuspiciousOperation
from django.shortcuts import render_to_response
-from django.utils.encoding import smart_str
from django.core.serializers.json import DjangoJSONEncoder
from django.test.client import CONTENT_TYPE_RE
from django.template import RequestContext
@@ -84,8 +83,8 @@ def return_json_file(request):
obj_json = json.dumps(obj_dict, encoding=charset,
cls=DjangoJSONEncoder,
ensure_ascii=False)
- response = HttpResponse(smart_str(obj_json, encoding=charset), status=200,
- mimetype='application/json; charset=' + charset)
+ response = HttpResponse(obj_json.encode(charset), status=200,
+ mimetype='application/json; charset=%s' % charset)
response['Content-Disposition'] = 'attachment; filename=testfile.json'
return response
diff --git a/tests/regressiontests/test_runner/tests.py b/tests/regressiontests/test_runner/tests.py
index 3a8a4efe3d..05f99105aa 100644
--- a/tests/regressiontests/test_runner/tests.py
+++ b/tests/regressiontests/test_runner/tests.py
@@ -8,8 +8,7 @@ from optparse import make_option
from django.core.exceptions import ImproperlyConfigured
from django.core.management import call_command
from django import db
-from django.db import connection
-from django.test import simple, TransactionTestCase
+from django.test import simple, TransactionTestCase, skipUnlessDBFeature
from django.test.simple import DjangoTestSuiteRunner, get_tests
from django.test.testcases import connections_support_transactions
from django.utils import unittest
@@ -291,16 +290,12 @@ class AutoIncrementResetTest(TransactionTestCase):
and check that both times they get "1" as their PK value. That is, we test
that AutoField values start from 1 for each transactional test case.
"""
- @unittest.skipIf(connection.vendor == 'oracle',
- "Oracle's auto-increment fields are not reset between "
- "tests")
+ @skipUnlessDBFeature('supports_sequence_reset')
def test_autoincrement_reset1(self):
p = Person.objects.create(first_name='Jack', last_name='Smith')
self.assertEqual(p.pk, 1)
- @unittest.skipIf(connection.vendor == 'oracle',
- "Oracle's auto-increment fields are not reset between "
- "tests")
+ @skipUnlessDBFeature('supports_sequence_reset')
def test_autoincrement_reset2(self):
p = Person.objects.create(first_name='Jack', last_name='Smith')
self.assertEqual(p.pk, 1)
diff --git a/tests/regressiontests/views/__init__.py b/tests/regressiontests/views/__init__.py
index fa3db00113..1e12679af2 100644
--- a/tests/regressiontests/views/__init__.py
+++ b/tests/regressiontests/views/__init__.py
@@ -3,8 +3,8 @@
class BrokenException(Exception):
pass
-except_args = ('Broken!', # plain exception with ASCII text
+except_args = (b'Broken!', # plain exception with ASCII text
u'¡Broken!', # non-ASCII unicode data
- '¡Broken!', # non-ASCII, utf-8 encoded bytestring
- '\xa1Broken!', ) # non-ASCII, latin1 bytestring
+ u'¡Broken!'.encode('utf-8'), # non-ASCII, utf-8 encoded bytestring
+ b'\xa1Broken!', ) # non-ASCII, latin1 bytestring
diff --git a/tests/regressiontests/views/tests/debug.py b/tests/regressiontests/views/tests/debug.py
index c8358d334f..e8a7d49e79 100644
--- a/tests/regressiontests/views/tests/debug.py
+++ b/tests/regressiontests/views/tests/debug.py
@@ -10,13 +10,12 @@ from django.test import TestCase, RequestFactory
from django.test.utils import (setup_test_template_loader,
restore_template_loaders)
from django.core.urlresolvers import reverse
-from django.template import TemplateSyntaxError
from django.views.debug import ExceptionReporter
from django.core import mail
from .. import BrokenException, except_args
from ..views import (sensitive_view, non_sensitive_view, paranoid_view,
- custom_exception_reporter_filter_view)
+ custom_exception_reporter_filter_view, sensitive_method_view)
class DebugViewTests(TestCase):
@@ -238,7 +237,8 @@ class ExceptionReportTestMixin(object):
'hash-brown-key': 'hash-brown-value',
'bacon-key': 'bacon-value',}
- def verify_unsafe_response(self, view, check_for_vars=True):
+ def verify_unsafe_response(self, view, check_for_vars=True,
+ check_for_POST_params=True):
"""
Asserts that potentially sensitive info are displayed in the response.
"""
@@ -250,13 +250,14 @@ class ExceptionReportTestMixin(object):
self.assertContains(response, 'scrambled', status_code=500)
self.assertContains(response, 'sauce', status_code=500)
self.assertContains(response, 'worcestershire', status_code=500)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters are shown.
+ self.assertContains(response, k, status_code=500)
+ self.assertContains(response, v, status_code=500)
- for k, v in self.breakfast_data.items():
- # All POST parameters are shown.
- self.assertContains(response, k, status_code=500)
- self.assertContains(response, v, status_code=500)
-
- def verify_safe_response(self, view, check_for_vars=True):
+ def verify_safe_response(self, view, check_for_vars=True,
+ check_for_POST_params=True):
"""
Asserts that certain sensitive info are not displayed in the response.
"""
@@ -269,18 +270,19 @@ class ExceptionReportTestMixin(object):
# Sensitive variable's name is shown but not its value.
self.assertContains(response, 'sauce', status_code=500)
self.assertNotContains(response, 'worcestershire', status_code=500)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters' names are shown.
+ self.assertContains(response, k, status_code=500)
+ # Non-sensitive POST parameters' values are shown.
+ self.assertContains(response, 'baked-beans-value', status_code=500)
+ self.assertContains(response, 'hash-brown-value', status_code=500)
+ # Sensitive POST parameters' values are not shown.
+ self.assertNotContains(response, 'sausage-value', status_code=500)
+ self.assertNotContains(response, 'bacon-value', status_code=500)
- for k, v in self.breakfast_data.items():
- # All POST parameters' names are shown.
- self.assertContains(response, k, status_code=500)
- # Non-sensitive POST parameters' values are shown.
- self.assertContains(response, 'baked-beans-value', status_code=500)
- self.assertContains(response, 'hash-brown-value', status_code=500)
- # Sensitive POST parameters' values are not shown.
- self.assertNotContains(response, 'sausage-value', status_code=500)
- self.assertNotContains(response, 'bacon-value', status_code=500)
-
- def verify_paranoid_response(self, view, check_for_vars=True):
+ def verify_paranoid_response(self, view, check_for_vars=True,
+ check_for_POST_params=True):
"""
Asserts that no variables or POST parameters are displayed in the response.
"""
@@ -292,14 +294,14 @@ class ExceptionReportTestMixin(object):
self.assertNotContains(response, 'scrambled', status_code=500)
self.assertContains(response, 'sauce', status_code=500)
self.assertNotContains(response, 'worcestershire', status_code=500)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters' names are shown.
+ self.assertContains(response, k, status_code=500)
+ # No POST parameters' values are shown.
+ self.assertNotContains(response, v, status_code=500)
- for k, v in self.breakfast_data.items():
- # All POST parameters' names are shown.
- self.assertContains(response, k, status_code=500)
- # No POST parameters' values are shown.
- self.assertNotContains(response, v, status_code=500)
-
- def verify_unsafe_email(self, view):
+ def verify_unsafe_email(self, view, check_for_POST_params=True):
"""
Asserts that potentially sensitive info are displayed in the email report.
"""
@@ -314,12 +316,13 @@ class ExceptionReportTestMixin(object):
self.assertNotIn('scrambled', email.body)
self.assertNotIn('sauce', email.body)
self.assertNotIn('worcestershire', email.body)
- for k, v in self.breakfast_data.items():
- # All POST parameters are shown.
- self.assertIn(k, email.body)
- self.assertIn(v, email.body)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters are shown.
+ self.assertIn(k, email.body)
+ self.assertIn(v, email.body)
- def verify_safe_email(self, view):
+ def verify_safe_email(self, view, check_for_POST_params=True):
"""
Asserts that certain sensitive info are not displayed in the email report.
"""
@@ -334,15 +337,16 @@ class ExceptionReportTestMixin(object):
self.assertNotIn('scrambled', email.body)
self.assertNotIn('sauce', email.body)
self.assertNotIn('worcestershire', email.body)
- for k, v in self.breakfast_data.items():
- # All POST parameters' names are shown.
- self.assertIn(k, email.body)
- # Non-sensitive POST parameters' values are shown.
- self.assertIn('baked-beans-value', email.body)
- self.assertIn('hash-brown-value', email.body)
- # Sensitive POST parameters' values are not shown.
- self.assertNotIn('sausage-value', email.body)
- self.assertNotIn('bacon-value', email.body)
+ if check_for_POST_params:
+ for k, v in self.breakfast_data.items():
+ # All POST parameters' names are shown.
+ self.assertIn(k, email.body)
+ # Non-sensitive POST parameters' values are shown.
+ self.assertIn('baked-beans-value', email.body)
+ self.assertIn('hash-brown-value', email.body)
+ # Sensitive POST parameters' values are not shown.
+ self.assertNotIn('sausage-value', email.body)
+ self.assertNotIn('bacon-value', email.body)
def verify_paranoid_email(self, view):
"""
@@ -425,6 +429,24 @@ class ExceptionReporterFilterTests(TestCase, ExceptionReportTestMixin):
self.verify_unsafe_response(custom_exception_reporter_filter_view)
self.verify_unsafe_email(custom_exception_reporter_filter_view)
+ def test_sensitive_method(self):
+ """
+ Ensure that the sensitive_variables decorator works with object
+ methods.
+ Refs #18379.
+ """
+ with self.settings(DEBUG=True):
+ self.verify_unsafe_response(sensitive_method_view,
+ check_for_POST_params=False)
+ self.verify_unsafe_email(sensitive_method_view,
+ check_for_POST_params=False)
+
+ with self.settings(DEBUG=False):
+ self.verify_safe_response(sensitive_method_view,
+ check_for_POST_params=False)
+ self.verify_safe_email(sensitive_method_view,
+ check_for_POST_params=False)
+
class AjaxResponseExceptionReporterFilter(TestCase, ExceptionReportTestMixin):
"""
diff --git a/tests/regressiontests/views/tests/static.py b/tests/regressiontests/views/tests/static.py
index 6cabf6453c..9d87ade137 100644
--- a/tests/regressiontests/views/tests/static.py
+++ b/tests/regressiontests/views/tests/static.py
@@ -29,7 +29,7 @@ class StaticTests(TestCase):
for filename in media_files:
response = self.client.get('/views/%s/%s' % (self.prefix, filename))
file_path = path.join(media_dir, filename)
- with open(file_path) as fp:
+ with open(file_path, 'rb') as fp:
self.assertEqual(fp.read(), response.content)
self.assertEqual(len(response.content), int(response['Content-Length']))
self.assertEqual(mimetypes.guess_type(file_path)[1], response.get('Content-Encoding', None))
@@ -41,14 +41,14 @@ class StaticTests(TestCase):
def test_copes_with_empty_path_component(self):
file_name = 'file.txt'
response = self.client.get('/views/%s//%s' % (self.prefix, file_name))
- with open(path.join(media_dir, file_name)) as fp:
+ with open(path.join(media_dir, file_name), 'rb') as fp:
self.assertEqual(fp.read(), response.content)
def test_is_modified_since(self):
file_name = 'file.txt'
response = self.client.get('/views/%s/%s' % (self.prefix, file_name),
HTTP_IF_MODIFIED_SINCE='Thu, 1 Jan 1970 00:00:00 GMT')
- with open(path.join(media_dir, file_name)) as fp:
+ with open(path.join(media_dir, file_name), 'rb') as fp:
self.assertEqual(fp.read(), response.content)
def test_not_modified_since(self):
@@ -71,7 +71,7 @@ class StaticTests(TestCase):
invalid_date = 'Mon, 28 May 999999999999 28:25:26 GMT'
response = self.client.get('/views/%s/%s' % (self.prefix, file_name),
HTTP_IF_MODIFIED_SINCE=invalid_date)
- with open(path.join(media_dir, file_name)) as fp:
+ with open(path.join(media_dir, file_name), 'rb') as fp:
self.assertEqual(fp.read(), response.content)
self.assertEqual(len(response.content),
int(response['Content-Length']))
@@ -86,7 +86,7 @@ class StaticTests(TestCase):
invalid_date = ': 1291108438, Wed, 20 Oct 2010 14:05:00 GMT'
response = self.client.get('/views/%s/%s' % (self.prefix, file_name),
HTTP_IF_MODIFIED_SINCE=invalid_date)
- with open(path.join(media_dir, file_name)) as fp:
+ with open(path.join(media_dir, file_name), 'rb') as fp:
self.assertEqual(fp.read(), response.content)
self.assertEqual(len(response.content),
int(response['Content-Length']))
diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
index 8e530cd2d8..2836d1bdde 100644
--- a/tests/regressiontests/views/views.py
+++ b/tests/regressiontests/views/views.py
@@ -2,7 +2,6 @@ from __future__ import absolute_import
import sys
-from django import forms
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import get_resolver
from django.http import HttpResponse, HttpResponseRedirect
@@ -14,7 +13,7 @@ from django.views.decorators.debug import (sensitive_post_parameters,
from django.utils.log import getLogger
from . import BrokenException, except_args
-from .models import Article
+
def index_page(request):
@@ -209,3 +208,23 @@ def custom_exception_reporter_filter_view(request):
exc_info = sys.exc_info()
send_log(request, exc_info)
return technical_500_response(request, *exc_info)
+
+
+class Klass(object):
+
+ @sensitive_variables('sauce')
+ def method(self, request):
+ # Do not just use plain strings for the variables' values in the code
+ # so that the tests don't return false positives when the function's
+ # source is displayed in the exception report.
+ cooked_eggs = ''.join(['s', 'c', 'r', 'a', 'm', 'b', 'l', 'e', 'd'])
+ sauce = ''.join(['w', 'o', 'r', 'c', 'e', 's', 't', 'e', 'r', 's', 'h', 'i', 'r', 'e'])
+ try:
+ raise Exception
+ except Exception:
+ exc_info = sys.exc_info()
+ send_log(request, exc_info)
+ return technical_500_response(request, *exc_info)
+
+def sensitive_method_view(request):
+ return Klass().method(request) \ No newline at end of file