| 
									
										
										
										
											2013-01-09 00:13:38 +02:00
										 |  |  | import queue | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  | import sched | 
					
						
							| 
									
										
										
										
											2017-09-07 18:56:24 +02:00
										 |  |  | import threading | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  | import time | 
					
						
							|  |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2017-09-14 14:40:56 -07:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  | from test.support import threading_helper | 
					
						
							| 
									
										
										
										
											2017-09-07 18:56:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-11 11:30:03 +01:00
										 |  |  | TIMEOUT = support.SHORT_TIMEOUT | 
					
						
							| 
									
										
										
										
											2013-01-09 00:13:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  | class TestCase(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_enter(self): | 
					
						
							|  |  |  |         l = [] | 
					
						
							|  |  |  |         fun = lambda x: l.append(x) | 
					
						
							|  |  |  |         scheduler = sched.scheduler(time.time, time.sleep) | 
					
						
							| 
									
										
										
										
											2012-02-16 19:49:48 +01:00
										 |  |  |         for x in [0.5, 0.4, 0.3, 0.2, 0.1]: | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  |             z = scheduler.enter(x, 1, fun, (x,)) | 
					
						
							|  |  |  |         scheduler.run() | 
					
						
							| 
									
										
										
										
											2012-02-16 19:49:48 +01:00
										 |  |  |         self.assertEqual(l, [0.1, 0.2, 0.3, 0.4, 0.5]) | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_enterabs(self): | 
					
						
							|  |  |  |         l = [] | 
					
						
							|  |  |  |         fun = lambda x: l.append(x) | 
					
						
							|  |  |  |         scheduler = sched.scheduler(time.time, time.sleep) | 
					
						
							|  |  |  |         for x in [0.05, 0.04, 0.03, 0.02, 0.01]: | 
					
						
							|  |  |  |             z = scheduler.enterabs(x, 1, fun, (x,)) | 
					
						
							|  |  |  |         scheduler.run() | 
					
						
							|  |  |  |         self.assertEqual(l, [0.01, 0.02, 0.03, 0.04, 0.05]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-07 10:22:47 +03:00
										 |  |  |     @threading_helper.requires_working_threading() | 
					
						
							| 
									
										
										
										
											2012-12-29 21:34:11 +02:00
										 |  |  |     def test_enter_concurrent(self): | 
					
						
							| 
									
										
										
										
											2013-01-09 00:13:38 +02:00
										 |  |  |         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,)) | 
					
						
							| 
									
										
										
										
											2012-12-29 21:34:11 +02:00
										 |  |  |         t = threading.Thread(target=scheduler.run) | 
					
						
							|  |  |  |         t.start() | 
					
						
							| 
									
										
										
										
											2013-01-09 00:13:38 +02:00
										 |  |  |         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) | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  |         threading_helper.join_thread(t) | 
					
						
							| 
									
										
										
										
											2013-01-09 00:13:38 +02:00
										 |  |  |         self.assertTrue(q.empty()) | 
					
						
							|  |  |  |         self.assertEqual(timer.time(), 5) | 
					
						
							| 
									
										
										
										
											2012-12-29 21:34:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  |     def test_priority(self): | 
					
						
							|  |  |  |         l = [] | 
					
						
							|  |  |  |         fun = lambda x: l.append(x) | 
					
						
							|  |  |  |         scheduler = sched.scheduler(time.time, time.sleep) | 
					
						
							|  |  |  |         for priority in [1, 2, 3, 4, 5]: | 
					
						
							| 
									
										
										
										
											2012-02-16 19:49:48 +01:00
										 |  |  |             z = scheduler.enterabs(0.01, priority, fun, (priority,)) | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  |         scheduler.run() | 
					
						
							|  |  |  |         self.assertEqual(l, [1, 2, 3, 4, 5]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_cancel(self): | 
					
						
							|  |  |  |         l = [] | 
					
						
							|  |  |  |         fun = lambda x: l.append(x) | 
					
						
							|  |  |  |         scheduler = sched.scheduler(time.time, time.sleep) | 
					
						
							| 
									
										
										
										
											2012-02-16 19:49:48 +01:00
										 |  |  |         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,)) | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  |         scheduler.cancel(event1) | 
					
						
							|  |  |  |         scheduler.cancel(event5) | 
					
						
							|  |  |  |         scheduler.run() | 
					
						
							|  |  |  |         self.assertEqual(l, [0.02, 0.03, 0.04]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-07 10:22:47 +03:00
										 |  |  |     @threading_helper.requires_working_threading() | 
					
						
							| 
									
										
										
										
											2012-12-29 21:34:11 +02:00
										 |  |  |     def test_cancel_concurrent(self): | 
					
						
							| 
									
										
										
										
											2013-01-09 00:13:38 +02:00
										 |  |  |         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,)) | 
					
						
							| 
									
										
										
										
											2012-12-29 21:34:11 +02:00
										 |  |  |         t = threading.Thread(target=scheduler.run) | 
					
						
							|  |  |  |         t.start() | 
					
						
							| 
									
										
										
										
											2013-01-09 00:13:38 +02:00
										 |  |  |         timer.advance(1) | 
					
						
							|  |  |  |         self.assertEqual(q.get(timeout=TIMEOUT), 1) | 
					
						
							|  |  |  |         self.assertTrue(q.empty()) | 
					
						
							|  |  |  |         scheduler.cancel(event2) | 
					
						
							| 
									
										
										
										
											2012-12-29 21:34:11 +02:00
										 |  |  |         scheduler.cancel(event5) | 
					
						
							| 
									
										
										
										
											2013-01-09 00:13:38 +02:00
										 |  |  |         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) | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  |         threading_helper.join_thread(t) | 
					
						
							| 
									
										
										
										
											2013-01-09 00:13:38 +02:00
										 |  |  |         self.assertTrue(q.empty()) | 
					
						
							|  |  |  |         self.assertEqual(timer.time(), 4) | 
					
						
							| 
									
										
										
										
											2012-12-29 21:34:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 10:33:43 +03:00
										 |  |  |     def test_cancel_correct_event(self): | 
					
						
							|  |  |  |         # bpo-19270 | 
					
						
							|  |  |  |         events = [] | 
					
						
							|  |  |  |         scheduler = sched.scheduler() | 
					
						
							|  |  |  |         scheduler.enterabs(1, 1, events.append, ("a",)) | 
					
						
							|  |  |  |         b = scheduler.enterabs(1, 1, events.append, ("b",)) | 
					
						
							|  |  |  |         scheduler.enterabs(1, 1, events.append, ("c",)) | 
					
						
							|  |  |  |         scheduler.cancel(b) | 
					
						
							|  |  |  |         scheduler.run() | 
					
						
							|  |  |  |         self.assertEqual(events, ["a", "c"]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  |     def test_empty(self): | 
					
						
							|  |  |  |         l = [] | 
					
						
							|  |  |  |         fun = lambda x: l.append(x) | 
					
						
							|  |  |  |         scheduler = sched.scheduler(time.time, time.sleep) | 
					
						
							|  |  |  |         self.assertTrue(scheduler.empty()) | 
					
						
							|  |  |  |         for x in [0.05, 0.04, 0.03, 0.02, 0.01]: | 
					
						
							|  |  |  |             z = scheduler.enterabs(x, 1, fun, (x,)) | 
					
						
							|  |  |  |         self.assertFalse(scheduler.empty()) | 
					
						
							|  |  |  |         scheduler.run() | 
					
						
							|  |  |  |         self.assertTrue(scheduler.empty()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_queue(self): | 
					
						
							|  |  |  |         l = [] | 
					
						
							|  |  |  |         fun = lambda x: l.append(x) | 
					
						
							|  |  |  |         scheduler = sched.scheduler(time.time, time.sleep) | 
					
						
							| 
									
										
										
										
											2012-02-16 19:51:45 +01:00
										 |  |  |         now = time.time() | 
					
						
							|  |  |  |         e5 = scheduler.enterabs(now + 0.05, 1, fun) | 
					
						
							|  |  |  |         e1 = scheduler.enterabs(now + 0.01, 1, fun) | 
					
						
							|  |  |  |         e2 = scheduler.enterabs(now + 0.02, 1, fun) | 
					
						
							|  |  |  |         e4 = scheduler.enterabs(now + 0.04, 1, fun) | 
					
						
							|  |  |  |         e3 = scheduler.enterabs(now + 0.03, 1, fun) | 
					
						
							| 
									
										
										
										
											2011-11-26 12:17:42 +01:00
										 |  |  |         # queue property is supposed to return an order list of | 
					
						
							|  |  |  |         # upcoming events | 
					
						
							| 
									
										
										
										
											2013-07-13 22:42:09 -07:00
										 |  |  |         self.assertEqual(scheduler.queue, [e1, e2, e3, e4, e5]) | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-22 13:33:34 +01:00
										 |  |  |     def test_args_kwargs(self): | 
					
						
							| 
									
										
										
										
											2016-11-21 16:48:10 -08:00
										 |  |  |         seq = [] | 
					
						
							| 
									
										
										
										
											2011-11-22 13:33:34 +01:00
										 |  |  |         def fun(*a, **b): | 
					
						
							| 
									
										
										
										
											2016-11-21 16:48:10 -08:00
										 |  |  |             seq.append((a, b)) | 
					
						
							| 
									
										
										
										
											2011-11-22 13:33:34 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-21 16:48:10 -08:00
										 |  |  |         now = time.time() | 
					
						
							| 
									
										
										
										
											2011-11-22 13:33:34 +01:00
										 |  |  |         scheduler = sched.scheduler(time.time, time.sleep) | 
					
						
							| 
									
										
										
										
											2016-11-21 16:48:10 -08:00
										 |  |  |         scheduler.enterabs(now, 1, fun) | 
					
						
							|  |  |  |         scheduler.enterabs(now, 1, fun, argument=(1, 2)) | 
					
						
							|  |  |  |         scheduler.enterabs(now, 1, fun, argument=('a', 'b')) | 
					
						
							|  |  |  |         scheduler.enterabs(now, 1, fun, argument=(1, 2), kwargs={"foo": 3}) | 
					
						
							| 
									
										
										
										
											2011-11-22 13:33:34 +01:00
										 |  |  |         scheduler.run() | 
					
						
							| 
									
										
										
										
											2016-11-21 16:48:10 -08:00
										 |  |  |         self.assertCountEqual(seq, [ | 
					
						
							|  |  |  |             ((), {}), | 
					
						
							|  |  |  |             ((1, 2), {}), | 
					
						
							|  |  |  |             (('a', 'b'), {}), | 
					
						
							|  |  |  |             ((1, 2), {'foo': 3}) | 
					
						
							|  |  |  |         ]) | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-14 14:38:45 +01:00
										 |  |  |     def test_run_non_blocking(self): | 
					
						
							|  |  |  |         l = [] | 
					
						
							|  |  |  |         fun = lambda x: l.append(x) | 
					
						
							|  |  |  |         scheduler = sched.scheduler(time.time, time.sleep) | 
					
						
							|  |  |  |         for x in [10, 9, 8, 7, 6]: | 
					
						
							|  |  |  |             scheduler.enter(x, 1, fun, (x,)) | 
					
						
							|  |  |  |         scheduler.run(blocking=False) | 
					
						
							|  |  |  |         self.assertEqual(l, []) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-04 09:28:05 +00:00
										 |  |  | if __name__ == "__main__": | 
					
						
							| 
									
										
										
										
											2013-06-12 21:25:59 -04:00
										 |  |  |     unittest.main() |