blob: 3f84af2a4c2a9e7f0e3b8cd53bbba1d5919e47bf [file] [log] [blame]
Serhiy Storchaka369a7822013-01-09 00:13:38 +02001import queue
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +00002import sched
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02003import threading
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +00004import time
5import unittest
Victor Stinnerb9b69002017-09-14 14:40:56 -07006from test import support
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02007
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +00008
Serhiy Storchaka369a7822013-01-09 00:13:38 +02009TIMEOUT = 10
10
11
12class Timer:
13 def __init__(self):
14 self._cond = threading.Condition()
15 self._time = 0
16 self._stop = 0
17
18 def time(self):
19 with self._cond:
20 return self._time
21
22 # increase the time but not beyond the established limit
23 def sleep(self, t):
24 assert t >= 0
25 with self._cond:
26 t += self._time
27 while self._stop < t:
28 self._time = self._stop
29 self._cond.wait()
30 self._time = t
31
32 # advance time limit for user code
33 def advance(self, t):
34 assert t >= 0
35 with self._cond:
36 self._stop += t
37 self._cond.notify_all()
38
39
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +000040class TestCase(unittest.TestCase):
41
42 def test_enter(self):
43 l = []
44 fun = lambda x: l.append(x)
45 scheduler = sched.scheduler(time.time, time.sleep)
Charles-François Natalif670ca52012-02-16 19:49:48 +010046 for x in [0.5, 0.4, 0.3, 0.2, 0.1]:
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +000047 z = scheduler.enter(x, 1, fun, (x,))
48 scheduler.run()
Charles-François Natalif670ca52012-02-16 19:49:48 +010049 self.assertEqual(l, [0.1, 0.2, 0.3, 0.4, 0.5])
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +000050
51 def test_enterabs(self):
52 l = []
53 fun = lambda x: l.append(x)
54 scheduler = sched.scheduler(time.time, time.sleep)
55 for x in [0.05, 0.04, 0.03, 0.02, 0.01]:
56 z = scheduler.enterabs(x, 1, fun, (x,))
57 scheduler.run()
58 self.assertEqual(l, [0.01, 0.02, 0.03, 0.04, 0.05])
59
Serhiy Storchakaf2b9cf42012-12-29 21:34:11 +020060 def test_enter_concurrent(self):
Serhiy Storchaka369a7822013-01-09 00:13:38 +020061 q = queue.Queue()
62 fun = q.put
63 timer = Timer()
64 scheduler = sched.scheduler(timer.time, timer.sleep)
65 scheduler.enter(1, 1, fun, (1,))
66 scheduler.enter(3, 1, fun, (3,))
Serhiy Storchakaf2b9cf42012-12-29 21:34:11 +020067 t = threading.Thread(target=scheduler.run)
68 t.start()
Serhiy Storchaka369a7822013-01-09 00:13:38 +020069 timer.advance(1)
70 self.assertEqual(q.get(timeout=TIMEOUT), 1)
71 self.assertTrue(q.empty())
72 for x in [4, 5, 2]:
73 z = scheduler.enter(x - 1, 1, fun, (x,))
74 timer.advance(2)
75 self.assertEqual(q.get(timeout=TIMEOUT), 2)
76 self.assertEqual(q.get(timeout=TIMEOUT), 3)
77 self.assertTrue(q.empty())
78 timer.advance(1)
79 self.assertEqual(q.get(timeout=TIMEOUT), 4)
80 self.assertTrue(q.empty())
81 timer.advance(1)
82 self.assertEqual(q.get(timeout=TIMEOUT), 5)
83 self.assertTrue(q.empty())
84 timer.advance(1000)
Victor Stinnerb9b69002017-09-14 14:40:56 -070085 support.join_thread(t, timeout=TIMEOUT)
Serhiy Storchaka369a7822013-01-09 00:13:38 +020086 self.assertTrue(q.empty())
87 self.assertEqual(timer.time(), 5)
Serhiy Storchakaf2b9cf42012-12-29 21:34:11 +020088
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +000089 def test_priority(self):
90 l = []
91 fun = lambda x: l.append(x)
92 scheduler = sched.scheduler(time.time, time.sleep)
93 for priority in [1, 2, 3, 4, 5]:
Charles-François Natalif670ca52012-02-16 19:49:48 +010094 z = scheduler.enterabs(0.01, priority, fun, (priority,))
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +000095 scheduler.run()
96 self.assertEqual(l, [1, 2, 3, 4, 5])
97
98 def test_cancel(self):
99 l = []
100 fun = lambda x: l.append(x)
101 scheduler = sched.scheduler(time.time, time.sleep)
Charles-François Natalif670ca52012-02-16 19:49:48 +0100102 now = time.time()
103 event1 = scheduler.enterabs(now + 0.01, 1, fun, (0.01,))
104 event2 = scheduler.enterabs(now + 0.02, 1, fun, (0.02,))
105 event3 = scheduler.enterabs(now + 0.03, 1, fun, (0.03,))
106 event4 = scheduler.enterabs(now + 0.04, 1, fun, (0.04,))
107 event5 = scheduler.enterabs(now + 0.05, 1, fun, (0.05,))
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +0000108 scheduler.cancel(event1)
109 scheduler.cancel(event5)
110 scheduler.run()
111 self.assertEqual(l, [0.02, 0.03, 0.04])
112
Serhiy Storchakaf2b9cf42012-12-29 21:34:11 +0200113 def test_cancel_concurrent(self):
Serhiy Storchaka369a7822013-01-09 00:13:38 +0200114 q = queue.Queue()
115 fun = q.put
116 timer = Timer()
117 scheduler = sched.scheduler(timer.time, timer.sleep)
118 now = timer.time()
119 event1 = scheduler.enterabs(now + 1, 1, fun, (1,))
120 event2 = scheduler.enterabs(now + 2, 1, fun, (2,))
121 event4 = scheduler.enterabs(now + 4, 1, fun, (4,))
122 event5 = scheduler.enterabs(now + 5, 1, fun, (5,))
123 event3 = scheduler.enterabs(now + 3, 1, fun, (3,))
Serhiy Storchakaf2b9cf42012-12-29 21:34:11 +0200124 t = threading.Thread(target=scheduler.run)
125 t.start()
Serhiy Storchaka369a7822013-01-09 00:13:38 +0200126 timer.advance(1)
127 self.assertEqual(q.get(timeout=TIMEOUT), 1)
128 self.assertTrue(q.empty())
129 scheduler.cancel(event2)
Serhiy Storchakaf2b9cf42012-12-29 21:34:11 +0200130 scheduler.cancel(event5)
Serhiy Storchaka369a7822013-01-09 00:13:38 +0200131 timer.advance(1)
132 self.assertTrue(q.empty())
133 timer.advance(1)
134 self.assertEqual(q.get(timeout=TIMEOUT), 3)
135 self.assertTrue(q.empty())
136 timer.advance(1)
137 self.assertEqual(q.get(timeout=TIMEOUT), 4)
138 self.assertTrue(q.empty())
139 timer.advance(1000)
Victor Stinnerb9b69002017-09-14 14:40:56 -0700140 support.join_thread(t, timeout=TIMEOUT)
Serhiy Storchaka369a7822013-01-09 00:13:38 +0200141 self.assertTrue(q.empty())
142 self.assertEqual(timer.time(), 4)
Serhiy Storchakaf2b9cf42012-12-29 21:34:11 +0200143
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +0000144 def test_empty(self):
145 l = []
146 fun = lambda x: l.append(x)
147 scheduler = sched.scheduler(time.time, time.sleep)
148 self.assertTrue(scheduler.empty())
149 for x in [0.05, 0.04, 0.03, 0.02, 0.01]:
150 z = scheduler.enterabs(x, 1, fun, (x,))
151 self.assertFalse(scheduler.empty())
152 scheduler.run()
153 self.assertTrue(scheduler.empty())
154
155 def test_queue(self):
156 l = []
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +0000157 fun = lambda x: l.append(x)
158 scheduler = sched.scheduler(time.time, time.sleep)
Charles-François Natali4a72ebe2012-02-16 19:51:45 +0100159 now = time.time()
160 e5 = scheduler.enterabs(now + 0.05, 1, fun)
161 e1 = scheduler.enterabs(now + 0.01, 1, fun)
162 e2 = scheduler.enterabs(now + 0.02, 1, fun)
163 e4 = scheduler.enterabs(now + 0.04, 1, fun)
164 e3 = scheduler.enterabs(now + 0.03, 1, fun)
Giampaolo Rodola'6a5dcd42011-11-26 12:17:42 +0100165 # queue property is supposed to return an order list of
166 # upcoming events
Raymond Hettinger889b92d2013-07-13 22:42:09 -0700167 self.assertEqual(scheduler.queue, [e1, e2, e3, e4, e5])
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +0000168
Giampaolo Rodola'be55d992011-11-22 13:33:34 +0100169 def test_args_kwargs(self):
Raymond Hettinger6b3481c2016-11-21 16:48:10 -0800170 seq = []
Giampaolo Rodola'be55d992011-11-22 13:33:34 +0100171 def fun(*a, **b):
Raymond Hettinger6b3481c2016-11-21 16:48:10 -0800172 seq.append((a, b))
Giampaolo Rodola'be55d992011-11-22 13:33:34 +0100173
Raymond Hettinger6b3481c2016-11-21 16:48:10 -0800174 now = time.time()
Giampaolo Rodola'be55d992011-11-22 13:33:34 +0100175 scheduler = sched.scheduler(time.time, time.sleep)
Raymond Hettinger6b3481c2016-11-21 16:48:10 -0800176 scheduler.enterabs(now, 1, fun)
177 scheduler.enterabs(now, 1, fun, argument=(1, 2))
178 scheduler.enterabs(now, 1, fun, argument=('a', 'b'))
179 scheduler.enterabs(now, 1, fun, argument=(1, 2), kwargs={"foo": 3})
Giampaolo Rodola'be55d992011-11-22 13:33:34 +0100180 scheduler.run()
Raymond Hettinger6b3481c2016-11-21 16:48:10 -0800181 self.assertCountEqual(seq, [
182 ((), {}),
183 ((1, 2), {}),
184 (('a', 'b'), {}),
185 ((1, 2), {'foo': 3})
186 ])
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +0000187
Giampaolo Rodola'556ba042011-12-14 14:38:45 +0100188 def test_run_non_blocking(self):
189 l = []
190 fun = lambda x: l.append(x)
191 scheduler = sched.scheduler(time.time, time.sleep)
192 for x in [10, 9, 8, 7, 6]:
193 scheduler.enter(x, 1, fun, (x,))
194 scheduler.run(blocking=False)
195 self.assertEqual(l, [])
196
197
Giampaolo Rodolàb5c23762010-08-04 09:28:05 +0000198if __name__ == "__main__":
Brett Cannon3e9a9ae2013-06-12 21:25:59 -0400199 unittest.main()