Skip to content

Commit

Permalink
Fixed #25176 -- Prevented TestCase.setUpTestData() exception from lea…
Browse files Browse the repository at this point in the history
…king transaction.
  • Loading branch information
Adam Chainz authored and timgraham committed Aug 1, 2015
1 parent f4afa69 commit 0abb069
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 1 deletion.
6 changes: 5 additions & 1 deletion django/test/testcases.py
Original file line number Diff line number Diff line change
Expand Up @@ -1017,7 +1017,11 @@ def setUpClass(cls):
except Exception:
cls._rollback_atomics(cls.cls_atomics)
raise
cls.setUpTestData()
try:
cls.setUpTestData()
except Exception:
cls._rollback_atomics(cls.cls_atomics)
raise

@classmethod
def tearDownClass(cls):
Expand Down
3 changes: 3 additions & 0 deletions docs/releases/1.8.4.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ Bugfixes
* Fixed ``QuerySet.raw()`` so ``InvalidQuery`` is not raised when using the
``db_column`` name of a ``ForeignKey`` field with ``primary_key=True``
(:ticket:`12768`).

* Prevented an exception in ``TestCase.setUpTestData()`` from leaking the
transaction (:ticket:`25176`).
33 changes: 33 additions & 0 deletions tests/test_utils/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,39 @@ def test_override_staticfiles_dirs(self):
self.assertIn(expected_location, finder.locations)


class TestBadSetUpTestData(TestCase):
"""
An exception in setUpTestData() shouldn't leak a transaction which would
cascade across the rest of the test suite.
"""
class MyException(Exception):
pass

@classmethod
def setUpClass(cls):
try:
super(TestBadSetupTestData, cls).setUpClass()
except cls.MyException:
cls._in_atomic_block = connection.in_atomic_block

@classmethod
def tearDownClass(Cls):
# override to avoid a second cls._rollback_atomics() which would fail.
# Normal setUpClass() methods won't have exception handling so this
# method wouldn't typically be run.
pass

@classmethod
def setUpTestData(cls):
# Simulate a broken setUpTestData() method.
raise cls.MyException()

def test_failure_in_setUpTestData_should_rollback_transaction(self):
# setUpTestData() should call _rollback_atomics() so that the
# transaction doesn't leak.
self.assertFalse(self._in_atomic_block)


class DisallowedDatabaseQueriesTests(SimpleTestCase):
def test_disallowed_database_queries(self):
expected_message = (
Expand Down

0 comments on commit 0abb069

Please sign in to comment.