summaryrefslogtreecommitdiff
path: root/tests/modeltests/delete
diff options
context:
space:
mode:
authorBrian Rosner <brosner@gmail.com>2008-06-23 21:05:02 +0000
committerBrian Rosner <brosner@gmail.com>2008-06-23 21:05:02 +0000
commit420f19aa353ee6568c93f34dfe2e6eef24bc528d (patch)
tree12f182ec4f958ac08a57f05786fdbefabae9910c /tests/modeltests/delete
parentc929440fcd001b97b805f2229fb85deae3f86e05 (diff)
newforms-admin: Merged from trunk up to [7729].
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7730 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests/modeltests/delete')
-rw-r--r--tests/modeltests/delete/__init__.py1
-rw-r--r--tests/modeltests/delete/models.py179
2 files changed, 180 insertions, 0 deletions
diff --git a/tests/modeltests/delete/__init__.py b/tests/modeltests/delete/__init__.py
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/tests/modeltests/delete/__init__.py
@@ -0,0 +1 @@
+
diff --git a/tests/modeltests/delete/models.py b/tests/modeltests/delete/models.py
new file mode 100644
index 0000000000..f5b423e9ff
--- /dev/null
+++ b/tests/modeltests/delete/models.py
@@ -0,0 +1,179 @@
+# coding: utf-8
+"""
+Tests for some corner cases with deleting.
+"""
+
+from django.db import models
+
+class DefaultRepr(object):
+ def __repr__(self):
+ return u"<%s: %s>" % (self.__class__.__name__, self.__dict__)
+
+class A(DefaultRepr, models.Model):
+ pass
+
+class B(DefaultRepr, models.Model):
+ a = models.ForeignKey(A)
+
+class C(DefaultRepr, models.Model):
+ b = models.ForeignKey(B)
+
+class D(DefaultRepr, models.Model):
+ c = models.ForeignKey(C)
+ a = models.ForeignKey(A)
+
+# Simplified, we have:
+# A
+# B -> A
+# C -> B
+# D -> C
+# D -> A
+
+# So, we must delete Ds first of all, then Cs then Bs then As.
+# However, if we start at As, we might find Bs first (in which
+# case things will be nice), or find Ds first.
+
+# Some mutually dependent models, but nullable
+class E(DefaultRepr, models.Model):
+ f = models.ForeignKey('F', null=True, related_name='e_rel')
+
+class F(DefaultRepr, models.Model):
+ e = models.ForeignKey(E, related_name='f_rel')
+
+
+__test__ = {'API_TESTS': """
+# First, some tests for the datastructure we use
+
+>>> from django.db.models.query import CollectedObjects
+
+>>> g = CollectedObjects()
+>>> g.add("key1", 1, "item1", None)
+False
+>>> g["key1"]
+{1: 'item1'}
+>>> g.add("key2", 1, "item1", "key1")
+False
+>>> g.add("key2", 2, "item2", "key1")
+False
+>>> g["key2"]
+{1: 'item1', 2: 'item2'}
+>>> g.add("key3", 1, "item1", "key1")
+False
+>>> g.add("key3", 1, "item1", "key2")
+True
+>>> g.ordered_keys()
+['key3', 'key2', 'key1']
+
+>>> g.add("key2", 1, "item1", "key3")
+True
+>>> g.ordered_keys()
+Traceback (most recent call last):
+ ...
+CyclicDependency: There is a cyclic dependency of items to be processed.
+
+
+
+# Due to the way that transactions work in the test harness,
+# doing m.delete() here can work but fail in a real situation,
+# since it may delete all objects, but not in the right order.
+# So we manually check that the order of deletion is correct.
+
+# Also, it is possible that the order is correct 'accidentally', due
+# solely to order of imports etc. To check this, we set the order
+# that 'get_models()' will retrieve to a known 'nice' order, and
+# then try again with a known 'tricky' order. Slightly naughty
+# access to internals here :-)
+
+>>> from django.db.models.loading import cache
+
+# Nice order
+>>> cache.app_models['delete'].keyOrder = ['a', 'b', 'c', 'd']
+>>> del A._meta._related_objects_cache
+>>> del B._meta._related_objects_cache
+>>> del C._meta._related_objects_cache
+>>> del D._meta._related_objects_cache
+
+>>> a1 = A()
+>>> a1.save()
+>>> b1 = B(a=a1)
+>>> b1.save()
+>>> c1 = C(b=b1)
+>>> c1.save()
+>>> d1 = D(c=c1, a=a1)
+>>> d1.save()
+
+>>> o = CollectedObjects()
+>>> a1._collect_sub_objects(o)
+>>> o.keys()
+[<class 'modeltests.delete.models.D'>, <class 'modeltests.delete.models.C'>, <class 'modeltests.delete.models.B'>, <class 'modeltests.delete.models.A'>]
+>>> a1.delete()
+
+# Same again with a known bad order
+>>> cache.app_models['delete'].keyOrder = ['d', 'c', 'b', 'a']
+>>> del A._meta._related_objects_cache
+>>> del B._meta._related_objects_cache
+>>> del C._meta._related_objects_cache
+>>> del D._meta._related_objects_cache
+
+>>> a2 = A()
+>>> a2.save()
+>>> b2 = B(a=a2)
+>>> b2.save()
+>>> c2 = C(b=b2)
+>>> c2.save()
+>>> d2 = D(c=c2, a=a2)
+>>> d2.save()
+
+>>> o = CollectedObjects()
+>>> a2._collect_sub_objects(o)
+>>> o.keys()
+[<class 'modeltests.delete.models.D'>, <class 'modeltests.delete.models.C'>, <class 'modeltests.delete.models.B'>, <class 'modeltests.delete.models.A'>]
+>>> a2.delete()
+
+# Tests for nullable related fields
+
+>>> g = CollectedObjects()
+>>> g.add("key1", 1, "item1", None)
+False
+>>> g.add("key2", 1, "item1", "key1", nullable=True)
+False
+>>> g.add("key1", 1, "item1", "key2")
+True
+>>> g.ordered_keys()
+['key1', 'key2']
+
+>>> e1 = E()
+>>> e1.save()
+>>> f1 = F(e=e1)
+>>> f1.save()
+>>> e1.f = f1
+>>> e1.save()
+
+# Since E.f is nullable, we should delete F first (after nulling out
+# the E.f field), then E.
+
+>>> o = CollectedObjects()
+>>> e1._collect_sub_objects(o)
+>>> o.keys()
+[<class 'modeltests.delete.models.F'>, <class 'modeltests.delete.models.E'>]
+
+>>> e1.delete()
+
+>>> e2 = E()
+>>> e2.save()
+>>> f2 = F(e=e2)
+>>> f2.save()
+>>> e2.f = f2
+>>> e2.save()
+
+# Same deal as before, though we are starting from the other object.
+
+>>> o = CollectedObjects()
+>>> f2._collect_sub_objects(o)
+>>> o.keys()
+[<class 'modeltests.delete.models.F'>, <class 'modeltests.delete.models.E'>]
+
+>>> f2.delete()
+
+"""
+}