PageRenderTime 193ms CodeModel.GetById 181ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/regressiontests/transactions_regress/tests.py

https://code.google.com/p/mango-py/
Python | 164 lines | 153 code | 3 blank | 8 comment | 7 complexity | 4e771ba9e4ad4a5593773df81c60fbeb MD5 | raw file
  1from django.core.exceptions import ImproperlyConfigured
  2from django.db import connection, transaction
  3from django.db.transaction import commit_on_success, commit_manually, TransactionManagementError
  4from django.test import TransactionTestCase, skipUnlessDBFeature
  5
  6from models import Mod
  7
  8
  9class TestTransactionClosing(TransactionTestCase):
 10    """
 11    Tests to make sure that transactions are properly closed
 12    when they should be, and aren't left pending after operations
 13    have been performed in them. Refs #9964.
 14    """
 15    def test_raw_committed_on_success(self):
 16        """
 17        Make sure a transaction consisting of raw SQL execution gets
 18        committed by the commit_on_success decorator.
 19        """
 20        @commit_on_success
 21        def raw_sql():
 22            "Write a record using raw sql under a commit_on_success decorator"
 23            cursor = connection.cursor()
 24            cursor.execute("INSERT into transactions_regress_mod (id,fld) values (17,18)")
 25
 26        raw_sql()
 27        # Rollback so that if the decorator didn't commit, the record is unwritten
 28        transaction.rollback()
 29        try:
 30            # Check that the record is in the DB
 31            obj = Mod.objects.get(pk=17)
 32            self.assertEqual(obj.fld, 18)
 33        except Mod.DoesNotExist:
 34            self.fail("transaction with raw sql not committed")
 35
 36    def test_commit_manually_enforced(self):
 37        """
 38        Make sure that under commit_manually, even "read-only" transaction require closure
 39        (commit or rollback), and a transaction left pending is treated as an error.
 40        """
 41        @commit_manually
 42        def non_comitter():
 43            "Execute a managed transaction with read-only operations and fail to commit"
 44            _ = Mod.objects.count()
 45
 46        self.assertRaises(TransactionManagementError, non_comitter)
 47
 48    def test_commit_manually_commit_ok(self):
 49        """
 50        Test that under commit_manually, a committed transaction is accepted by the transaction
 51        management mechanisms
 52        """
 53        @commit_manually
 54        def committer():
 55            """
 56            Perform a database query, then commit the transaction
 57            """
 58            _ = Mod.objects.count()
 59            transaction.commit()
 60
 61        try:
 62            committer()
 63        except TransactionManagementError:
 64            self.fail("Commit did not clear the transaction state")
 65
 66    def test_commit_manually_rollback_ok(self):
 67        """
 68        Test that under commit_manually, a rolled-back transaction is accepted by the transaction
 69        management mechanisms
 70        """
 71        @commit_manually
 72        def roller_back():
 73            """
 74            Perform a database query, then rollback the transaction
 75            """
 76            _ = Mod.objects.count()
 77            transaction.rollback()
 78
 79        try:
 80            roller_back()
 81        except TransactionManagementError:
 82            self.fail("Rollback did not clear the transaction state")
 83
 84    def test_commit_manually_enforced_after_commit(self):
 85        """
 86        Test that under commit_manually, if a transaction is committed and an operation is
 87        performed later, we still require the new transaction to be closed
 88        """
 89        @commit_manually
 90        def fake_committer():
 91            "Query, commit, then query again, leaving with a pending transaction"
 92            _ = Mod.objects.count()
 93            transaction.commit()
 94            _ = Mod.objects.count()
 95
 96        self.assertRaises(TransactionManagementError, fake_committer)
 97
 98    @skipUnlessDBFeature('supports_transactions')
 99    def test_reuse_cursor_reference(self):
100        """
101        Make sure transaction closure is enforced even when the queries are performed
102        through a single cursor reference retrieved in the beginning
103        (this is to show why it is wrong to set the transaction dirty only when a cursor
104        is fetched from the connection).
105        """
106        @commit_on_success
107        def reuse_cursor_ref():
108            """
109            Fetch a cursor, perform an query, rollback to close the transaction,
110            then write a record (in a new transaction) using the same cursor object
111            (reference). All this under commit_on_success, so the second insert should
112            be committed.
113            """
114            cursor = connection.cursor()
115            cursor.execute("INSERT into transactions_regress_mod (id,fld) values (1,2)")
116            transaction.rollback()
117            cursor.execute("INSERT into transactions_regress_mod (id,fld) values (1,2)")
118
119        reuse_cursor_ref()
120        # Rollback so that if the decorator didn't commit, the record is unwritten
121        transaction.rollback()
122        try:
123            # Check that the record is in the DB
124            obj = Mod.objects.get(pk=1)
125            self.assertEqual(obj.fld, 2)
126        except Mod.DoesNotExist:
127            self.fail("After ending a transaction, cursor use no longer sets dirty")
128
129    def test_failing_query_transaction_closed(self):
130        """
131        Make sure that under commit_on_success, a transaction is rolled back even if
132        the first database-modifying operation fails.
133        This is prompted by http://code.djangoproject.com/ticket/6669 (and based on sample
134        code posted there to exemplify the problem): Before Django 1.3,
135        transactions were only marked "dirty" by the save() function after it successfully
136        wrote the object to the database.
137        """
138        from django.contrib.auth.models import User
139
140        @transaction.commit_on_success
141        def create_system_user():
142            "Create a user in a transaction"
143            user = User.objects.create_user(username='system', password='iamr00t', email='root@SITENAME.com')
144            # Redundant, just makes sure the user id was read back from DB
145            Mod.objects.create(fld=user.id)
146
147        # Create a user
148        create_system_user()
149
150        try:
151            # The second call to create_system_user should fail for violating a unique constraint
152            # (it's trying to re-create the same user)
153            create_system_user()
154        except:
155            pass
156        else:
157            raise ImproperlyConfigured('Unique constraint not enforced on django.contrib.auth.models.User')
158
159        try:
160            # Try to read the database. If the last transaction was indeed closed,
161            # this should cause no problems
162            _ = User.objects.all()[0]
163        except:
164            self.fail("A transaction consisting of a failed operation was not closed.")