diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2013-01-08 22:13:38 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2013-01-08 22:13:38 (GMT) |
commit | 369a7822d68b6b3949587127565e693acc8e7277 (patch) | |
tree | bb1148064b360ffb439e7ea1cce1dce322ed84e3 /Lib | |
parent | ae3b32ad6bd6326e14b4b4316af6edea8dfc9173 (diff) | |
download | cpython-369a7822d68b6b3949587127565e693acc8e7277.zip cpython-369a7822d68b6b3949587127565e693acc8e7277.tar.gz cpython-369a7822d68b6b3949587127565e693acc8e7277.tar.bz2 |
Issue #16843: Make concurrent tests for sched module deterministic.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_sched.py | 106 |
1 files changed, 85 insertions, 21 deletions
diff --git a/Lib/test/test_sched.py b/Lib/test/test_sched.py index d0112e4..1fe6ad4 100644 --- a/Lib/test/test_sched.py +++ b/Lib/test/test_sched.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +import queue import sched import time import unittest @@ -9,6 +10,37 @@ try: except ImportError: threading = None +TIMEOUT = 10 + + +class Timer: + def __init__(self): + self._cond = threading.Condition() + self._time = 0 + self._stop = 0 + + def time(self): + with self._cond: + return self._time + + # increase the time but not beyond the established limit + def sleep(self, t): + assert t >= 0 + with self._cond: + t += self._time + while self._stop < t: + self._time = self._stop + self._cond.wait() + self._time = t + + # advance time limit for user code + def advance(self, t): + assert t >= 0 + with self._cond: + self._stop += t + self._cond.notify_all() + + class TestCase(unittest.TestCase): def test_enter(self): @@ -31,17 +63,34 @@ class TestCase(unittest.TestCase): @unittest.skipUnless(threading, 'Threading required for this test.') def test_enter_concurrent(self): - l = [] - fun = lambda x: l.append(x) - scheduler = sched.scheduler(time.time, time.sleep) - scheduler.enter(0.03, 1, fun, (0.03,)) + q = queue.Queue() + fun = q.put + timer = Timer() + scheduler = sched.scheduler(timer.time, timer.sleep) + scheduler.enter(1, 1, fun, (1,)) + scheduler.enter(3, 1, fun, (3,)) t = threading.Thread(target=scheduler.run) t.start() - for x in [0.05, 0.04, 0.02, 0.01]: - z = scheduler.enter(x, 1, fun, (x,)) - scheduler.run() - t.join() - self.assertEqual(l, [0.01, 0.02, 0.03, 0.04, 0.05]) + timer.advance(1) + self.assertEqual(q.get(timeout=TIMEOUT), 1) + self.assertTrue(q.empty()) + for x in [4, 5, 2]: + z = scheduler.enter(x - 1, 1, fun, (x,)) + timer.advance(2) + self.assertEqual(q.get(timeout=TIMEOUT), 2) + self.assertEqual(q.get(timeout=TIMEOUT), 3) + self.assertTrue(q.empty()) + timer.advance(1) + self.assertEqual(q.get(timeout=TIMEOUT), 4) + self.assertTrue(q.empty()) + timer.advance(1) + self.assertEqual(q.get(timeout=TIMEOUT), 5) + self.assertTrue(q.empty()) + timer.advance(1000) + t.join(timeout=TIMEOUT) + self.assertFalse(t.is_alive()) + self.assertTrue(q.empty()) + self.assertEqual(timer.time(), 5) def test_priority(self): l = [] @@ -69,21 +118,36 @@ class TestCase(unittest.TestCase): @unittest.skipUnless(threading, 'Threading required for this test.') def test_cancel_concurrent(self): - l = [] - fun = lambda x: l.append(x) - scheduler = sched.scheduler(time.time, time.sleep) - now = time.time() - event1 = scheduler.enterabs(now + 0.01, 1, fun, (0.01,)) - event2 = scheduler.enterabs(now + 0.02, 1, fun, (0.02,)) - event3 = scheduler.enterabs(now + 0.03, 1, fun, (0.03,)) - event4 = scheduler.enterabs(now + 0.04, 1, fun, (0.04,)) - event5 = scheduler.enterabs(now + 0.05, 1, fun, (0.05,)) + q = queue.Queue() + fun = q.put + timer = Timer() + scheduler = sched.scheduler(timer.time, timer.sleep) + now = timer.time() + event1 = scheduler.enterabs(now + 1, 1, fun, (1,)) + event2 = scheduler.enterabs(now + 2, 1, fun, (2,)) + event4 = scheduler.enterabs(now + 4, 1, fun, (4,)) + event5 = scheduler.enterabs(now + 5, 1, fun, (5,)) + event3 = scheduler.enterabs(now + 3, 1, fun, (3,)) t = threading.Thread(target=scheduler.run) t.start() - scheduler.cancel(event1) + timer.advance(1) + self.assertEqual(q.get(timeout=TIMEOUT), 1) + self.assertTrue(q.empty()) + scheduler.cancel(event2) scheduler.cancel(event5) - t.join() - self.assertEqual(l, [0.02, 0.03, 0.04]) + timer.advance(1) + self.assertTrue(q.empty()) + timer.advance(1) + self.assertEqual(q.get(timeout=TIMEOUT), 3) + self.assertTrue(q.empty()) + timer.advance(1) + self.assertEqual(q.get(timeout=TIMEOUT), 4) + self.assertTrue(q.empty()) + timer.advance(1000) + t.join(timeout=TIMEOUT) + self.assertFalse(t.is_alive()) + self.assertTrue(q.empty()) + self.assertEqual(timer.time(), 4) def test_empty(self): l = [] |