def test_order(self): # The behavior of a queue should be FIFO queue = gruvi.Queue() for i in range(10): queue.put(10 + i) for i in range(10): self.assertEqual(queue.get(), 10 + i)
def test_produce_consume(self): # Ensure that there's no deadlocks when pushing a large number of items # through a queue with a fixed size. queue = gruvi.Queue(maxsize=10) result = [] sizes = [] def consumer(n): for i in range(n): queue.put(i) sizes.append(queue.qsize()) def producer(n): for i in range(n): result.append(queue.get()) sizes.append(queue.qsize()) ni = 2000 fcons = gruvi.spawn(consumer, ni) fprod = gruvi.spawn(producer, ni) fcons.join() fprod.join() self.assertEqual(len(result), ni) self.assertEqual(result, list(range(ni))) self.assertLessEqual(max(sizes), 10)
def test_types(self): # Queue should support putting in arbitrary objects. queue = gruvi.Queue() queue.put('foo') self.assertEqual(queue.get(), 'foo') queue.put(['foo']) self.assertEqual(queue.get(), ['foo'])
def test_thread_safety(self): # A Queue should be thread safe. This meanst that all entries that are # put in the queue must be returned, that no entry must be returned # twice and that the order must be respected. Also no deadlock must # ever occur. # To test, fire up a bunch of threads which each fire up a bunch of # fibers, and have the fibers do some random sleeps. Then let it run # and test the result. result = [] reference = [] lock = gruvi.Lock() def put_queue(tid, fid, count): for i in range(count): with lock: gruvi.sleep(random.randint(0, 2) / 1000) queue.put((tid, fid, count)) reference.append((tid, fid, count)) def get_queue(count): for i in range(count): with lock: result.append(queue.get()) def thread_put(tid, nfibers, count): fibers = [] for i in range(nfibers): fibers.append(gruvi.spawn(put_queue, tid, i, count)) for fib in fibers: fib.join() gruvi.get_hub().close() def thread_get(nfibers, count): fibers = [] for i in range(nfibers): fibers.append(gruvi.spawn(get_queue, count)) for fib in fibers: fib.join() gruvi.get_hub().close() queue = gruvi.Queue() threads = [] # 5 procuders and 5 consumers, each with 20 fibers for i in range(5): thread = threading.Thread(target=thread_put, args=(i, 20, 5)) thread.start() threads.append(thread) for i in range(5): thread = threading.Thread(target=thread_get, args=(20, 5)) thread.start() threads.append(thread) for thread in threads: thread.join() gruvi.sleep(0) # run callbacks self.assertEqual(len(result), 500) self.assertEqual(result, reference) # Within a (tid,fid) pair, the counts must be monotonic partial_sort = sorted(result, key=lambda el: (el[0], el[1])) full_sort = sorted(result, key=lambda el: (el[0], el[1], el[2])) self.assertEqual(partial_sort, full_sort)
def test_get_timeout(self): # Ensure the "timeout" argument to Queue.get() works queue = gruvi.Queue() hub = get_hub() t0 = hub.loop.now() self.assertRaises(gruvi.QueueEmpty, queue.get, timeout=0.01) t1 = hub.loop.now() self.assertGreaterEqual(t1 - t0, 10)
def test_qsize(self): # The qsize() of a queue should by default be the number of elements queue = gruvi.Queue() for i in range(10): queue.put(10 + i) self.assertEqual(queue.qsize(), i + 1) for i in range(10): self.assertEqual(queue.get(), 10 + i) self.assertEqual(queue.qsize(), 10 - i - 1)
def test_put_timeout(self): # Ensure the "timeout" argument to Queue.put() works queue = gruvi.Queue(maxsize=10) queue.put('foo', size=10) hub = get_hub() t0 = hub.loop.now() self.assertRaises(gruvi.QueueFull, queue.put, 'bar', timeout=0.01) t1 = hub.loop.now() self.assertGreaterEqual(t1 - t0, 10)
def test_get_wait(self): # Queue.get() should wait until an item becomes available. queue = gruvi.Queue() def put_queue(value): gruvi.sleep(0.01) queue.put(value) gruvi.spawn(put_queue, 'foo') self.assertEqual(queue.get(), 'foo')
def test_qsize_custom_size(self): # The put() method has an optional "size" argument that allows you to # specify a custom size. queue = gruvi.Queue() for i in range(10): queue.put(10 + i, size=2) self.assertEqual(queue.qsize(), 2 * (i + 1)) for i in range(10): self.assertEqual(queue.get(), 10 + i) self.assertEqual(queue.qsize(), 2 * (10 - i - 1))
def test_task_done(self): # Ensure that task_done properly updates the unifished_tasks property. queue = gruvi.Queue() self.assertEqual(queue.unfinished_tasks, 0) queue.put('foo') self.assertEqual(queue.unfinished_tasks, 1) self.assertEqual(queue.get(), 'foo') self.assertEqual(queue.unfinished_tasks, 1) queue.task_done() self.assertEqual(queue.unfinished_tasks, 0) self.assertRaises(RuntimeError, queue.task_done) self.assertEqual(queue.unfinished_tasks, 0)
def test_join_wait(self): # Ensure that join() waits until all unfished tasks are done. queue = gruvi.Queue() self.assertEqual(queue.unfinished_tasks, 0) queue.put('foo') def consumer(): queue.get() gruvi.sleep(0.01) queue.task_done() gruvi.spawn(consumer) self.assertEqual(queue.unfinished_tasks, 1) queue.join() self.assertEqual(queue.unfinished_tasks, 0)
def test_full(self): # Ensure that empty() returns nonzero if the queue is empty. queue = gruvi.Queue(maxsize=1) self.assertFalse(queue.full()) queue.put('foo') self.assertTrue(queue.full())
def test_empty(self): # Ensure that empty() returns nonzero if the queue is empty. queue = gruvi.Queue() self.assertTrue(queue.empty()) queue.put('foo') self.assertFalse(queue.empty())
def test_put_non_blocking(self): # Ensure the "block" argument to Queue.put() works queue = gruvi.Queue(maxsize=10) queue.put('foo', size=10) self.assertRaises(gruvi.QueueFull, queue.put, 'bar', block=False) self.assertRaises(gruvi.QueueFull, queue.put_nowait, 'bar')
def test_get_non_blocking(self): # Ensure the "block" argument to Queue.get() works queue = gruvi.Queue() self.assertRaises(gruvi.QueueEmpty, queue.get, block=False) self.assertRaises(gruvi.QueueEmpty, queue.get_nowait)
def mem_queue(self): # In a Queue there's 2 conditions that share the same lock. queue = gruvi.Queue() self.add_result( sizeof(queue, exclude=('_lock', )) + sizeof(queue._lock))
def test_basic(self): # What is put in the queue, should come out. queue = gruvi.Queue() queue.put(10) self.assertEqual(queue.get(), 10)