blob: df0af12d3886d65f152ddb65a01d8036af531f74 [file] [log] [blame]
Eric Snow3497c0b2014-05-16 11:40:40 -06001from . import util as test_util
2
3init = test_util.import_importlib('importlib')
Brett Cannon6a57dd82013-10-18 15:12:21 -04004
Antoine Pitrou5b9eccb2012-08-28 20:10:18 +02005import sys
Antoine Pitrouea3eb882012-05-17 18:55:59 +02006import time
7import unittest
8import weakref
9
10from test import support
11
12try:
13 import threading
14except ImportError:
15 threading = None
16else:
17 from test import lock_tests
18
Antoine Pitrouea3eb882012-05-17 18:55:59 +020019if threading is not None:
Brett Cannonc5168152013-10-18 16:55:15 -040020 class ModuleLockAsRLockTests:
Brett Cannon6a57dd82013-10-18 15:12:21 -040021 locktype = classmethod(lambda cls: cls.LockType("some_lock"))
Antoine Pitrouea3eb882012-05-17 18:55:59 +020022
23 # _is_owned() unsupported
24 test__is_owned = None
25 # acquire(blocking=False) unsupported
26 test_try_acquire = None
27 test_try_acquire_contended = None
28 # `with` unsupported
29 test_with = None
30 # acquire(timeout=...) unsupported
31 test_timeout = None
32 # _release_save() unsupported
33 test_release_save_unacquired = None
Raymond Hettinger62f4dad2014-05-25 18:22:35 -070034 # lock status in repr unsupported
35 test_repr = None
36 test_locked_repr = None
Antoine Pitrouea3eb882012-05-17 18:55:59 +020037
Eric Snow3497c0b2014-05-16 11:40:40 -060038 LOCK_TYPES = {kind: splitinit._bootstrap._ModuleLock
39 for kind, splitinit in init.items()}
Brett Cannon6a57dd82013-10-18 15:12:21 -040040
Eric Snow3497c0b2014-05-16 11:40:40 -060041 (Frozen_ModuleLockAsRLockTests,
42 Source_ModuleLockAsRLockTests
43 ) = test_util.test_both(ModuleLockAsRLockTests, lock_tests.RLockTests,
44 LockType=LOCK_TYPES)
Antoine Pitrouea3eb882012-05-17 18:55:59 +020045else:
Eric Snow3497c0b2014-05-16 11:40:40 -060046 LOCK_TYPES = {}
47
Brett Cannon6a57dd82013-10-18 15:12:21 -040048 class Frozen_ModuleLockAsRLockTests(unittest.TestCase):
49 pass
50
51 class Source_ModuleLockAsRLockTests(unittest.TestCase):
Antoine Pitrouea3eb882012-05-17 18:55:59 +020052 pass
53
54
Berker Peksagf7eaa0c2014-07-03 06:25:10 +030055if threading is not None:
56 class DeadlockAvoidanceTests:
Antoine Pitrouea3eb882012-05-17 18:55:59 +020057
Berker Peksagf7eaa0c2014-07-03 06:25:10 +030058 def setUp(self):
Antoine Pitrouea3eb882012-05-17 18:55:59 +020059 try:
Berker Peksagf7eaa0c2014-07-03 06:25:10 +030060 self.old_switchinterval = sys.getswitchinterval()
61 sys.setswitchinterval(0.000001)
62 except AttributeError:
63 self.old_switchinterval = None
64
65 def tearDown(self):
66 if self.old_switchinterval is not None:
67 sys.setswitchinterval(self.old_switchinterval)
68
69 def run_deadlock_avoidance_test(self, create_deadlock):
70 NLOCKS = 10
71 locks = [self.LockType(str(i)) for i in range(NLOCKS)]
72 pairs = [(locks[i], locks[(i+1)%NLOCKS]) for i in range(NLOCKS)]
73 if create_deadlock:
74 NTHREADS = NLOCKS
Antoine Pitrouea3eb882012-05-17 18:55:59 +020075 else:
Berker Peksagf7eaa0c2014-07-03 06:25:10 +030076 NTHREADS = NLOCKS - 1
77 barrier = threading.Barrier(NTHREADS)
78 results = []
Antoine Pitrouea3eb882012-05-17 18:55:59 +020079
Berker Peksagf7eaa0c2014-07-03 06:25:10 +030080 def _acquire(lock):
81 """Try to acquire the lock. Return True on success,
82 False on deadlock."""
83 try:
84 lock.acquire()
85 except self.DeadlockError:
86 return False
87 else:
88 return True
Antoine Pitrouea3eb882012-05-17 18:55:59 +020089
Berker Peksagf7eaa0c2014-07-03 06:25:10 +030090 def f():
91 a, b = pairs.pop()
92 ra = _acquire(a)
93 barrier.wait()
94 rb = _acquire(b)
95 results.append((ra, rb))
96 if rb:
97 b.release()
98 if ra:
99 a.release()
100 lock_tests.Bunch(f, NTHREADS).wait_for_finished()
101 self.assertEqual(len(results), NTHREADS)
102 return results
103
104 def test_deadlock(self):
105 results = self.run_deadlock_avoidance_test(True)
106 # At least one of the threads detected a potential deadlock on its
107 # second acquire() call. It may be several of them, because the
108 # deadlock avoidance mechanism is conservative.
109 nb_deadlocks = results.count((True, False))
110 self.assertGreaterEqual(nb_deadlocks, 1)
111 self.assertEqual(results.count((True, True)), len(results) - nb_deadlocks)
112
113 def test_no_deadlock(self):
114 results = self.run_deadlock_avoidance_test(False)
115 self.assertEqual(results.count((True, False)), 0)
116 self.assertEqual(results.count((True, True)), len(results))
Antoine Pitrouea3eb882012-05-17 18:55:59 +0200117
118
Berker Peksagf7eaa0c2014-07-03 06:25:10 +0300119 DEADLOCK_ERRORS = {kind: splitinit._bootstrap._DeadlockError
120 for kind, splitinit in init.items()}
Eric Snow3497c0b2014-05-16 11:40:40 -0600121
Berker Peksagf7eaa0c2014-07-03 06:25:10 +0300122 (Frozen_DeadlockAvoidanceTests,
123 Source_DeadlockAvoidanceTests
124 ) = test_util.test_both(DeadlockAvoidanceTests,
125 LockType=LOCK_TYPES,
126 DeadlockError=DEADLOCK_ERRORS)
127else:
128 DEADLOCK_ERRORS = {}
129
130 class Frozen_DeadlockAvoidanceTests(unittest.TestCase):
131 pass
132
133 class Source_DeadlockAvoidanceTests(unittest.TestCase):
134 pass
Brett Cannon6a57dd82013-10-18 15:12:21 -0400135
136
137class LifetimeTests:
Antoine Pitrouea3eb882012-05-17 18:55:59 +0200138
Eric Snow3497c0b2014-05-16 11:40:40 -0600139 @property
140 def bootstrap(self):
141 return self.init._bootstrap
142
Antoine Pitrouea3eb882012-05-17 18:55:59 +0200143 def test_lock_lifetime(self):
144 name = "xyzzy"
Brett Cannon6a57dd82013-10-18 15:12:21 -0400145 self.assertNotIn(name, self.bootstrap._module_locks)
146 lock = self.bootstrap._get_module_lock(name)
147 self.assertIn(name, self.bootstrap._module_locks)
Antoine Pitrouea3eb882012-05-17 18:55:59 +0200148 wr = weakref.ref(lock)
149 del lock
150 support.gc_collect()
Brett Cannon6a57dd82013-10-18 15:12:21 -0400151 self.assertNotIn(name, self.bootstrap._module_locks)
Eric V. Smithb1095152012-06-28 06:15:01 -0400152 self.assertIsNone(wr())
Antoine Pitrouea3eb882012-05-17 18:55:59 +0200153
154 def test_all_locks(self):
155 support.gc_collect()
Brett Cannon6a57dd82013-10-18 15:12:21 -0400156 self.assertEqual(0, len(self.bootstrap._module_locks),
157 self.bootstrap._module_locks)
158
Brett Cannon6a57dd82013-10-18 15:12:21 -0400159
Eric Snow3497c0b2014-05-16 11:40:40 -0600160(Frozen_LifetimeTests,
161 Source_LifetimeTests
162 ) = test_util.test_both(LifetimeTests, init=init)
Antoine Pitrouea3eb882012-05-17 18:55:59 +0200163
164
165@support.reap_threads
166def test_main():
Brett Cannon6a57dd82013-10-18 15:12:21 -0400167 support.run_unittest(Frozen_ModuleLockAsRLockTests,
168 Source_ModuleLockAsRLockTests,
169 Frozen_DeadlockAvoidanceTests,
170 Source_DeadlockAvoidanceTests,
171 Frozen_LifetimeTests,
172 Source_LifetimeTests)
Antoine Pitrouea3eb882012-05-17 18:55:59 +0200173
174
175if __name__ == '__main__':
176 test_main()