Ticket #10868: 10868.diff
File 10868.diff, 6.4 KB (added by , 13 years ago) |
---|
-
django/test/simple.py
diff --git a/django/test/simple.py b/django/test/simple.py index c9adfd2..7e722cd 100644
a b 1 import threading 1 2 import unittest as real_unittest 2 3 3 4 from django.conf import settings … … class DjangoTestSuiteRunner(object): 252 253 return reorder_suite(suite, (TestCase,)) 253 254 254 255 def setup_databases(self, **kwargs): 256 # Record existing threads, so that we can check for threads created 257 # during testing before tearing down databases. See #10868. 258 self._record_threads() 255 259 from django.db import connections, DEFAULT_DB_ALIAS 256 260 257 261 # First pass -- work out which databases actually need to be created, … … class DjangoTestSuiteRunner(object): 311 315 return unittest.TextTestRunner(verbosity=self.verbosity, failfast=self.failfast).run(suite) 312 316 313 317 def teardown_databases(self, old_config, **kwargs): 318 # Check that there are no alive threads left behind from the tests. 319 # If these would sprung to life, they would access the production DB. 320 # see #10868. 321 self._check_alive_threads() 314 322 from django.db import connections 315 323 old_names, mirrors = old_config 316 324 # Point all the mirrors back to the originals … … class DjangoTestSuiteRunner(object): 356 364 self.teardown_databases(old_config) 357 365 self.teardown_test_environment() 358 366 return self.suite_result(suite, result) 367 368 def _get_thread_ident(self, thread): 369 """ 370 Get an identifier for the given thread. 371 372 Python 2.5 doesn't have thread.ident, so use thread.name if ident 373 doesn't exists. 374 """ 375 try: 376 return thread.ident 377 except AttributeError: 378 return thread.name 379 380 def _check_alive_threads(self): 381 for thread in threading.enumerate(): 382 if self._get_thread_ident(thread) not in self._pre_test_threads: 383 thread.join(timeout=1.0) 384 if thread.is_alive(): 385 raise RuntimeError( 386 "Thread (name=%s) still alive after tests.", 387 thread.name) 388 389 def _record_threads(self): 390 self._pre_test_threads = set() 391 for thread in threading.enumerate(): 392 self._pre_test_threads.add(self._get_thread_ident(thread)) -
docs/releases/1.4.txt
diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index f614dee..c4d8442 100644
a b useful, it was removed in Django 1.4. If you relied on it, you must edit your 995 995 settings file to list all your applications explicitly. 996 996 997 997 .. _this can't be done reliably: http://docs.python.org/tutorial/modules.html#importing-from-a-package 998 999 Threads created during testing must be also closed during testing 1000 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1001 1002 To make sure test threads will not access the production database (or 1003 otherwise create havoc after tests) Django now enforces that threads created 1004 during testing must not be alive after the tests have ran. -
tests/regressiontests/test_runner/tests.py
diff --git a/tests/regressiontests/test_runner/tests.py b/tests/regressiontests/test_runner/tests.py index 4e2555e..4dd04f4 100644
a b from __future__ import absolute_import 5 5 6 6 import StringIO 7 7 from optparse import make_option 8 import time 9 from threading import Thread 8 10 import warnings 9 11 10 12 from django.core.exceptions import ImproperlyConfigured 11 13 from django.core.management import call_command 12 14 from django.test import simple 13 15 from django.test.simple import get_tests 14 from django.test.utils import get_warnings_state, restore_warnings_state 16 from django.test.utils import (get_warnings_state, restore_warnings_state, 17 override_settings) 15 18 from django.utils import unittest 16 19 from django.utils.importlib import import_module 17 20 … … class ModulesTestsPackages(unittest.TestCase): 225 228 "Test for #12658 - Tests with ImportError's shouldn't fail silently" 226 229 module = import_module(TEST_APP_ERROR) 227 230 self.assertRaises(ImportError, get_tests, module) 231 232 class Condition(object): 233 def __init__(self): 234 self._break = False 235 236 def waiter_thread(condition): 237 while True: 238 if condition._break: 239 break 240 time.sleep(0.1) 241 242 243 class ThreadsTest(unittest.TestCase): 244 """ 245 Test that all threads created while running the tests are gone before 246 tearing down the testing databases. Refs: #10868. 247 248 The tests target _record_threads and _check_alive_threds, because actually 249 running teardown_databases seems a little problematic. 250 """ 251 def test_threads_left_alive(self): 252 """ 253 Check that there is an error if there are threads left alive after tests. 254 """ 255 dj = simple.DjangoTestSuiteRunner() 256 dj._record_threads() 257 condition = Condition() 258 t = Thread(target=waiter_thread, args=(condition,)) 259 t.start() 260 with self.assertRaises(RuntimeError): 261 dj._check_alive_threads() 262 condition._break = True 263 t.join() 264 265 def test_threads_created_before(self): 266 """ 267 Check that threads started before testing are allowed to exist also 268 after tests. 269 """ 270 condition = Condition() 271 t = Thread(target=waiter_thread, args=(condition,)) 272 t.start() 273 dj = simple.DjangoTestSuiteRunner() 274 dj._record_threads() 275 try: 276 dj._check_alive_threads() 277 except RuntimeError: 278 self.assertFalse(True) # Should not raise this error! 279 condition._break = True 280 t.join() 281 282 def test_threads_mixed(self): 283 """ 284 Check that if there are threads created before tests, and threads left 285 alive during testing, there is an error. 286 """ 287 condition1 = Condition() 288 condition2 = Condition() 289 t1 = Thread(target=waiter_thread, args=(condition1,)) 290 t1.start() 291 dj = simple.DjangoTestSuiteRunner() 292 dj._record_threads() 293 t2 = Thread(target=waiter_thread, args=(condition2,)) 294 t2.start() 295 with self.assertRaises(RuntimeError): 296 dj._check_alive_threads() 297 condition1._break = True 298 condition2._break = True 299 t1.join() 300 t2.join()