PageRenderTime 229ms CodeModel.GetById 212ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/regressiontests/delete_regress/tests.py

https://code.google.com/p/mango-py/
Python | 147 lines | 89 code | 22 blank | 36 comment | 2 complexity | 9f4ec0428761d56ac468c9ce8ba8db25 MD5 | raw file
  1import datetime
  2
  3from django.conf import settings
  4from django.db import backend, connection, transaction, DEFAULT_DB_ALIAS
  5from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
  6
  7from models import (Book, Award, AwardNote, Person, Child, Toy, PlayedWith,
  8    PlayedWithNote, Contact, Email, Researcher, Food, Eaten,
  9    Policy, Version, Location, Item)
 10
 11
 12# Can't run this test under SQLite, because you can't
 13# get two connections to an in-memory database.
 14class DeleteLockingTest(TransactionTestCase):
 15    def setUp(self):
 16        # Create a second connection to the default database
 17        conn_settings = settings.DATABASES[DEFAULT_DB_ALIAS]
 18        self.conn2 = backend.DatabaseWrapper({
 19            'HOST': conn_settings['HOST'],
 20            'NAME': conn_settings['NAME'],
 21            'OPTIONS': conn_settings['OPTIONS'],
 22            'PASSWORD': conn_settings['PASSWORD'],
 23            'PORT': conn_settings['PORT'],
 24            'USER': conn_settings['USER'],
 25            'TIME_ZONE': settings.TIME_ZONE,
 26        })
 27
 28        # Put both DB connections into managed transaction mode
 29        transaction.enter_transaction_management()
 30        transaction.managed(True)
 31        self.conn2._enter_transaction_management(True)
 32
 33    def tearDown(self):
 34        # Close down the second connection.
 35        transaction.leave_transaction_management()
 36        self.conn2.close()
 37
 38    @skipUnlessDBFeature('test_db_allows_multiple_connections')
 39    def test_concurrent_delete(self):
 40        "Deletes on concurrent transactions don't collide and lock the database. Regression for #9479"
 41
 42        # Create some dummy data
 43        b1 = Book(id=1, pagecount=100)
 44        b2 = Book(id=2, pagecount=200)
 45        b3 = Book(id=3, pagecount=300)
 46        b1.save()
 47        b2.save()
 48        b3.save()
 49
 50        transaction.commit()
 51
 52        self.assertEqual(3, Book.objects.count())
 53
 54        # Delete something using connection 2.
 55        cursor2 = self.conn2.cursor()
 56        cursor2.execute('DELETE from delete_regress_book WHERE id=1')
 57        self.conn2._commit();
 58
 59        # Now perform a queryset delete that covers the object
 60        # deleted in connection 2. This causes an infinite loop
 61        # under MySQL InnoDB unless we keep track of already
 62        # deleted objects.
 63        Book.objects.filter(pagecount__lt=250).delete()
 64        transaction.commit()
 65        self.assertEqual(1, Book.objects.count())
 66        transaction.commit()
 67
 68
 69class DeleteCascadeTests(TestCase):
 70    def test_generic_relation_cascade(self):
 71        """
 72        Django cascades deletes through generic-related objects to their
 73        reverse relations.
 74
 75        """
 76        person = Person.objects.create(name='Nelson Mandela')
 77        award = Award.objects.create(name='Nobel', content_object=person)
 78        note = AwardNote.objects.create(note='a peace prize',
 79                                        award=award)
 80        self.assertEqual(AwardNote.objects.count(), 1)
 81        person.delete()
 82        self.assertEqual(Award.objects.count(), 0)
 83        # first two asserts are just sanity checks, this is the kicker:
 84        self.assertEqual(AwardNote.objects.count(), 0)
 85
 86    def test_fk_to_m2m_through(self):
 87        """
 88        If an M2M relationship has an explicitly-specified through model, and
 89        some other model has an FK to that through model, deletion is cascaded
 90        from one of the participants in the M2M, to the through model, to its
 91        related model.
 92
 93        """
 94        juan = Child.objects.create(name='Juan')
 95        paints = Toy.objects.create(name='Paints')
 96        played = PlayedWith.objects.create(child=juan, toy=paints,
 97                                           date=datetime.date.today())
 98        note = PlayedWithNote.objects.create(played=played,
 99                                             note='the next Jackson Pollock')
100        self.assertEqual(PlayedWithNote.objects.count(), 1)
101        paints.delete()
102        self.assertEqual(PlayedWith.objects.count(), 0)
103        # first two asserts just sanity checks, this is the kicker:
104        self.assertEqual(PlayedWithNote.objects.count(), 0)
105
106    def test_15776(self):
107        policy = Policy.objects.create(pk=1, policy_number="1234")
108        version = Version.objects.create(policy=policy)
109        location = Location.objects.create(version=version)
110        item = Item.objects.create(version=version, location=location)
111        policy.delete()
112
113
114class DeleteCascadeTransactionTests(TransactionTestCase):
115    def test_inheritance(self):
116        """
117        Auto-created many-to-many through tables referencing a parent model are
118        correctly found by the delete cascade when a child of that parent is
119        deleted.
120
121        Refs #14896.
122        """
123        r = Researcher.objects.create()
124        email = Email.objects.create(
125            label="office-email", email_address="carl@science.edu"
126        )
127        r.contacts.add(email)
128
129        email.delete()
130
131    def test_to_field(self):
132        """
133        Cascade deletion works with ForeignKey.to_field set to non-PK.
134
135        """
136        apple = Food.objects.create(name="apple")
137        eaten = Eaten.objects.create(food=apple, meal="lunch")
138
139        apple.delete()
140
141class LargeDeleteTests(TestCase):
142    def test_large_deletes(self):
143        "Regression for #13309 -- if the number of objects > chunk size, deletion still occurs"
144        for x in range(300):
145            track = Book.objects.create(pagecount=x+100)
146        Book.objects.all().delete()
147        self.assertEqual(Book.objects.count(), 0)