|
4 | 4 |
|
5 | 5 | import sys |
6 | 6 | import time |
7 | | -from _thread import start_new_thread, get_ident |
| 7 | +from _thread import start_new_thread, get_ident, TIMEOUT_MAX |
8 | 8 | import threading |
9 | 9 | import unittest |
10 | 10 |
|
@@ -62,6 +62,14 @@ def tearDown(self): |
62 | 62 | support.threading_cleanup(*self._threads) |
63 | 63 | support.reap_children() |
64 | 64 |
|
| 65 | + def assertTimeout(self, actual, expected): |
| 66 | + # The waiting and/or time.time() can be imprecise, which |
| 67 | + # is why comparing to the expected value would sometimes fail |
| 68 | + # (especially under Windows). |
| 69 | + self.assertGreaterEqual(actual, expected * 0.6) |
| 70 | + # Test nothing insane happened |
| 71 | + self.assertLess(actual, expected * 10.0) |
| 72 | + |
65 | 73 |
|
66 | 74 | class BaseLockTests(BaseTestCase): |
67 | 75 | """ |
@@ -143,6 +151,32 @@ def f(): |
143 | 151 | Bunch(f, 15).wait_for_finished() |
144 | 152 | self.assertEqual(n, len(threading.enumerate())) |
145 | 153 |
|
| 154 | + def test_timeout(self): |
| 155 | + lock = self.locktype() |
| 156 | + # Can't set timeout if not blocking |
| 157 | + self.assertRaises(ValueError, lock.acquire, 0, 1) |
| 158 | + # Invalid timeout values |
| 159 | + self.assertRaises(ValueError, lock.acquire, timeout=-100) |
| 160 | + self.assertRaises(OverflowError, lock.acquire, timeout=1e100) |
| 161 | + self.assertRaises(OverflowError, lock.acquire, timeout=TIMEOUT_MAX + 1) |
| 162 | + # TIMEOUT_MAX is ok |
| 163 | + lock.acquire(timeout=TIMEOUT_MAX) |
| 164 | + lock.release() |
| 165 | + t1 = time.time() |
| 166 | + self.assertTrue(lock.acquire(timeout=5)) |
| 167 | + t2 = time.time() |
| 168 | + # Just a sanity test that it didn't actually wait for the timeout. |
| 169 | + self.assertLess(t2 - t1, 5) |
| 170 | + results = [] |
| 171 | + def f(): |
| 172 | + t1 = time.time() |
| 173 | + results.append(lock.acquire(timeout=0.5)) |
| 174 | + t2 = time.time() |
| 175 | + results.append(t2 - t1) |
| 176 | + Bunch(f, 1).wait_for_finished() |
| 177 | + self.assertFalse(results[0]) |
| 178 | + self.assertTimeout(results[1], 0.5) |
| 179 | + |
146 | 180 |
|
147 | 181 | class LockTests(BaseLockTests): |
148 | 182 | """ |
@@ -284,14 +318,14 @@ def test_timeout(self): |
284 | 318 | def f(): |
285 | 319 | results1.append(evt.wait(0.0)) |
286 | 320 | t1 = time.time() |
287 | | - r = evt.wait(0.2) |
| 321 | + r = evt.wait(0.5) |
288 | 322 | t2 = time.time() |
289 | 323 | results2.append((r, t2 - t1)) |
290 | 324 | Bunch(f, N).wait_for_finished() |
291 | 325 | self.assertEqual(results1, [False] * N) |
292 | 326 | for r, dt in results2: |
293 | 327 | self.assertFalse(r) |
294 | | - self.assertTrue(dt >= 0.2, dt) |
| 328 | + self.assertTimeout(dt, 0.5) |
295 | 329 | # The event is set |
296 | 330 | results1 = [] |
297 | 331 | results2 = [] |
@@ -397,14 +431,14 @@ def test_timeout(self): |
397 | 431 | def f(): |
398 | 432 | cond.acquire() |
399 | 433 | t1 = time.time() |
400 | | - cond.wait(0.2) |
| 434 | + cond.wait(0.5) |
401 | 435 | t2 = time.time() |
402 | 436 | cond.release() |
403 | 437 | results.append(t2 - t1) |
404 | 438 | Bunch(f, N).wait_for_finished() |
405 | 439 | self.assertEqual(len(results), 5) |
406 | 440 | for dt in results: |
407 | | - self.assertTrue(dt >= 0.2, dt) |
| 441 | + self.assertTimeout(dt, 0.5) |
408 | 442 |
|
409 | 443 |
|
410 | 444 | class BaseSemaphoreTests(BaseTestCase): |
|
0 commit comments