diff options
| author | Brian Rosner <brosner@gmail.com> | 2008-06-10 04:03:09 +0000 |
|---|---|---|
| committer | Brian Rosner <brosner@gmail.com> | 2008-06-10 04:03:09 +0000 |
| commit | 4530a408c40647c195f27f81da1315e98e956f96 (patch) | |
| tree | ed8290751a7e284b9f030f4da97b422067ca9c95 /tests/regressiontests | |
| parent | 3b92ced51856e740cd6fb3d3e5bb8ea932bd276e (diff) | |
newforms-admin: Merged from trunk up to [7602].
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7604 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests/regressiontests')
9 files changed, 267 insertions, 7 deletions
diff --git a/tests/regressiontests/fixtures_regress/fixtures/bad_fixture1.unkn b/tests/regressiontests/fixtures_regress/fixtures/bad_fixture1.unkn new file mode 100644 index 0000000000..a8b0a0c56c --- /dev/null +++ b/tests/regressiontests/fixtures_regress/fixtures/bad_fixture1.unkn @@ -0,0 +1 @@ +This data shouldn't load, as it's of an unknown file format.
\ No newline at end of file diff --git a/tests/regressiontests/fixtures_regress/fixtures/bad_fixture2.xml b/tests/regressiontests/fixtures_regress/fixtures/bad_fixture2.xml new file mode 100644 index 0000000000..87b809fbc6 --- /dev/null +++ b/tests/regressiontests/fixtures_regress/fixtures/bad_fixture2.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<django-objcts version="1.0"> + <objct pk="2" model="fixtures.article"> + <field type="CharField" name="headline">Poker on TV is great!</field> + <field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field> + </objct> +</django-objcts>
\ No newline at end of file diff --git a/tests/regressiontests/fixtures_regress/models.py b/tests/regressiontests/fixtures_regress/models.py index 144debe05a..59fc167d50 100644 --- a/tests/regressiontests/fixtures_regress/models.py +++ b/tests/regressiontests/fixtures_regress/models.py @@ -71,4 +71,27 @@ __test__ = {'API_TESTS':""" >>> Absolute.load_count 1 +############################################### +# Test for ticket #4371 -- fixture loading fails silently in testcases +# Validate that error conditions are caught correctly + +# redirect stderr for the next few tests... +>>> import sys +>>> savestderr = sys.stderr +>>> sys.stderr = sys.stdout + +# Loading data of an unknown format should fail +>>> management.call_command('loaddata', 'bad_fixture1.unkn', verbosity=0) +Problem installing fixture 'bad_fixture1': unkn is not a known serialization format. + +# Loading a fixture file with invalid data using explicit filename +>>> management.call_command('loaddata', 'bad_fixture2.xml', verbosity=0) +No fixture data found for 'bad_fixture2'. (File format may be invalid.) + +# Loading a fixture file with invalid data without file extension +>>> management.call_command('loaddata', 'bad_fixture2', verbosity=0) +No fixture data found for 'bad_fixture2'. (File format may be invalid.) + +>>> sys.stderr = savestderr + """} diff --git a/tests/regressiontests/model_inheritance_regress/__init__.py b/tests/regressiontests/model_inheritance_regress/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/regressiontests/model_inheritance_regress/__init__.py diff --git a/tests/regressiontests/model_inheritance_regress/models.py b/tests/regressiontests/model_inheritance_regress/models.py new file mode 100644 index 0000000000..8801715a0c --- /dev/null +++ b/tests/regressiontests/model_inheritance_regress/models.py @@ -0,0 +1,120 @@ +""" +Regression tests for Model inheritance behaviour. +""" + +from django.db import models + +class Place(models.Model): + name = models.CharField(max_length=50) + address = models.CharField(max_length=80) + + class Meta: + ordering = ('name',) + + def __unicode__(self): + return u"%s the place" % self.name + +class Restaurant(Place): + serves_hot_dogs = models.BooleanField() + serves_pizza = models.BooleanField() + + def __unicode__(self): + return u"%s the restaurant" % self.name + +class ItalianRestaurant(Restaurant): + serves_gnocchi = models.BooleanField() + + def __unicode__(self): + return u"%s the italian restaurant" % self.name + +class ParkingLot(Place): + # An explicit link to the parent (we can control the attribute name). + parent = models.OneToOneField(Place, primary_key=True, parent_link=True) + capacity = models.IntegerField() + + def __unicode__(self): + return u"%s the parking lot" % self.name + +__test__ = {'API_TESTS':""" +# Regression for #7350, #7202 +# Check that when you create a Parent object with a specific reference to an existent +# child instance, saving the Parent doesn't duplicate the child. +# This behaviour is only activated during a raw save - it is mostly relevant to +# deserialization, but any sort of CORBA style 'narrow()' API would require a +# similar approach. + +# Create a child-parent-grandparent chain +>>> place1 = Place(name="Guido's House of Pasta", address='944 W. Fullerton') +>>> place1.save_base(raw=True) +>>> restaurant = Restaurant(place_ptr=place1, serves_hot_dogs=True, serves_pizza=False) +>>> restaurant.save_base(raw=True) +>>> italian_restaurant = ItalianRestaurant(restaurant_ptr=restaurant, serves_gnocchi=True) +>>> italian_restaurant.save_base(raw=True) + +# Create a child-parent chain with an explicit parent link +>>> place2 = Place(name='Main St', address='111 Main St') +>>> place2.save_base(raw=True) +>>> park = ParkingLot(parent=place2, capacity=100) +>>> park.save_base(raw=True) + +# Check that no extra parent objects have been created. +>>> Place.objects.all() +[<Place: Guido's House of Pasta the place>, <Place: Main St the place>] + +>>> dicts = Restaurant.objects.values('name','serves_hot_dogs') +>>> [sorted(d.items()) for d in dicts] +[[('name', u"Guido's House of Pasta"), ('serves_hot_dogs', True)]] + +>>> dicts = ItalianRestaurant.objects.values('name','serves_hot_dogs','serves_gnocchi') +>>> [sorted(d.items()) for d in dicts] +[[('name', u"Guido's House of Pasta"), ('serves_gnocchi', True), ('serves_hot_dogs', True)]] + +>>> dicts = ParkingLot.objects.values('name','capacity') +>>> [sorted(d.items()) for d in dicts] +[[('capacity', 100), ('name', u'Main St')]] + +# You can also update objects when using a raw save. +>>> place1.name = "Guido's All New House of Pasta" +>>> place1.save_base(raw=True) + +>>> restaurant.serves_hot_dogs = False +>>> restaurant.save_base(raw=True) + +>>> italian_restaurant.serves_gnocchi = False +>>> italian_restaurant.save_base(raw=True) + +>>> place2.name='Derelict lot' +>>> place2.save_base(raw=True) + +>>> park.capacity = 50 +>>> park.save_base(raw=True) + +# No extra parent objects after an update, either. +>>> Place.objects.all() +[<Place: Derelict lot the place>, <Place: Guido's All New House of Pasta the place>] + +>>> dicts = Restaurant.objects.values('name','serves_hot_dogs') +>>> [sorted(d.items()) for d in dicts] +[[('name', u"Guido's All New House of Pasta"), ('serves_hot_dogs', False)]] + +>>> dicts = ItalianRestaurant.objects.values('name','serves_hot_dogs','serves_gnocchi') +>>> [sorted(d.items()) for d in dicts] +[[('name', u"Guido's All New House of Pasta"), ('serves_gnocchi', False), ('serves_hot_dogs', False)]] + +>>> dicts = ParkingLot.objects.values('name','capacity') +>>> [sorted(d.items()) for d in dicts] +[[('capacity', 50), ('name', u'Derelict lot')]] + +# If you try to raw_save a parent attribute onto a child object, +# the attribute will be ignored. + +>>> italian_restaurant.name = "Lorenzo's Pasta Hut" +>>> italian_restaurant.save_base(raw=True) + +# Note that the name has not changed +# - name is an attribute of Place, not ItalianRestaurant +>>> dicts = ItalianRestaurant.objects.values('name','serves_hot_dogs','serves_gnocchi') +>>> [sorted(d.items()) for d in dicts] +[[('name', u"Guido's All New House of Pasta"), ('serves_gnocchi', False), ('serves_hot_dogs', False)]] + +"""} diff --git a/tests/regressiontests/null_fk/__init__.py b/tests/regressiontests/null_fk/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/regressiontests/null_fk/__init__.py diff --git a/tests/regressiontests/null_fk/models.py b/tests/regressiontests/null_fk/models.py new file mode 100644 index 0000000000..1bc266c033 --- /dev/null +++ b/tests/regressiontests/null_fk/models.py @@ -0,0 +1,55 @@ +""" +Regression tests for proper working of ForeignKey(null=True). Tests these bugs: + + * #7369: FK non-null after null relationship on select_related() generates an invalid query + +""" + +from django.db import models + +class SystemInfo(models.Model): + system_name = models.CharField(max_length=32) + +class Forum(models.Model): + system_info = models.ForeignKey(SystemInfo) + forum_name = models.CharField(max_length=32) + +class Post(models.Model): + forum = models.ForeignKey(Forum, null=True) + title = models.CharField(max_length=32) + + def __unicode__(self): + return self.title + +class Comment(models.Model): + post = models.ForeignKey(Post, null=True) + comment_text = models.CharField(max_length=250) + + def __unicode__(self): + return self.comment_text + +__test__ = {'API_TESTS':""" + +>>> s = SystemInfo.objects.create(system_name='First forum') +>>> f = Forum.objects.create(system_info=s, forum_name='First forum') +>>> p = Post.objects.create(forum=f, title='First Post') +>>> c1 = Comment.objects.create(post=p, comment_text='My first comment') +>>> c2 = Comment.objects.create(comment_text='My second comment') + +# Starting from comment, make sure that a .select_related(...) with a specified +# set of fields will properly LEFT JOIN multiple levels of NULLs (and the things +# that come after the NULLs, or else data that should exist won't). +>>> c = Comment.objects.select_related().get(id=1) +>>> c.post +<Post: First Post> +>>> c = Comment.objects.select_related().get(id=2) +>>> print c.post +None + +>>> comments = Comment.objects.select_related('post__forum__system_info').all() +>>> [(c.id, c.post.id) for c in comments] +[(1, 1), (2, None)] +>>> [(c.comment_text, c.post.title) for c in comments] +[(u'My first comment', u'First Post'), (u'My second comment', None)] + +"""} diff --git a/tests/regressiontests/serializers_regress/models.py b/tests/regressiontests/serializers_regress/models.py index 593e61ecc7..7d3f9d3b1d 100644 --- a/tests/regressiontests/serializers_regress/models.py +++ b/tests/regressiontests/serializers_regress/models.py @@ -223,3 +223,23 @@ class ModifyingSaveData(models.Model): "A save method that modifies the data in the object" self.data = 666 super(ModifyingSaveData, self).save(raw) + +# Tests for serialization of models using inheritance. +# Regression for #7202, #7350 +class AbstractBaseModel(models.Model): + parent_data = models.IntegerField() + class Meta: + abstract = True + +class InheritAbstractModel(AbstractBaseModel): + child_data = models.IntegerField() + +class BaseModel(models.Model): + parent_data = models.IntegerField() + +class InheritBaseModel(BaseModel): + child_data = models.IntegerField() + +class ExplicitInheritBaseModel(BaseModel): + parent = models.OneToOneField(BaseModel) + child_data = models.IntegerField() diff --git a/tests/regressiontests/serializers_regress/tests.py b/tests/regressiontests/serializers_regress/tests.py index db34f8cf77..9bc5eec1eb 100644 --- a/tests/regressiontests/serializers_regress/tests.py +++ b/tests/regressiontests/serializers_regress/tests.py @@ -32,7 +32,7 @@ def data_create(pk, klass, data): instance = klass(id=pk) instance.data = data models.Model.save_base(instance, raw=True) - return instance + return [instance] def generic_create(pk, klass, data): instance = klass(id=pk) @@ -40,32 +40,45 @@ def generic_create(pk, klass, data): models.Model.save_base(instance, raw=True) for tag in data[1:]: instance.tags.create(data=tag) - return instance + return [instance] def fk_create(pk, klass, data): instance = klass(id=pk) setattr(instance, 'data_id', data) models.Model.save_base(instance, raw=True) - return instance + return [instance] def m2m_create(pk, klass, data): instance = klass(id=pk) models.Model.save_base(instance, raw=True) instance.data = data - return instance + return [instance] def o2o_create(pk, klass, data): instance = klass() instance.data_id = data models.Model.save_base(instance, raw=True) - return instance + return [instance] def pk_create(pk, klass, data): instance = klass() instance.data = data models.Model.save_base(instance, raw=True) - return instance + return [instance] +def inherited_create(pk, klass, data): + instance = klass(id=pk,**data) + # This isn't a raw save because: + # 1) we're testing inheritance, not field behaviour, so none + # of the field values need to be protected. + # 2) saving the child class and having the parent created + # automatically is easier than manually creating both. + models.Model.save(instance) + created = [instance] + for klass,field in instance._meta.parents.items(): + created.append(klass.objects.get(id=pk)) + return created + # A set of functions that can be used to compare # test data objects of various kinds def data_compare(testcase, pk, klass, data): @@ -94,6 +107,11 @@ def pk_compare(testcase, pk, klass, data): instance = klass.objects.get(data=data) testcase.assertEqual(data, instance.data) +def inherited_compare(testcase, pk, klass, data): + instance = klass.objects.get(id=pk) + for key,value in data.items(): + testcase.assertEqual(value, getattr(instance,key)) + # Define some data types. Each data type is # actually a pair of functions; one to create # and one to compare objects of that type @@ -103,6 +121,7 @@ fk_obj = (fk_create, fk_compare) m2m_obj = (m2m_create, m2m_compare) o2o_obj = (o2o_create, o2o_compare) pk_obj = (pk_create, pk_compare) +inherited_obj = (inherited_create, inherited_compare) test_data = [ # Format: (data type, PK value, Model Class, data) @@ -255,6 +274,10 @@ The end."""), (data_obj, 800, AutoNowDateTimeData, datetime.datetime(2006,6,16,10,42,37)), (data_obj, 810, ModifyingSaveData, 42), + + (inherited_obj, 900, InheritAbstractModel, {'child_data':37,'parent_data':42}), + (inherited_obj, 910, ExplicitInheritBaseModel, {'child_data':37,'parent_data':42}), + (inherited_obj, 920, InheritBaseModel, {'child_data':37,'parent_data':42}), ] # Because Oracle treats the empty string as NULL, Oracle is expected to fail @@ -277,13 +300,19 @@ def serializerTest(format, self): # Create all the objects defined in the test data objects = [] + instance_count = {} transaction.enter_transaction_management() transaction.managed(True) for (func, pk, klass, datum) in test_data: - objects.append(func[0](pk, klass, datum)) + objects.extend(func[0](pk, klass, datum)) + instance_count[klass] = 0 transaction.commit() transaction.leave_transaction_management() + # Get a count of the number of objects created for each class + for klass in instance_count: + instance_count[klass] = klass.objects.count() + # Add the generic tagged objects to the object list objects.extend(Tag.objects.all()) @@ -304,6 +333,11 @@ def serializerTest(format, self): for (func, pk, klass, datum) in test_data: func[1](self, pk, klass, datum) + # Assert that the number of objects deserialized is the + # same as the number that was serialized. + for klass, count in instance_count.items(): + self.assertEquals(count, klass.objects.count()) + def fieldsTest(format, self): # Clear the database first management.call_command('flush', verbosity=0, interactive=False) |
