blob: 19cd321d14e569dafce55b087df558d9de9aa89f [file] [log] [blame]
Mark Hammond3b959db2002-04-19 00:11:32 +00001# Some simple Queue module tests, plus some failure conditions
2# to ensure the Queue locks remain stable
3import 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
10queue_size = 5
11
12# Execute a function that blocks, and in a seperate thread, a function that
13# triggers the release. Returns the result of the blocking function.
14class _TriggerThread(threading.Thread):
15 def __init__(self, fn, args):
16 self.fn = fn
17 self.args = args
18 self.startedEvent = threading.Event()
19 threading.Thread.__init__(self)
20 def run(self):
21 time.sleep(.1)
22 self.startedEvent.set()
23 self.fn(*self.args)
24
25def _doBlockingTest( block_func, block_args, trigger_func, trigger_args):
26 t = _TriggerThread(trigger_func, trigger_args)
27 t.start()
28 try:
29 return block_func(*block_args)
30 finally:
31 # If we unblocked before our thread made the call, we failed!
32 if not t.startedEvent.isSet():
33 raise TestFailed("blocking function '%r' appeared not to block" % (block_func,))
34 t.join(1) # make sure the thread terminates
35 if t.isAlive():
36 raise TestFailed("trigger function '%r' appeared to not return" % (trigger_func,))
37
38# A Queue subclass that can provoke failure at a moment's notice :)
39class FailingQueueException(Exception):
40 pass
41
42class FailingQueue(Queue.Queue):
43 def __init__(self, *args):
44 self.fail_next_put = False
45 self.fail_next_get = False
46 Queue.Queue.__init__(self, *args)
47 def _put(self, item):
48 if self.fail_next_put:
49 self.fail_next_put = False
50 raise FailingQueueException, "You Lose"
51 return Queue.Queue._put(self, item)
52 def _get(self):
53 if self.fail_next_get:
54 self.fail_next_get = False
55 raise FailingQueueException, "You Lose"
56 return Queue.Queue._get(self)
57
58def FailingQueueTest(q):
59 if not q.empty():
60 raise RuntimeError, "Call this function with an empty queue"
61 for i in range(queue_size-1):
62 q.put(i)
Mark Hammond3b959db2002-04-19 00:11:32 +000063 # Test a failing non-blocking put.
Martin v. Löwis77ac4292002-10-15 15:11:13 +000064 q.fail_next_put = True
Mark Hammond3b959db2002-04-19 00:11:32 +000065 try:
66 q.put("oops", block=0)
67 raise TestFailed("The queue didn't fail when it should have")
68 except FailingQueueException:
69 pass
Martin v. Löwis77ac4292002-10-15 15:11:13 +000070 q.fail_next_put = True
71 try:
72 q.put("oops", timeout=0.1)
73 raise TestFailed("The queue didn't fail when it should have")
74 except FailingQueueException:
75 pass
Mark Hammond3b959db2002-04-19 00:11:32 +000076 q.put("last")
77 verify(q.full(), "Queue should be full")
Mark Hammond3b959db2002-04-19 00:11:32 +000078 # Test a failing blocking put
Martin v. Löwis77ac4292002-10-15 15:11:13 +000079 q.fail_next_put = True
Mark Hammond3b959db2002-04-19 00:11:32 +000080 try:
81 _doBlockingTest( q.put, ("full",), q.get, ())
82 raise TestFailed("The queue didn't fail when it should have")
83 except FailingQueueException:
84 pass
85 # Check the Queue isn't damaged.
86 # put failed, but get succeeded - re-add
87 q.put("last")
Martin v. Löwis77ac4292002-10-15 15:11:13 +000088 # Test a failing timeout put
89 q.fail_next_put = True
90 try:
91 _doBlockingTest( q.put, ("full", True, 0.2), q.get, ())
92 raise TestFailed("The queue didn't fail when it should have")
93 except FailingQueueException:
94 pass
95 # Check the Queue isn't damaged.
96 # put failed, but get succeeded - re-add
97 q.put("last")
Mark Hammond3b959db2002-04-19 00:11:32 +000098 verify(q.full(), "Queue should be full")
99 q.get()
100 verify(not q.full(), "Queue should not be full")
101 q.put("last")
102 verify(q.full(), "Queue should be full")
103 # Test a blocking put
104 _doBlockingTest( q.put, ("full",), q.get, ())
105 # Empty it
106 for i in range(queue_size):
107 q.get()
108 verify(q.empty(), "Queue should be empty")
109 q.put("first")
110 q.fail_next_get = True
111 try:
112 q.get()
113 raise TestFailed("The queue didn't fail when it should have")
114 except FailingQueueException:
115 pass
116 verify(not q.empty(), "Queue should not be empty")
Martin v. Löwis77ac4292002-10-15 15:11:13 +0000117 q.fail_next_get = True
118 try:
119 q.get(timeout=0.1)
120 raise TestFailed("The queue didn't fail when it should have")
121 except FailingQueueException:
122 pass
123 verify(not q.empty(), "Queue should not be empty")
Mark Hammond3b959db2002-04-19 00:11:32 +0000124 q.get()
125 verify(q.empty(), "Queue should be empty")
126 q.fail_next_get = True
127 try:
128 _doBlockingTest( q.get, (), q.put, ('empty',))
129 raise TestFailed("The queue didn't fail when it should have")
130 except FailingQueueException:
131 pass
132 # put succeeded, but get failed.
133 verify(not q.empty(), "Queue should not be empty")
134 q.get()
135 verify(q.empty(), "Queue should be empty")
136
137def SimpleQueueTest(q):
138 if not q.empty():
139 raise RuntimeError, "Call this function with an empty queue"
140 # I guess we better check things actually queue correctly a little :)
141 q.put(111)
142 q.put(222)
143 verify(q.get()==111 and q.get()==222, "Didn't seem to queue the correct data!")
144 for i in range(queue_size-1):
145 q.put(i)
146 verify(not q.full(), "Queue should not be full")
147 q.put("last")
148 verify(q.full(), "Queue should be full")
149 try:
150 q.put("full", block=0)
151 raise TestFailed("Didn't appear to block with a full queue")
152 except Queue.Full:
153 pass
Martin v. Löwis77ac4292002-10-15 15:11:13 +0000154 try:
155 q.put("full", timeout=0.1)
156 raise TestFailed("Didn't appear to time-out with a full queue")
157 except Queue.Full:
158 pass
Mark Hammond3b959db2002-04-19 00:11:32 +0000159 # Test a blocking put
160 _doBlockingTest( q.put, ("full",), q.get, ())
Martin v. Löwis77ac4292002-10-15 15:11:13 +0000161 _doBlockingTest( q.put, ("full", True, 0.2), q.get, ())
Mark Hammond3b959db2002-04-19 00:11:32 +0000162 # Empty it
163 for i in range(queue_size):
164 q.get()
165 verify(q.empty(), "Queue should be empty")
166 try:
167 q.get(block=0)
168 raise TestFailed("Didn't appear to block with an empty queue")
169 except Queue.Empty:
170 pass
Martin v. Löwis77ac4292002-10-15 15:11:13 +0000171 try:
172 q.get(timeout=0.1)
173 raise TestFailed("Didn't appear to time-out with an empty queue")
174 except Queue.Empty:
175 pass
Mark Hammond3b959db2002-04-19 00:11:32 +0000176 # Test a blocking get
177 _doBlockingTest( q.get, (), q.put, ('empty',))
Martin v. Löwis77ac4292002-10-15 15:11:13 +0000178 _doBlockingTest( q.get, (True, 0.2), q.put, ('empty',))
Mark Hammond3b959db2002-04-19 00:11:32 +0000179
180def test():
181 q=Queue.Queue(queue_size)
182 # Do it a couple of times on the same queue
183 SimpleQueueTest(q)
184 SimpleQueueTest(q)
185 if verbose:
186 print "Simple Queue tests seemed to work"
187 q = FailingQueue(queue_size)
188 FailingQueueTest(q)
189 FailingQueueTest(q)
190 if verbose:
191 print "Failing Queue tests seemed to work"
192
193test()