PageRenderTime 3085ms CodeModel.GetById 2583ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/modeltests/transactions/tests.py

https://code.google.com/p/mango-py/
Python | 185 lines | 153 code | 14 blank | 18 comment | 1 complexity | a5c8edcf9f1373675f6b75184c281079 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. import sys
  2. from django.db import connection, transaction, IntegrityError, DEFAULT_DB_ALIAS
  3. from django.conf import settings
  4. from django.test import TransactionTestCase, skipUnlessDBFeature
  5. from models import Reporter
  6. if sys.version_info >= (2, 5):
  7. from tests_25 import TransactionContextManagerTests
  8. class TransactionTests(TransactionTestCase):
  9. def create_a_reporter_then_fail(self, first, last):
  10. a = Reporter(first_name=first, last_name=last)
  11. a.save()
  12. raise Exception("I meant to do that")
  13. def remove_a_reporter(self, first_name):
  14. r = Reporter.objects.get(first_name="Alice")
  15. r.delete()
  16. def manually_managed(self):
  17. r = Reporter(first_name="Dirk", last_name="Gently")
  18. r.save()
  19. transaction.commit()
  20. def manually_managed_mistake(self):
  21. r = Reporter(first_name="Edward", last_name="Woodward")
  22. r.save()
  23. # Oops, I forgot to commit/rollback!
  24. @skipUnlessDBFeature('supports_transactions')
  25. def test_autocommit(self):
  26. """
  27. The default behavior is to autocommit after each save() action.
  28. """
  29. self.assertRaises(Exception,
  30. self.create_a_reporter_then_fail,
  31. "Alice", "Smith"
  32. )
  33. # The object created before the exception still exists
  34. self.assertEqual(Reporter.objects.count(), 1)
  35. @skipUnlessDBFeature('supports_transactions')
  36. def test_autocommit_decorator(self):
  37. """
  38. The autocommit decorator works exactly the same as the default behavior.
  39. """
  40. autocomitted_create_then_fail = transaction.autocommit(
  41. self.create_a_reporter_then_fail
  42. )
  43. self.assertRaises(Exception,
  44. autocomitted_create_then_fail,
  45. "Alice", "Smith"
  46. )
  47. # Again, the object created before the exception still exists
  48. self.assertEqual(Reporter.objects.count(), 1)
  49. @skipUnlessDBFeature('supports_transactions')
  50. def test_autocommit_decorator_with_using(self):
  51. """
  52. The autocommit decorator also works with a using argument.
  53. """
  54. autocomitted_create_then_fail = transaction.autocommit(using='default')(
  55. self.create_a_reporter_then_fail
  56. )
  57. self.assertRaises(Exception,
  58. autocomitted_create_then_fail,
  59. "Alice", "Smith"
  60. )
  61. # Again, the object created before the exception still exists
  62. self.assertEqual(Reporter.objects.count(), 1)
  63. @skipUnlessDBFeature('supports_transactions')
  64. def test_commit_on_success(self):
  65. """
  66. With the commit_on_success decorator, the transaction is only committed
  67. if the function doesn't throw an exception.
  68. """
  69. committed_on_success = transaction.commit_on_success(
  70. self.create_a_reporter_then_fail)
  71. self.assertRaises(Exception, committed_on_success, "Dirk", "Gently")
  72. # This time the object never got saved
  73. self.assertEqual(Reporter.objects.count(), 0)
  74. @skipUnlessDBFeature('supports_transactions')
  75. def test_commit_on_success_with_using(self):
  76. """
  77. The commit_on_success decorator also works with a using argument.
  78. """
  79. using_committed_on_success = transaction.commit_on_success(using='default')(
  80. self.create_a_reporter_then_fail
  81. )
  82. self.assertRaises(Exception,
  83. using_committed_on_success,
  84. "Dirk", "Gently"
  85. )
  86. # This time the object never got saved
  87. self.assertEqual(Reporter.objects.count(), 0)
  88. @skipUnlessDBFeature('supports_transactions')
  89. def test_commit_on_success_succeed(self):
  90. """
  91. If there aren't any exceptions, the data will get saved.
  92. """
  93. Reporter.objects.create(first_name="Alice", last_name="Smith")
  94. remove_comitted_on_success = transaction.commit_on_success(
  95. self.remove_a_reporter
  96. )
  97. remove_comitted_on_success("Alice")
  98. self.assertEqual(list(Reporter.objects.all()), [])
  99. @skipUnlessDBFeature('supports_transactions')
  100. def test_commit_on_success_exit(self):
  101. @transaction.autocommit()
  102. def gen_reporter():
  103. @transaction.commit_on_success
  104. def create_reporter():
  105. Reporter.objects.create(first_name="Bobby", last_name="Tables")
  106. create_reporter()
  107. # Much more formal
  108. r = Reporter.objects.get()
  109. r.first_name = "Robert"
  110. r.save()
  111. gen_reporter()
  112. r = Reporter.objects.get()
  113. self.assertEqual(r.first_name, "Robert")
  114. @skipUnlessDBFeature('supports_transactions')
  115. def test_manually_managed(self):
  116. """
  117. You can manually manage transactions if you really want to, but you
  118. have to remember to commit/rollback.
  119. """
  120. manually_managed = transaction.commit_manually(self.manually_managed)
  121. manually_managed()
  122. self.assertEqual(Reporter.objects.count(), 1)
  123. @skipUnlessDBFeature('supports_transactions')
  124. def test_manually_managed_mistake(self):
  125. """
  126. If you forget, you'll get bad errors.
  127. """
  128. manually_managed_mistake = transaction.commit_manually(
  129. self.manually_managed_mistake
  130. )
  131. self.assertRaises(transaction.TransactionManagementError,
  132. manually_managed_mistake)
  133. @skipUnlessDBFeature('supports_transactions')
  134. def test_manually_managed_with_using(self):
  135. """
  136. The commit_manually function also works with a using argument.
  137. """
  138. using_manually_managed_mistake = transaction.commit_manually(using='default')(
  139. self.manually_managed_mistake
  140. )
  141. self.assertRaises(transaction.TransactionManagementError,
  142. using_manually_managed_mistake
  143. )
  144. class TransactionRollbackTests(TransactionTestCase):
  145. def execute_bad_sql(self):
  146. cursor = connection.cursor()
  147. cursor.execute("INSERT INTO transactions_reporter (first_name, last_name) VALUES ('Douglas', 'Adams');")
  148. transaction.set_dirty()
  149. @skipUnlessDBFeature('requires_rollback_on_dirty_transaction')
  150. def test_bad_sql(self):
  151. """
  152. Regression for #11900: If a function wrapped by commit_on_success
  153. writes a transaction that can't be committed, that transaction should
  154. be rolled back. The bug is only visible using the psycopg2 backend,
  155. though the fix is generally a good idea.
  156. """
  157. execute_bad_sql = transaction.commit_on_success(self.execute_bad_sql)
  158. self.assertRaises(IntegrityError, execute_bad_sql)
  159. transaction.rollback()