summaryrefslogtreecommitdiff
path: root/tests/regressiontests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/regressiontests')
-rw-r--r--tests/regressiontests/backends/models.py19
-rw-r--r--tests/regressiontests/backends/tests.py53
-rw-r--r--tests/regressiontests/httpwrappers/tests.py658
-rw-r--r--tests/regressiontests/m2m_through_regress/models.py158
-rw-r--r--tests/regressiontests/m2m_through_regress/tests.py126
-rw-r--r--tests/regressiontests/multiple_database/tests.py31
-rw-r--r--tests/regressiontests/serializers_regress/tests.py71
-rw-r--r--tests/regressiontests/utils/timesince.py14
8 files changed, 445 insertions, 685 deletions
diff --git a/tests/regressiontests/backends/models.py b/tests/regressiontests/backends/models.py
index 423bead1ad..e3137f2710 100644
--- a/tests/regressiontests/backends/models.py
+++ b/tests/regressiontests/backends/models.py
@@ -1,5 +1,7 @@
+from django.conf import settings
from django.db import models
-from django.db import connection
+from django.db import connection, DEFAULT_DB_ALIAS
+
class Square(models.Model):
root = models.IntegerField()
@@ -8,6 +10,7 @@ class Square(models.Model):
def __unicode__(self):
return "%s ** 2 == %s" % (self.root, self.square)
+
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
@@ -15,11 +18,25 @@ class Person(models.Model):
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
+
class SchoolClass(models.Model):
year = models.PositiveIntegerField()
day = models.CharField(max_length=9, blank=True)
last_updated = models.DateTimeField()
+# Unfortunately, the following model breaks MySQL hard.
+# Until #13711 is fixed, this test can't be run under MySQL.
+if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
+ class VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ(models.Model):
+ class Meta:
+ # We need to use a short actual table name or
+ # we hit issue #8548 which we're not testing!
+ verbose_name = 'model_with_long_table_name'
+ primary_key_is_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.AutoField(primary_key=True)
+ charfield_is_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.CharField(max_length=100)
+ m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.ManyToManyField(Person,blank=True)
+
+
qn = connection.ops.quote_name
__test__ = {'API_TESTS': """
diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
index 6a26a608eb..ee3ccdc72f 100644
--- a/tests/regressiontests/backends/tests.py
+++ b/tests/regressiontests/backends/tests.py
@@ -1,13 +1,17 @@
# -*- coding: utf-8 -*-
# Unit and doctests for specific database backends.
import datetime
-import models
import unittest
+
+from django.conf import settings
+from django.core import management
+from django.core.management.color import no_style
from django.db import backend, connection, DEFAULT_DB_ALIAS
from django.db.backends.signals import connection_created
-from django.conf import settings
from django.test import TestCase
+from regressiontests.backends import models
+
class Callproc(unittest.TestCase):
def test_dbms_session(self):
@@ -76,6 +80,7 @@ class DateQuotingTest(TestCase):
classes = models.SchoolClass.objects.filter(last_updated__day=20)
self.assertEqual(len(classes), 1)
+
class ParameterHandlingTest(TestCase):
def test_bad_parameter_count(self):
"An executemany call with too many/not enough parameters will raise an exception (Refs #12612)"
@@ -88,6 +93,50 @@ class ParameterHandlingTest(TestCase):
self.assertRaises(Exception, cursor.executemany, query, [(1,2,3),])
self.assertRaises(Exception, cursor.executemany, query, [(1,),])
+# Unfortunately, the following tests would be a good test to run on all
+# backends, but it breaks MySQL hard. Until #13711 is fixed, it can't be run
+# everywhere (although it would be an effective test of #13711).
+if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
+ class LongNameTest(TestCase):
+ """Long primary keys and model names can result in a sequence name
+ that exceeds the database limits, which will result in truncation
+ on certain databases (e.g., Postgres). The backend needs to use
+ the correct sequence name in last_insert_id and other places, so
+ check it is. Refs #8901.
+ """
+
+ def test_sequence_name_length_limits_create(self):
+ """Test creation of model with long name and long pk name doesn't error. Ref #8901"""
+ models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.objects.create()
+
+ def test_sequence_name_length_limits_m2m(self):
+ """Test an m2m save of a model with a long name and a long m2m field name doesn't error as on Django >=1.2 this now uses object saves. Ref #8901"""
+ obj = models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.objects.create()
+ rel_obj = models.Person.objects.create(first_name='Django', last_name='Reinhardt')
+ obj.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.add(rel_obj)
+
+ def test_sequence_name_length_limits_flush(self):
+ """Test that sequence resetting as part of a flush with model with long name and long pk name doesn't error. Ref #8901"""
+ # A full flush is expensive to the full test, so we dig into the
+ # internals to generate the likely offending SQL and run it manually
+
+ # Some convenience aliases
+ VLM = models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+ VLM_m2m = VLM.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.through
+ tables = [
+ VLM._meta.db_table,
+ VLM_m2m._meta.db_table,
+ ]
+ sequences = [
+ {
+ 'column': VLM._meta.pk.column,
+ 'table': VLM._meta.db_table
+ },
+ ]
+ cursor = connection.cursor()
+ for statement in connection.ops.sql_flush(no_style(), tables, sequences):
+ cursor.execute(statement)
+
def connection_created_test(sender, **kwargs):
print 'connection_created signal'
diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py
index 132472ca37..23aa526a37 100644
--- a/tests/regressiontests/httpwrappers/tests.py
+++ b/tests/regressiontests/httpwrappers/tests.py
@@ -1,476 +1,228 @@
-"""
-###################
-# Empty QueryDict #
-###################
+import copy
+import pickle
+import unittest
+from django.http import QueryDict, HttpResponse, CompatCookie, BadHeaderError
->>> q = QueryDict('')
+class QueryDictTests(unittest.TestCase):
+ def test_missing_key(self):
+ q = QueryDict('')
+ self.assertRaises(KeyError, q.__getitem__, 'foo')
->>> q['foo']
-Traceback (most recent call last):
-...
-MultiValueDictKeyError: "Key 'foo' not found in <QueryDict: {}>"
+ def test_immutability(self):
+ q = QueryDict('')
+ self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar')
+ self.assertRaises(AttributeError, q.setlist, 'foo', ['bar'])
+ self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar'])
+ self.assertRaises(AttributeError, q.update, {'foo': 'bar'})
+ self.assertRaises(AttributeError, q.pop, 'foo')
+ self.assertRaises(AttributeError, q.popitem)
+ self.assertRaises(AttributeError, q.clear)
+
+ def test_immutable_get_with_default(self):
+ q = QueryDict('')
+ self.assertEqual(q.get('foo', 'default'), 'default')
->>> q['something'] = 'bar'
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
+ def test_immutable_basic_operations(self):
+ q = QueryDict('')
+ self.assertEqual(q.getlist('foo'), [])
+ self.assertEqual(q.has_key('foo'), False)
+ self.assertEqual('foo' in q, False)
+ self.assertEqual(q.items(), [])
+ self.assertEqual(q.lists(), [])
+ self.assertEqual(q.items(), [])
+ self.assertEqual(q.keys(), [])
+ self.assertEqual(q.values(), [])
+ self.assertEqual(len(q), 0)
+ self.assertEqual(q.urlencode(), '')
+
+ def test_single_key_value(self):
+ """Test QueryDict with one key/value pair"""
->>> q.get('foo', 'default')
-'default'
+ q = QueryDict('foo=bar')
+ self.assertEqual(q['foo'], 'bar')
+ self.assertRaises(KeyError, q.__getitem__, 'bar')
+ self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar')
->>> q.getlist('foo')
-[]
+ self.assertEqual(q.get('foo', 'default'), 'bar')
+ self.assertEqual(q.get('bar', 'default'), 'default')
+ self.assertEqual(q.getlist('foo'), ['bar'])
+ self.assertEqual(q.getlist('bar'), [])
+
+ self.assertRaises(AttributeError, q.setlist, 'foo', ['bar'])
+ self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar'])
->>> q.setlist('foo', ['bar', 'baz'])
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
+ self.failUnless(q.has_key('foo'))
+ self.failUnless('foo' in q)
+ self.failIf(q.has_key('bar'))
+ self.failIf('bar' in q)
->>> q.appendlist('foo', ['bar'])
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
+ self.assertEqual(q.items(), [(u'foo', u'bar')])
+ self.assertEqual(q.lists(), [(u'foo', [u'bar'])])
+ self.assertEqual(q.keys(), ['foo'])
+ self.assertEqual(q.values(), ['bar'])
+ self.assertEqual(len(q), 1)
->>> q.has_key('foo')
-False
+ self.assertRaises(AttributeError, q.update, {'foo': 'bar'})
+ self.assertRaises(AttributeError, q.pop, 'foo')
+ self.assertRaises(AttributeError, q.popitem)
+ self.assertRaises(AttributeError, q.clear)
+ self.assertRaises(AttributeError, q.setdefault, 'foo', 'bar')
+
+ self.assertEqual(q.urlencode(), 'foo=bar')
+
+ def test_mutable_copy(self):
+ """A copy of a QueryDict is mutable."""
+ q = QueryDict('').copy()
+ self.assertRaises(KeyError, q.__getitem__, "foo")
+ q['name'] = 'john'
+ self.assertEqual(q['name'], 'john')
+
+ def test_mutable_delete(self):
+ q = QueryDict('').copy()
+ q['name'] = 'john'
+ del q['name']
+ self.failIf('name' in q)
->>> 'foo' in q
-False
+ def test_basic_mutable_operations(self):
+ q = QueryDict('').copy()
+ q['name'] = 'john'
+ self.assertEqual(q.get('foo', 'default'), 'default')
+ self.assertEqual(q.get('name', 'default'), 'john')
+ self.assertEqual(q.getlist('name'), ['john'])
+ self.assertEqual(q.getlist('foo'), [])
->>> q.items()
-[]
+ q.setlist('foo', ['bar', 'baz'])
+ self.assertEqual(q.get('foo', 'default'), 'baz')
+ self.assertEqual(q.getlist('foo'), ['bar', 'baz'])
->>> q.lists()
-[]
+ q.appendlist('foo', 'another')
+ self.assertEqual(q.getlist('foo'), ['bar', 'baz', 'another'])
+ self.assertEqual(q['foo'], 'another')
+ self.failUnless(q.has_key('foo'))
+ self.failUnless('foo' in q)
->>> q.keys()
-[]
+ self.assertEqual(q.items(), [(u'foo', u'another'), (u'name', u'john')])
+ self.assertEqual(q.lists(), [(u'foo', [u'bar', u'baz', u'another']), (u'name', [u'john'])])
+ self.assertEqual(q.keys(), [u'foo', u'name'])
+ self.assertEqual(q.values(), [u'another', u'john'])
+ self.assertEqual(len(q), 2)
->>> q.values()
-[]
+ q.update({'foo': 'hello'})
+ self.assertEqual(q['foo'], 'hello')
+ self.assertEqual(q.get('foo', 'not available'), 'hello')
+ self.assertEqual(q.getlist('foo'), [u'bar', u'baz', u'another', u'hello'])
+ self.assertEqual(q.pop('foo'), [u'bar', u'baz', u'another', u'hello'])
+ self.assertEqual(q.pop('foo', 'not there'), 'not there')
+ self.assertEqual(q.get('foo', 'not there'), 'not there')
+ self.assertEqual(q.setdefault('foo', 'bar'), 'bar')
+ self.assertEqual(q['foo'], 'bar')
+ self.assertEqual(q.getlist('foo'), ['bar'])
+ self.assertEqual(q.urlencode(), 'foo=bar&name=john')
->>> len(q)
-0
+ q.clear()
+ self.assertEqual(len(q), 0)
->>> q.update({'foo': 'bar'})
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
+ def test_multiple_keys(self):
+ """Test QueryDict with two key/value pairs with same keys."""
->>> q.pop('foo')
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
+ q = QueryDict('vote=yes&vote=no')
+
+ self.assertEqual(q['vote'], u'no')
+ self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar')
+
+ self.assertEqual(q.get('vote', 'default'), u'no')
+ self.assertEqual(q.get('foo', 'default'), 'default')
+ self.assertEqual(q.getlist('vote'), [u'yes', u'no'])
+ self.assertEqual(q.getlist('foo'), [])
+
+ self.assertRaises(AttributeError, q.setlist, 'foo', ['bar', 'baz'])
+ self.assertRaises(AttributeError, q.setlist, 'foo', ['bar', 'baz'])
+ self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar'])
->>> q.popitem()
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.clear()
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.setdefault('foo', 'bar')
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.urlencode()
-''
-
-###################################
-# Mutable copy of empty QueryDict #
-###################################
-
->>> q = q.copy()
-
->>> q['foo']
-Traceback (most recent call last):
-...
-MultiValueDictKeyError: "Key 'foo' not found in <QueryDict: {}>"
-
->>> q['name'] = 'john'
-
->>> q['name']
-u'john'
-
->>> del q['name']
->>> 'name' in q
-False
-
->>> q['name'] = 'john'
-
->>> q.get('foo', 'default')
-'default'
-
->>> q.get('name', 'default')
-u'john'
-
->>> q.getlist('name')
-[u'john']
-
->>> q.getlist('foo')
-[]
-
->>> q.setlist('foo', ['bar', 'baz'])
-
->>> q.get('foo', 'default')
-u'baz'
-
->>> q.getlist('foo')
-[u'bar', u'baz']
-
->>> q.appendlist('foo', 'another')
-
->>> q.getlist('foo')
-[u'bar', u'baz', u'another']
-
->>> q['foo']
-u'another'
-
->>> q.has_key('foo')
-True
-
->>> 'foo' in q
-True
-
->>> q.items()
-[(u'foo', u'another'), (u'name', u'john')]
-
->>> q.lists()
-[(u'foo', [u'bar', u'baz', u'another']), (u'name', [u'john'])]
-
->>> q.keys()
-[u'foo', u'name']
-
->>> q.values()
-[u'another', u'john']
-
->>> len(q)
-2
-
->>> q.update({'foo': 'hello'})
-
-# Displays last value
->>> q['foo']
-u'hello'
-
->>> q.get('foo', 'not available')
-u'hello'
-
->>> q.getlist('foo')
-[u'bar', u'baz', u'another', u'hello']
-
->>> q.pop('foo')
-[u'bar', u'baz', u'another', u'hello']
-
->>> q.pop('foo', 'not there')
-'not there'
-
->>> q.get('foo', 'not there')
-'not there'
-
->>> q.setdefault('foo', 'bar')
-u'bar'
-
->>> q['foo']
-u'bar'
-
->>> q.getlist('foo')
-[u'bar']
-
->>> q.urlencode()
-'foo=bar&name=john'
-
->>> q.clear()
-
->>> len(q)
-0
-
-#####################################
-# QueryDict with one key/value pair #
-#####################################
-
->>> q = QueryDict('foo=bar')
-
->>> q['foo']
-u'bar'
-
->>> q['bar']
-Traceback (most recent call last):
-...
-MultiValueDictKeyError: "Key 'bar' not found in <QueryDict: {u'foo': [u'bar']}>"
-
->>> q['something'] = 'bar'
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.get('foo', 'default')
-u'bar'
-
->>> q.get('bar', 'default')
-'default'
-
->>> q.getlist('foo')
-[u'bar']
-
->>> q.getlist('bar')
-[]
-
->>> q.setlist('foo', ['bar', 'baz'])
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.appendlist('foo', ['bar'])
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.has_key('foo')
-True
-
->>> 'foo' in q
-True
-
->>> q.has_key('bar')
-False
-
->>> 'bar' in q
-False
-
->>> q.items()
-[(u'foo', u'bar')]
-
->>> q.lists()
-[(u'foo', [u'bar'])]
-
->>> q.keys()
-[u'foo']
-
->>> q.values()
-[u'bar']
-
->>> len(q)
-1
-
->>> q.update({'foo': 'bar'})
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.pop('foo')
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.popitem()
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.clear()
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.setdefault('foo', 'bar')
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.urlencode()
-'foo=bar'
-
-#####################################################
-# QueryDict with two key/value pairs with same keys #
-#####################################################
-
->>> q = QueryDict('vote=yes&vote=no')
-
->>> q['vote']
-u'no'
-
->>> q['something'] = 'bar'
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.get('vote', 'default')
-u'no'
-
->>> q.get('foo', 'default')
-'default'
-
->>> q.getlist('vote')
-[u'yes', u'no']
-
->>> q.getlist('foo')
-[]
-
->>> q.setlist('foo', ['bar', 'baz'])
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.appendlist('foo', ['bar'])
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.has_key('vote')
-True
-
->>> 'vote' in q
-True
-
->>> q.has_key('foo')
-False
-
->>> 'foo' in q
-False
-
->>> q.items()
-[(u'vote', u'no')]
-
->>> q.lists()
-[(u'vote', [u'yes', u'no'])]
-
->>> q.keys()
-[u'vote']
-
->>> q.values()
-[u'no']
-
->>> len(q)
-1
-
->>> q.update({'foo': 'bar'})
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.pop('foo')
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.popitem()
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.clear()
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.setdefault('foo', 'bar')
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
->>> q.urlencode()
-'vote=yes&vote=no'
-
->>> del q['vote']
-Traceback (most recent call last):
-...
-AttributeError: This QueryDict instance is immutable
-
-# QueryDicts must be able to handle invalid input encoding (in this case, bad
-# UTF-8 encoding).
->>> q = QueryDict('foo=bar&foo=\xff')
-
->>> q['foo']
-u'\ufffd'
-
->>> q.getlist('foo')
-[u'bar', u'\ufffd']
-
-
-########################
-# Pickling a QueryDict #
-########################
->>> import pickle
->>> q = QueryDict('')
->>> q1 = pickle.loads(pickle.dumps(q, 2))
->>> q == q1
-True
->>> q = QueryDict('a=b&c=d')
->>> q1 = pickle.loads(pickle.dumps(q, 2))
->>> q == q1
-True
->>> q = QueryDict('a=b&c=d&a=1')
->>> q1 = pickle.loads(pickle.dumps(q, 2))
->>> q == q1
-True
-
-######################################
-# HttpResponse with Unicode headers #
-######################################
-
->>> r = HttpResponse()
-
-If we insert a unicode value it will be converted to an ascii
-string. This makes sure we comply with the HTTP specifications.
-
->>> r['value'] = u'test value'
->>> isinstance(r['value'], str)
-True
-
-An error is raised When a unicode object with non-ascii is assigned.
-
->>> r['value'] = u't\xebst value' # doctest:+ELLIPSIS
-Traceback (most recent call last):
-...
-UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format
-
-The response also converts unicode keys to strings.
-
->>> r[u'test'] = 'testing key'
->>> l = list(r.items())
->>> l.sort()
->>> l[1]
-('test', 'testing key')
-
-It will also raise errors for keys with non-ascii data.
-
->>> r[u't\xebst'] = 'testing key' # doctest:+ELLIPSIS
-Traceback (most recent call last):
-...
-UnicodeEncodeError: ..., HTTP response headers must be in US-ASCII format
-
-# Bug #10188: Do not allow newlines in headers (CR or LF)
->>> r['test\\rstr'] = 'test'
-Traceback (most recent call last):
-...
-BadHeaderError: Header values can't contain newlines (got 'test\\rstr')
-
->>> r['test\\nstr'] = 'test'
-Traceback (most recent call last):
-...
-BadHeaderError: Header values can't contain newlines (got 'test\\nstr')
+ self.assertEqual(q.has_key('vote'), True)
+ self.assertEqual('vote' in q, True)
+ self.assertEqual(q.has_key('foo'), False)
+ self.assertEqual('foo' in q, False)
+ self.assertEqual(q.items(), [(u'vote', u'no')])
+ self.assertEqual(q.lists(), [(u'vote', [u'yes', u'no'])])
+ self.assertEqual(q.keys(), [u'vote'])
+ self.assertEqual(q.values(), [u'no'])
+ self.assertEqual(len(q), 1)
+
+ self.assertRaises(AttributeError, q.update, {'foo': 'bar'})
+ self.assertRaises(AttributeError, q.pop, 'foo')
+ self.assertRaises(AttributeError, q.popitem)
+ self.assertRaises(AttributeError, q.clear)
+ self.assertRaises(AttributeError, q.setdefault, 'foo', 'bar')
+ self.assertRaises(AttributeError, q.__delitem__, 'vote')
+
+ def test_invalid_input_encoding(self):
+ """
+ QueryDicts must be able to handle invalid input encoding (in this
+ case, bad UTF-8 encoding).
+ """
+ q = QueryDict('foo=bar&foo=\xff')
+ self.assertEqual(q['foo'], u'\ufffd')
+ self.assertEqual(q.getlist('foo'), [u'bar', u'\ufffd'])
+
+ def test_pickle(self):
+ q = QueryDict('')
+ q1 = pickle.loads(pickle.dumps(q, 2))
+ self.assertEqual(q == q1, True)
+ q = QueryDict('a=b&c=d')
+ q1 = pickle.loads(pickle.dumps(q, 2))
+ self.assertEqual(q == q1, True)
+ q = QueryDict('a=b&c=d&a=1')
+ q1 = pickle.loads(pickle.dumps(q, 2))
+ self.assertEqual(q == q1 , True)
-#
-# Regression test for #8278: QueryDict.update(QueryDict)
-#
->>> x = QueryDict("a=1&a=2", mutable=True)
->>> y = QueryDict("a=3&a=4")
->>> x.update(y)
->>> x.getlist('a')
-[u'1', u'2', u'3', u'4']
-"""
+ def test_update_from_querydict(self):
+ """Regression test for #8278: QueryDict.update(QueryDict)"""
+ x = QueryDict("a=1&a=2", mutable=True)
+ y = QueryDict("a=3&a=4")
+ x.update(y)
+ self.assertEqual(x.getlist('a'), [u'1', u'2', u'3', u'4'])
-from django.http import QueryDict, HttpResponse, CompatCookie
-from django.test import TestCase
+ def test_non_default_encoding(self):
+ """#13572 - QueryDict with a non-default encoding"""
+ q = QueryDict('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' )
+ q = q.copy()
+ self.assertEqual(q.encoding , 'rot_13' )
+ self.assertEqual(q.items() , [(u'foo', u'bar')] )
+ self.assertEqual(q.urlencode() , 'sbb=one' )
+ self.assertEqual(copy.copy(q).encoding , 'rot_13' )
+ self.assertEqual(copy.deepcopy(q).encoding , 'rot_13')
+
+class HttpResponseTests(unittest.TestCase):
+ def test_unicode_headers(self):
+ r = HttpResponse()
+ # If we insert a unicode value it will be converted to an ascii
+ r['value'] = u'test value'
+ self.failUnless(isinstance(r['value'], str))
+
+ # An error is raised When a unicode object with non-ascii is assigned.
+ self.assertRaises(UnicodeEncodeError, r.__setitem__, 'value', u't\xebst value')
+
+ # The response also converts unicode keys to strings.)
+ r[u'test'] = 'testing key'
+ l = list(r.items())
+ l.sort()
+ self.assertEqual(l[1], ('test', 'testing key'))
+
+ # It will also raise errors for keys with non-ascii data.
+ self.assertRaises(UnicodeEncodeError, r.__setitem__, u't\xebst key', 'value')
-class Cookies(TestCase):
+ def test_newlines_in_headers(self):
+ # Bug #10188: Do not allow newlines in headers (CR or LF)
+ r = HttpResponse()
+ self.assertRaises(BadHeaderError, r.__setitem__, 'test\rstr', 'test')
+ self.assertRaises(BadHeaderError, r.__setitem__, 'test\nstr', 'test')
+class CookieTests(unittest.TestCase):
def test_encode(self):
"""
Test that we don't output tricky characters in encoded value
@@ -502,7 +254,3 @@ class Cookies(TestCase):
c2 = CompatCookie()
c2.load(c.output())
self.assertEqual(c['test'].value, c2['test'].value)
-
-if __name__ == "__main__":
- import doctest
- doctest.testmod()
diff --git a/tests/regressiontests/m2m_through_regress/models.py b/tests/regressiontests/m2m_through_regress/models.py
index 56aecd6975..ec87985765 100644
--- a/tests/regressiontests/m2m_through_regress/models.py
+++ b/tests/regressiontests/m2m_through_regress/models.py
@@ -1,8 +1,10 @@
from datetime import datetime
+
from django.contrib.auth.models import User
from django.core import management
from django.db import models
+
# Forward declared intermediate model
class Membership(models.Model):
person = models.ForeignKey('Person')
@@ -51,159 +53,3 @@ class Through(ThroughBase):
class B(models.Model):
b_text = models.CharField(max_length=20)
a_list = models.ManyToManyField(A, through=Through)
-
-
-__test__ = {'API_TESTS':"""
-# Create some dummy data
->>> bob = Person.objects.create(name='Bob')
->>> jim = Person.objects.create(name='Jim')
-
->>> rock = Group.objects.create(name='Rock')
->>> roll = Group.objects.create(name='Roll')
-
->>> frank = User.objects.create_user('frank','frank@example.com','password')
->>> jane = User.objects.create_user('jane','jane@example.com','password')
-
-# Now test that the forward declared Membership works
->>> Membership.objects.create(person=bob, group=rock)
-<Membership: Bob is a member of Rock>
-
->>> Membership.objects.create(person=bob, group=roll)
-<Membership: Bob is a member of Roll>
-
->>> Membership.objects.create(person=jim, group=rock)
-<Membership: Jim is a member of Rock>
-
->>> bob.group_set.all()
-[<Group: Rock>, <Group: Roll>]
-
->>> roll.members.all()
-[<Person: Bob>]
-
-# Error messages use the model name, not repr of the class name
->>> bob.group_set = []
-Traceback (most recent call last):
-...
-AttributeError: Cannot set values on a ManyToManyField which specifies an intermediary model. Use m2m_through_regress.Membership's Manager instead.
-
->>> roll.members = []
-Traceback (most recent call last):
-...
-AttributeError: Cannot set values on a ManyToManyField which specifies an intermediary model. Use m2m_through_regress.Membership's Manager instead.
-
->>> rock.members.create(name='Anne')
-Traceback (most recent call last):
-...
-AttributeError: Cannot use create() on a ManyToManyField which specifies an intermediary model. Use m2m_through_regress.Membership's Manager instead.
-
->>> bob.group_set.create(name='Funk')
-Traceback (most recent call last):
-...
-AttributeError: Cannot use create() on a ManyToManyField which specifies an intermediary model. Use m2m_through_regress.Membership's Manager instead.
-
-# Now test that the intermediate with a relationship outside
-# the current app (i.e., UserMembership) workds
->>> UserMembership.objects.create(user=frank, group=rock)
-<UserMembership: frank is a user and member of Rock>
-
->>> UserMembership.objects.create(user=frank, group=roll)
-<UserMembership: frank is a user and member of Roll>
-
->>> UserMembership.objects.create(user=jane, group=rock)
-<UserMembership: jane is a user and member of Rock>
-
->>> frank.group_set.all()
-[<Group: Rock>, <Group: Roll>]
-
->>> roll.user_members.all()
-[<User: frank>]
-
-# Regression test for #8134 --
-# m2m-through models shouldn't be serialized as m2m fields on the model.
-
-# First, clean up a lot of objects we don't need.
-# The serialization test only requires three objects to work -
-# one for each end of the m2m, plus the through model.
-
->>> User.objects.all().delete()
->>> UserMembership.objects.all().delete()
->>> frank.delete()
->>> rock.delete()
->>> jim.delete()
-
-# Dump the current contents of the database as a JSON fixture
->>> management.call_command('dumpdata', 'm2m_through_regress', format='json', indent=2)
-[
- {
- "pk": 2,
- "model": "m2m_through_regress.membership",
- "fields": {
- "person": 1,
- "price": 100,
- "group": 2
- }
- },
- {
- "pk": 1,
- "model": "m2m_through_regress.person",
- "fields": {
- "name": "Bob"
- }
- },
- {
- "pk": 2,
- "model": "m2m_through_regress.group",
- "fields": {
- "name": "Roll"
- }
- }
-]
-
-# Check the XML serializer too, since it doesn't use the common implementation
->>> management.call_command('dumpdata', 'm2m_through_regress', format='xml', indent=2)
-<?xml version="1.0" encoding="utf-8"?>
-<django-objects version="1.0">
- <object pk="2" model="m2m_through_regress.membership">
- <field to="m2m_through_regress.person" name="person" rel="ManyToOneRel">1</field>
- <field to="m2m_through_regress.group" name="group" rel="ManyToOneRel">2</field>
- <field type="IntegerField" name="price">100</field>
- </object>
- <object pk="1" model="m2m_through_regress.person">
- <field type="CharField" name="name">Bob</field>
- </object>
- <object pk="2" model="m2m_through_regress.group">
- <field type="CharField" name="name">Roll</field>
- </object>
-</django-objects>
-
-## Regression test for #8046:
-Check that we don't involve too many copies of the intermediate table when
-doing a join.
-
->>> bob = Person.objects.create(name='Bob')
->>> jim = Person.objects.create(name='Jim')
->>> rock = Group.objects.create(name='Rock')
->>> roll = Group.objects.create(name='Roll')
->>> _ = Membership.objects.create(person=bob, group=rock)
->>> _ = Membership.objects.create(person=jim, group=rock, price=50)
->>> _ = Membership.objects.create(person=bob, group=roll, price=50)
->>> rock.members.filter(membership__price=50)
-[<Person: Jim>]
-
-## Regression test for #8254
->>> bob.group_set.filter(membership__price=50)
-[<Group: Roll>]
-
-## Regression test for #9804
-# Flush the database, just to make sure we can.
->>> management.call_command('flush', verbosity=0, interactive=False)
-
-## Regression test for #11107
-Ensure that sequences on m2m_through tables are being created for the through
-model, not for a phantom auto-generated m2m table.
-
->>> management.call_command('loaddata', 'm2m_through', verbosity=0)
->>> management.call_command('dumpdata', 'm2m_through_regress', format='json')
-[{"pk": 1, "model": "m2m_through_regress.usermembership", "fields": {"price": 100, "group": 1, "user": 1}}, {"pk": 1, "model": "m2m_through_regress.person", "fields": {"name": "Guido"}}, {"pk": 1, "model": "m2m_through_regress.group", "fields": {"name": "Python Core Group"}}]
-
-"""}
diff --git a/tests/regressiontests/m2m_through_regress/tests.py b/tests/regressiontests/m2m_through_regress/tests.py
new file mode 100644
index 0000000000..ff1d95020e
--- /dev/null
+++ b/tests/regressiontests/m2m_through_regress/tests.py
@@ -0,0 +1,126 @@
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+from django.core import management
+from django.contrib.auth.models import User
+from django.test import TestCase
+
+from models import Person, Group, Membership, UserMembership
+
+
+class M2MThroughTestCase(TestCase):
+ def test_everything(self):
+ bob = Person.objects.create(name="Bob")
+ jim = Person.objects.create(name="Jim")
+
+ rock = Group.objects.create(name="Rock")
+ roll = Group.objects.create(name="Roll")
+
+ frank = User.objects.create_user("frank", "frank@example.com", "password")
+ jane = User.objects.create_user("jane", "jane@example.com", "password")
+
+ Membership.objects.create(person=bob, group=rock)
+ Membership.objects.create(person=bob, group=roll)
+ Membership.objects.create(person=jim, group=rock)
+
+ self.assertQuerysetEqual(
+ bob.group_set.all(), [
+ "<Group: Rock>",
+ "<Group: Roll>",
+ ]
+ )
+
+ self.assertQuerysetEqual(
+ roll.members.all(), [
+ "<Person: Bob>",
+ ]
+ )
+
+ self.assertRaises(AttributeError, setattr, bob, "group_set", [])
+ self.assertRaises(AttributeError, setattr, roll, "members", [])
+
+ self.assertRaises(AttributeError, rock.members.create, name="Anne")
+ self.assertRaises(AttributeError, bob.group_set.create, name="Funk")
+
+ UserMembership.objects.create(user=frank, group=rock)
+ UserMembership.objects.create(user=frank, group=roll)
+ UserMembership.objects.create(user=jane, group=rock)
+
+ self.assertQuerysetEqual(
+ frank.group_set.all(), [
+ "<Group: Rock>",
+ "<Group: Roll>",
+ ]
+ )
+
+ self.assertQuerysetEqual(
+ roll.user_members.all(), [
+ "<User: frank>",
+ ]
+ )
+
+ def test_serialization(self):
+ "m2m-through models aren't serialized as m2m fields. Refs #8134"
+
+ p = Person.objects.create(name="Bob")
+ g = Group.objects.create(name="Roll")
+ Membership.objects.create(person=p, group=g)
+
+ out = StringIO()
+ management.call_command("dumpdata", "m2m_through_regress", format="json", stdout=out)
+ self.assertEqual(out.getvalue().strip(), """[{"pk": 1, "model": "m2m_through_regress.membership", "fields": {"person": 1, "price": 100, "group": 1}}, {"pk": 1, "model": "m2m_through_regress.person", "fields": {"name": "Bob"}}, {"pk": 1, "model": "m2m_through_regress.group", "fields": {"name": "Roll"}}]""")
+
+ out = StringIO()
+ management.call_command("dumpdata", "m2m_through_regress", format="xml",
+ indent=2, stdout=out)
+ self.assertEqual(out.getvalue().strip(), """
+<?xml version="1.0" encoding="utf-8"?>
+<django-objects version="1.0">
+ <object pk="1" model="m2m_through_regress.membership">
+ <field to="m2m_through_regress.person" name="person" rel="ManyToOneRel">1</field>
+ <field to="m2m_through_regress.group" name="group" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="price">100</field>
+ </object>
+ <object pk="1" model="m2m_through_regress.person">
+ <field type="CharField" name="name">Bob</field>
+ </object>
+ <object pk="1" model="m2m_through_regress.group">
+ <field type="CharField" name="name">Roll</field>
+ </object>
+</django-objects>
+ """.strip())
+
+ def test_join_trimming(self):
+ "Check that we don't involve too many copies of the intermediate table when doing a join. Refs #8046, #8254"
+ bob = Person.objects.create(name="Bob")
+ jim = Person.objects.create(name="Jim")
+
+ rock = Group.objects.create(name="Rock")
+ roll = Group.objects.create(name="Roll")
+
+ Membership.objects.create(person=bob, group=rock)
+ Membership.objects.create(person=jim, group=rock, price=50)
+ Membership.objects.create(person=bob, group=roll, price=50)
+
+ self.assertQuerysetEqual(
+ rock.members.filter(membership__price=50), [
+ "<Person: Jim>",
+ ]
+ )
+
+ self.assertQuerysetEqual(
+ bob.group_set.filter(membership__price=50), [
+ "<Group: Roll>",
+ ]
+ )
+
+class ThroughLoadDataTestCase(TestCase):
+ fixtures = ["m2m_through"]
+
+ def test_sequence_creation(self):
+ "Check that sequences on an m2m_through are created for the through model, not a phantom auto-generated m2m table. Refs #11107"
+ out = StringIO()
+ management.call_command("dumpdata", "m2m_through_regress", format="json", stdout=out)
+ self.assertEqual(out.getvalue().strip(), """[{"pk": 1, "model": "m2m_through_regress.usermembership", "fields": {"price": 100, "group": 1, "user": 1}}, {"pk": 1, "model": "m2m_through_regress.person", "fields": {"name": "Guido"}}, {"pk": 1, "model": "m2m_through_regress.group", "fields": {"name": "Python Core Group"}}]""")
diff --git a/tests/regressiontests/multiple_database/tests.py b/tests/regressiontests/multiple_database/tests.py
index 7bde8bf037..6675fdcc6c 100644
--- a/tests/regressiontests/multiple_database/tests.py
+++ b/tests/regressiontests/multiple_database/tests.py
@@ -883,7 +883,13 @@ class QueryTestCase(TestCase):
self.assertRaises(ValueError, str, qs.query)
# Evaluating the query shouldn't work, either
- self.assertRaises(ValueError, list, qs)
+ try:
+ for obj in qs:
+ pass
+ self.fail('Iterating over query should raise ValueError')
+ except ValueError:
+ pass
+
class TestRouter(object):
# A test router. The behaviour is vaguely master/slave, but the
@@ -1491,19 +1497,10 @@ class AuthTestCase(TestCase):
self.old_routers = router.routers
router.routers = [AuthRouter()]
- # Redirect stdout to a buffer so we can test
- # the output of a management command
- self.old_stdout = sys.stdout
- self.stdout = StringIO()
- sys.stdout = self.stdout
-
def tearDown(self):
# Restore the 'other' database as an independent database
router.routers = self.old_routers
- # Restore stdout
- sys.stdout = self.old_stdout
-
def test_auth_manager(self):
"The methods on the auth manager obey database hints"
# Create one user using default allocation policy
@@ -1539,14 +1536,16 @@ class AuthTestCase(TestCase):
# Check that dumping the default database doesn't try to include auth
# because allow_syncdb prohibits auth on default
- self.stdout.flush()
- management.call_command('dumpdata', 'auth', format='json', database='default')
- self.assertEquals(self.stdout.getvalue(), '[]\n')
+ new_io = StringIO()
+ management.call_command('dumpdata', 'auth', format='json', database='default', stdout=new_io)
+ command_output = new_io.getvalue().strip()
+ self.assertEqual(command_output, '[]')
# Check that dumping the other database does include auth
- self.stdout.flush()
- management.call_command('dumpdata', 'auth', format='json', database='other')
- self.assertTrue('alice@example.com' in self.stdout.getvalue())
+ new_io = StringIO()
+ management.call_command('dumpdata', 'auth', format='json', database='other', stdout=new_io)
+ command_output = new_io.getvalue().strip()
+ self.assertTrue('"email": "alice@example.com",' in command_output)
class UserProfileTestCase(TestCase):
def setUp(self):
diff --git a/tests/regressiontests/serializers_regress/tests.py b/tests/regressiontests/serializers_regress/tests.py
index 84e90ff7e1..be920c6920 100644
--- a/tests/regressiontests/serializers_regress/tests.py
+++ b/tests/regressiontests/serializers_regress/tests.py
@@ -10,14 +10,16 @@ forward, backwards and self references.
import datetime
import decimal
-import unittest
-from cStringIO import StringIO
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
-from django.utils.functional import curry
-from django.core import serializers
-from django.db import transaction, DEFAULT_DB_ALIAS
-from django.core import management
from django.conf import settings
+from django.core import serializers, management
+from django.db import transaction, DEFAULT_DB_ALIAS
+from django.test import TestCase
+from django.utils.functional import curry
from models import *
@@ -59,10 +61,10 @@ def im2m_create(pk, klass, data):
def im_create(pk, klass, data):
instance = klass(id=pk)
- setattr(instance, 'right_id', data['right'])
- setattr(instance, 'left_id', data['left'])
+ instance.right_id = data['right']
+ instance.left_id = data['left']
if 'extra' in data:
- setattr(instance, 'extra', data['extra'])
+ instance.extra = data['extra']
models.Model.save_base(instance, raw=True)
return [instance]
@@ -96,7 +98,9 @@ def inherited_create(pk, klass, data):
def data_compare(testcase, pk, klass, data):
instance = klass.objects.get(id=pk)
testcase.assertEqual(data, instance.data,
- "Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data)))
+ "Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (
+ pk, data, type(data), instance.data, type(instance.data))
+ )
def generic_compare(testcase, pk, klass, data):
instance = klass.objects.get(id=pk)
@@ -348,28 +352,16 @@ if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
# Dynamically create serializer tests to ensure that all
# registered serializers are automatically tested.
-class SerializerTests(unittest.TestCase):
+class SerializerTests(TestCase):
pass
def serializerTest(format, self):
- # Clear the database first
- management.call_command('flush', verbosity=0, interactive=False)
# Create all the objects defined in the test data
objects = []
instance_count = {}
- transaction.enter_transaction_management()
- try:
- transaction.managed(True)
- for (func, pk, klass, datum) in test_data:
- objects.extend(func[0](pk, klass, datum))
- instance_count[klass] = 0
- transaction.commit()
- except:
- transaction.rollback()
- transaction.leave_transaction_management()
- raise
- transaction.leave_transaction_management()
+ for (func, pk, klass, datum) in test_data:
+ objects.extend(func[0](pk, klass, datum))
# Get a count of the number of objects created for each class
for klass in instance_count:
@@ -381,19 +373,8 @@ def serializerTest(format, self):
# Serialize the test database
serialized_data = serializers.serialize(format, objects, indent=2)
- # Flush the database and recreate from the serialized data
- management.call_command('flush', verbosity=0, interactive=False)
- transaction.enter_transaction_management()
- try:
- transaction.managed(True)
- for obj in serializers.deserialize(format, serialized_data):
- obj.save()
- transaction.commit()
- except:
- transaction.rollback()
- transaction.leave_transaction_management()
- raise
- transaction.leave_transaction_management()
+ for obj in serializers.deserialize(format, serialized_data):
+ obj.save()
# Assert that the deserialized data is the same
# as the original source
@@ -406,10 +387,7 @@ def serializerTest(format, self):
self.assertEquals(count, klass.objects.count())
def fieldsTest(format, self):
- # Clear the database first
- management.call_command('flush', verbosity=0, interactive=False)
-
- obj = ComplexModel(field1='first',field2='second',field3='third')
+ obj = ComplexModel(field1='first', field2='second', field3='third')
obj.save_base(raw=True)
# Serialize then deserialize the test database
@@ -422,9 +400,6 @@ def fieldsTest(format, self):
self.assertEqual(result.object.field3, 'third')
def streamTest(format, self):
- # Clear the database first
- management.call_command('flush', verbosity=0, interactive=False)
-
obj = ComplexModel(field1='first',field2='second',field3='third')
obj.save_base(raw=True)
@@ -440,7 +415,7 @@ def streamTest(format, self):
stream.close()
for format in serializers.get_serializer_formats():
- setattr(SerializerTests, 'test_'+format+'_serializer', curry(serializerTest, format))
- setattr(SerializerTests, 'test_'+format+'_serializer_fields', curry(fieldsTest, format))
+ setattr(SerializerTests, 'test_' + format + '_serializer', curry(serializerTest, format))
+ setattr(SerializerTests, 'test_' + format + '_serializer_fields', curry(fieldsTest, format))
if format != 'python':
- setattr(SerializerTests, 'test_'+format+'_serializer_stream', curry(streamTest, format))
+ setattr(SerializerTests, 'test_' + format + '_serializer_stream', curry(streamTest, format))
diff --git a/tests/regressiontests/utils/timesince.py b/tests/regressiontests/utils/timesince.py
index 04878b272a..5a54bf4c8c 100644
--- a/tests/regressiontests/utils/timesince.py
+++ b/tests/regressiontests/utils/timesince.py
@@ -88,11 +88,11 @@ u'0 minutes'
u'0 minutes'
# Timesince should work with both date objects (#9672)
->>> today = datetime.date.today()
->>> timeuntil(today+oneday, today)
-u'1 day'
->>> timeuntil(today-oneday, today)
-u'0 minutes'
->>> timeuntil(today+oneweek, today)
-u'1 week'
+>>> today = datetime.date.today()
+>>> timeuntil(today+oneday, today)
+u'1 day'
+>>> timeuntil(today-oneday, today)
+u'0 minutes'
+>>> timeuntil(today+oneweek, today)
+u'1 week'
"""