blob: 0bd395ad379a0a12c9d59a97385fbccf9dcce937 [file] [log] [blame]
Mark Hammond3b959db2002-04-19 00:11:32 +00001# Some simple Queue module tests, plus some failure conditions
Tim Petersafe52972004-08-20 02:37:25 +00002# to ensure the Queue locks remain stable.
Mark Hammond3b959db2002-04-19 00:11:32 +00003import Queue
4import sys
5import threading
6import time
7
Barry Warsaw04f357c2002-07-23 19:04:11 +00008from test.test_support import verify, TestFailed, verbose
Mark Hammond3b959db2002-04-19 00:11:32 +00009
Tim Petersafe52972004-08-20 02:37:25 +000010QUEUE_SIZE = 5
Mark Hammond3b959db2002-04-19 00:11:32 +000011
Tim Petersafe52972004-08-20 02:37:25 +000012# A thread to run a function that unclogs a blocked Queue.
Mark Hammond3b959db2002-04-19 00:11:32 +000013class _TriggerThread(threading.Thread):
14 def __init__(self, fn, args):
15 self.fn = fn
16 self.args = args
17 self.startedEvent = threading.Event()
18 threading.Thread.__init__(self)
Tim Petersafe52972004-08-20 02:37:25 +000019
Mark Hammond3b959db2002-04-19 00:11:32 +000020 def run(self):
21 time.sleep(.1)
22 self.startedEvent.set()
23 self.fn(*self.args)
24
Tim Petersafe52972004-08-20 02:37:25 +000025# Execute a function that blocks, and in a seperate thread, a function that
26# triggers the release. Returns the result of the blocking function.
Tim Petersa1d004a2002-11-15 19:08:50 +000027def _doBlockingTest(block_func, block_args, trigger_func, trigger_args):
Mark Hammond3b959db2002-04-19 00:11:32 +000028 t = _TriggerThread(trigger_func, trigger_args)
29 t.start()
30 try:
31 return block_func(*block_args)
32 finally:
33 # If we unblocked before our thread made the call, we failed!
34 if not t.startedEvent.isSet():
Tim Petersa1d004a2002-11-15 19:08:50 +000035 raise TestFailed("blocking function '%r' appeared not to block" %
36 block_func)
Mark Hammond3b959db2002-04-19 00:11:32 +000037 t.join(1) # make sure the thread terminates
38 if t.isAlive():
Tim Petersa1d004a2002-11-15 19:08:50 +000039 raise TestFailed("trigger function '%r' appeared to not return" %
40 trigger_func)
Mark Hammond3b959db2002-04-19 00:11:32 +000041
42# A Queue subclass that can provoke failure at a moment's notice :)
43class FailingQueueException(Exception):
44 pass
45
46class FailingQueue(Queue.Queue):
47 def __init__(self, *args):
48 self.fail_next_put = False
49 self.fail_next_get = False
50 Queue.Queue.__init__(self, *args)
51 def _put(self, item):
52 if self.fail_next_put:
53 self.fail_next_put = False
54 raise FailingQueueException, "You Lose"
55 return Queue.Queue._put(self, item)
56 def _get(self):
57 if self.fail_next_get:
58 self.fail_next_get = False
59 raise FailingQueueException, "You Lose"
60 return Queue.Queue._get(self)
61
62def FailingQueueTest(q):
63 if not q.empty():
64 raise RuntimeError, "Call this function with an empty queue"
Tim Petersafe52972004-08-20 02:37:25 +000065 for i in range(QUEUE_SIZE-1):
Mark Hammond3b959db2002-04-19 00:11:32 +000066 q.put(i)
Mark Hammond3b959db2002-04-19 00:11:32 +000067 # Test a failing non-blocking put.
Martin v. Löwis77ac4292002-10-15 15:11:13 +000068 q.fail_next_put = True
Mark Hammond3b959db2002-04-19 00:11:32 +000069 try:
70 q.put("oops", block=0)
71 raise TestFailed("The queue didn't fail when it should have")
72 except FailingQueueException:
73 pass
Martin v. Löwis77ac4292002-10-15 15:11:13 +000074 q.fail_next_put = True
75 try:
76 q.put("oops", timeout=0.1)
77 raise TestFailed("The queue didn't fail when it should have")
78 except FailingQueueException:
79 pass
Mark Hammond3b959db2002-04-19 00:11:32 +000080 q.put("last")
81 verify(q.full(), "Queue should be full")
Mark Hammond3b959db2002-04-19 00:11:32 +000082 # Test a failing blocking put
Martin v. Löwis77ac4292002-10-15 15:11:13 +000083 q.fail_next_put = True
Mark Hammond3b959db2002-04-19 00:11:32 +000084 try:
Tim Petersafe52972004-08-20 02:37:25 +000085 _doBlockingTest(q.put, ("full",), q.get, ())
Mark Hammond3b959db2002-04-19 00:11:32 +000086 raise TestFailed("The queue didn't fail when it should have")
87 except FailingQueueException:
88 pass
89 # Check the Queue isn't damaged.
90 # put failed, but get succeeded - re-add
91 q.put("last")
Martin v. Löwis77ac4292002-10-15 15:11:13 +000092 # Test a failing timeout put
93 q.fail_next_put = True
94 try:
Tim Petersafe52972004-08-20 02:37:25 +000095 _doBlockingTest(q.put, ("full", True, 0.2), q.get, ())
Martin v. Löwis77ac4292002-10-15 15:11:13 +000096 raise TestFailed("The queue didn't fail when it should have")
97 except FailingQueueException:
98 pass
99 # Check the Queue isn't damaged.
100 # put failed, but get succeeded - re-add
101 q.put("last")
Mark Hammond3b959db2002-04-19 00:11:32 +0000102 verify(q.full(), "Queue should be full")
103 q.get()
104 verify(not q.full(), "Queue should not be full")
105 q.put("last")
106 verify(q.full(), "Queue should be full")
107 # Test a blocking put
108 _doBlockingTest( q.put, ("full",), q.get, ())
109 # Empty it
Tim Petersafe52972004-08-20 02:37:25 +0000110 for i in range(QUEUE_SIZE):
Mark Hammond3b959db2002-04-19 00:11:32 +0000111 q.get()
112 verify(q.empty(), "Queue should be empty")
113 q.put("first")
114 q.fail_next_get = True
115 try:
116 q.get()
117 raise TestFailed("The queue didn't fail when it should have")
118 except FailingQueueException:
119 pass
120 verify(not q.empty(), "Queue should not be empty")
Martin v. Löwis77ac4292002-10-15 15:11:13 +0000121 q.fail_next_get = True
122 try:
123 q.get(timeout=0.1)
124 raise TestFailed("The queue didn't fail when it should have")
125 except FailingQueueException:
126 pass
127 verify(not q.empty(), "Queue should not be empty")
Mark Hammond3b959db2002-04-19 00:11:32 +0000128 q.get()
129 verify(q.empty(), "Queue should be empty")
130 q.fail_next_get = True
131 try:
132 _doBlockingTest( q.get, (), q.put, ('empty',))
133 raise TestFailed("The queue didn't fail when it should have")
134 except FailingQueueException:
135 pass
136 # put succeeded, but get failed.
137 verify(not q.empty(), "Queue should not be empty")
138 q.get()
139 verify(q.empty(), "Queue should be empty")
140
141def SimpleQueueTest(q):
142 if not q.empty():
143 raise RuntimeError, "Call this function with an empty queue"
144 # I guess we better check things actually queue correctly a little :)
145 q.put(111)
146 q.put(222)
Tim Petersa1d004a2002-11-15 19:08:50 +0000147 verify(q.get() == 111 and q.get() == 222,
148 "Didn't seem to queue the correct data!")
Tim Petersafe52972004-08-20 02:37:25 +0000149 for i in range(QUEUE_SIZE-1):
Mark Hammond3b959db2002-04-19 00:11:32 +0000150 q.put(i)
151 verify(not q.full(), "Queue should not be full")
152 q.put("last")
153 verify(q.full(), "Queue should be full")
154 try:
155 q.put("full", block=0)
156 raise TestFailed("Didn't appear to block with a full queue")
157 except Queue.Full:
158 pass
Martin v. Löwis77ac4292002-10-15 15:11:13 +0000159 try:
160 q.put("full", timeout=0.1)
161 raise TestFailed("Didn't appear to time-out with a full queue")
162 except Queue.Full:
163 pass
Mark Hammond3b959db2002-04-19 00:11:32 +0000164 # Test a blocking put
Tim Petersafe52972004-08-20 02:37:25 +0000165 _doBlockingTest(q.put, ("full",), q.get, ())
166 _doBlockingTest(q.put, ("full", True, 0.2), q.get, ())
Mark Hammond3b959db2002-04-19 00:11:32 +0000167 # Empty it
Tim Petersafe52972004-08-20 02:37:25 +0000168 for i in range(QUEUE_SIZE):
Mark Hammond3b959db2002-04-19 00:11:32 +0000169 q.get()
170 verify(q.empty(), "Queue should be empty")
171 try:
172 q.get(block=0)
173 raise TestFailed("Didn't appear to block with an empty queue")
174 except Queue.Empty:
175 pass
Martin v. Löwis77ac4292002-10-15 15:11:13 +0000176 try:
177 q.get(timeout=0.1)
178 raise TestFailed("Didn't appear to time-out with an empty queue")
179 except Queue.Empty:
180 pass
Mark Hammond3b959db2002-04-19 00:11:32 +0000181 # Test a blocking get
Tim Petersa1d004a2002-11-15 19:08:50 +0000182 _doBlockingTest(q.get, (), q.put, ('empty',))
183 _doBlockingTest(q.get, (True, 0.2), q.put, ('empty',))
Mark Hammond3b959db2002-04-19 00:11:32 +0000184
185def test():
Tim Petersafe52972004-08-20 02:37:25 +0000186 q = Queue.Queue(QUEUE_SIZE)
Mark Hammond3b959db2002-04-19 00:11:32 +0000187 # Do it a couple of times on the same queue
188 SimpleQueueTest(q)
189 SimpleQueueTest(q)
190 if verbose:
191 print "Simple Queue tests seemed to work"
Tim Petersafe52972004-08-20 02:37:25 +0000192 q = FailingQueue(QUEUE_SIZE)
Mark Hammond3b959db2002-04-19 00:11:32 +0000193 FailingQueueTest(q)
194 FailingQueueTest(q)
195 if verbose:
196 print "Failing Queue tests seemed to work"
197
198test()