| 
									
										
										
										
											2014-05-16 11:40:40 -06:00
										 |  |  | from . import util as test_util | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | init = test_util.import_importlib('importlib') | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-28 20:10:18 +02:00
										 |  |  | import sys | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | import time | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | import weakref | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from test import support | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     import threading | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     threading = None | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     from test import lock_tests | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if threading is not None: | 
					
						
							| 
									
										
										
										
											2013-10-18 16:55:15 -04:00
										 |  |  |     class ModuleLockAsRLockTests: | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  |         locktype = classmethod(lambda cls: cls.LockType("some_lock")) | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # _is_owned() unsupported | 
					
						
							|  |  |  |         test__is_owned = None | 
					
						
							|  |  |  |         # acquire(blocking=False) unsupported | 
					
						
							|  |  |  |         test_try_acquire = None | 
					
						
							|  |  |  |         test_try_acquire_contended = None | 
					
						
							|  |  |  |         # `with` unsupported | 
					
						
							|  |  |  |         test_with = None | 
					
						
							|  |  |  |         # acquire(timeout=...) unsupported | 
					
						
							|  |  |  |         test_timeout = None | 
					
						
							|  |  |  |         # _release_save() unsupported | 
					
						
							|  |  |  |         test_release_save_unacquired = None | 
					
						
							| 
									
										
										
										
											2014-05-25 18:22:35 -07:00
										 |  |  |         # lock status in repr unsupported | 
					
						
							|  |  |  |         test_repr = None | 
					
						
							|  |  |  |         test_locked_repr = None | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-16 11:40:40 -06:00
										 |  |  |     LOCK_TYPES = {kind: splitinit._bootstrap._ModuleLock | 
					
						
							|  |  |  |                   for kind, splitinit in init.items()} | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-16 11:40:40 -06:00
										 |  |  |     (Frozen_ModuleLockAsRLockTests, | 
					
						
							|  |  |  |      Source_ModuleLockAsRLockTests | 
					
						
							|  |  |  |      ) = test_util.test_both(ModuleLockAsRLockTests, lock_tests.RLockTests, | 
					
						
							|  |  |  |                              LockType=LOCK_TYPES) | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | else: | 
					
						
							| 
									
										
										
										
											2014-05-16 11:40:40 -06:00
										 |  |  |     LOCK_TYPES = {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  |     class Frozen_ModuleLockAsRLockTests(unittest.TestCase): | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  |     class Source_ModuleLockAsRLockTests(unittest.TestCase): | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-03 06:25:10 +03:00
										 |  |  | if threading is not None: | 
					
						
							|  |  |  |     class DeadlockAvoidanceTests: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def setUp(self): | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2014-07-03 06:25:10 +03:00
										 |  |  |                 self.old_switchinterval = sys.getswitchinterval() | 
					
						
							|  |  |  |                 sys.setswitchinterval(0.000001) | 
					
						
							|  |  |  |             except AttributeError: | 
					
						
							|  |  |  |                 self.old_switchinterval = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def tearDown(self): | 
					
						
							|  |  |  |             if self.old_switchinterval is not None: | 
					
						
							|  |  |  |                 sys.setswitchinterval(self.old_switchinterval) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def run_deadlock_avoidance_test(self, create_deadlock): | 
					
						
							|  |  |  |             NLOCKS = 10 | 
					
						
							|  |  |  |             locks = [self.LockType(str(i)) for i in range(NLOCKS)] | 
					
						
							|  |  |  |             pairs = [(locks[i], locks[(i+1)%NLOCKS]) for i in range(NLOCKS)] | 
					
						
							|  |  |  |             if create_deadlock: | 
					
						
							|  |  |  |                 NTHREADS = NLOCKS | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2014-07-03 06:25:10 +03:00
										 |  |  |                 NTHREADS = NLOCKS - 1 | 
					
						
							|  |  |  |             barrier = threading.Barrier(NTHREADS) | 
					
						
							|  |  |  |             results = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             def _acquire(lock): | 
					
						
							|  |  |  |                 """Try to acquire the lock. Return True on success,
 | 
					
						
							|  |  |  |                 False on deadlock."""
 | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     lock.acquire() | 
					
						
							|  |  |  |                 except self.DeadlockError: | 
					
						
							|  |  |  |                     return False | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             def f(): | 
					
						
							|  |  |  |                 a, b = pairs.pop() | 
					
						
							|  |  |  |                 ra = _acquire(a) | 
					
						
							|  |  |  |                 barrier.wait() | 
					
						
							|  |  |  |                 rb = _acquire(b) | 
					
						
							|  |  |  |                 results.append((ra, rb)) | 
					
						
							|  |  |  |                 if rb: | 
					
						
							|  |  |  |                     b.release() | 
					
						
							|  |  |  |                 if ra: | 
					
						
							|  |  |  |                     a.release() | 
					
						
							|  |  |  |             lock_tests.Bunch(f, NTHREADS).wait_for_finished() | 
					
						
							|  |  |  |             self.assertEqual(len(results), NTHREADS) | 
					
						
							|  |  |  |             return results | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def test_deadlock(self): | 
					
						
							|  |  |  |             results = self.run_deadlock_avoidance_test(True) | 
					
						
							|  |  |  |             # At least one of the threads detected a potential deadlock on its | 
					
						
							|  |  |  |             # second acquire() call.  It may be several of them, because the | 
					
						
							|  |  |  |             # deadlock avoidance mechanism is conservative. | 
					
						
							|  |  |  |             nb_deadlocks = results.count((True, False)) | 
					
						
							|  |  |  |             self.assertGreaterEqual(nb_deadlocks, 1) | 
					
						
							|  |  |  |             self.assertEqual(results.count((True, True)), len(results) - nb_deadlocks) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def test_no_deadlock(self): | 
					
						
							|  |  |  |             results = self.run_deadlock_avoidance_test(False) | 
					
						
							|  |  |  |             self.assertEqual(results.count((True, False)), 0) | 
					
						
							|  |  |  |             self.assertEqual(results.count((True, True)), len(results)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DEADLOCK_ERRORS = {kind: splitinit._bootstrap._DeadlockError | 
					
						
							|  |  |  |                        for kind, splitinit in init.items()} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     (Frozen_DeadlockAvoidanceTests, | 
					
						
							|  |  |  |      Source_DeadlockAvoidanceTests | 
					
						
							|  |  |  |      ) = test_util.test_both(DeadlockAvoidanceTests, | 
					
						
							|  |  |  |                              LockType=LOCK_TYPES, | 
					
						
							|  |  |  |                              DeadlockError=DEADLOCK_ERRORS) | 
					
						
							|  |  |  | else: | 
					
						
							|  |  |  |     DEADLOCK_ERRORS = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class Frozen_DeadlockAvoidanceTests(unittest.TestCase): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class Source_DeadlockAvoidanceTests(unittest.TestCase): | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | class LifetimeTests: | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-16 11:40:40 -06:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def bootstrap(self): | 
					
						
							|  |  |  |         return self.init._bootstrap | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  |     def test_lock_lifetime(self): | 
					
						
							|  |  |  |         name = "xyzzy" | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  |         self.assertNotIn(name, self.bootstrap._module_locks) | 
					
						
							|  |  |  |         lock = self.bootstrap._get_module_lock(name) | 
					
						
							|  |  |  |         self.assertIn(name, self.bootstrap._module_locks) | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  |         wr = weakref.ref(lock) | 
					
						
							|  |  |  |         del lock | 
					
						
							|  |  |  |         support.gc_collect() | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  |         self.assertNotIn(name, self.bootstrap._module_locks) | 
					
						
							| 
									
										
										
										
											2012-06-28 06:15:01 -04:00
										 |  |  |         self.assertIsNone(wr()) | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_all_locks(self): | 
					
						
							|  |  |  |         support.gc_collect() | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  |         self.assertEqual(0, len(self.bootstrap._module_locks), | 
					
						
							|  |  |  |                          self.bootstrap._module_locks) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-16 11:40:40 -06:00
										 |  |  | (Frozen_LifetimeTests, | 
					
						
							|  |  |  |  Source_LifetimeTests | 
					
						
							|  |  |  |  ) = test_util.test_both(LifetimeTests, init=init) | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @support.reap_threads | 
					
						
							|  |  |  | def test_main(): | 
					
						
							| 
									
										
										
										
											2013-10-18 15:12:21 -04:00
										 |  |  |     support.run_unittest(Frozen_ModuleLockAsRLockTests, | 
					
						
							|  |  |  |                          Source_ModuleLockAsRLockTests, | 
					
						
							|  |  |  |                          Frozen_DeadlockAvoidanceTests, | 
					
						
							|  |  |  |                          Source_DeadlockAvoidanceTests, | 
					
						
							|  |  |  |                          Frozen_LifetimeTests, | 
					
						
							|  |  |  |                          Source_LifetimeTests) | 
					
						
							| 
									
										
										
										
											2012-05-17 18:55:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     test_main() |