class TestLocalRouter(PyonTestCase): def setUp(self): self.lr = LocalRouter(get_sys_name()) self.lr.start() self.addCleanup(self.lr.stop) # make a hook so we can tell when a message gets routed self.ev = Event() def new_route(*args, **kwargs): self.ev.set() self.lr._oldroute(*args, **kwargs) self.lr._oldroute = self.lr._route self.lr._route = new_route def test_publish_to_unknown_exchange(self): self.assertEquals(len(self.lr.errors), 0) self.lr.publish('ex', 'rkey', 'body', 'props') self.ev.wait(timeout=10) self.assertEquals(len(self.lr.errors), 1) def test_publish_to_known_exchange(self): # declare exchange self.lr.declare_exchange('known') # send message self.lr.publish('known', 'rkey', 'body', 'props') # wait for route self.ev.wait(timeout=10) # message is binned but no errors self.assertEquals(len(self.lr.errors), 0) def test_publish_to_queue(self): # declare exchange/queue/binding self.lr.declare_exchange('known') self.lr.declare_queue('iamqueue') self.lr.bind('known', 'iamqueue', 'binzim') self.assertEquals(self.lr._queues['iamqueue'].qsize(), 0) # send message self.lr.publish('known', 'binzim', 'body', 'props') # wait for route self.ev.wait(timeout=10) # should be sitting in a queue waiting self.assertEquals(self.lr._queues['iamqueue'].qsize(), 1) #self.assertIn(('known', 'binzim', 'body', 'props'), self.lr._queues['iamqueue']) def test_publish_to_many_queues(self): # declare exchange/queue/binding self.lr.declare_exchange('known') self.lr.declare_queue('q1') self.lr.bind('known', 'q1', 'a.*') self.lr.declare_queue('q2') self.lr.bind('known', 'q2', 'a.b') self.lr.declare_queue('q3') self.lr.bind('known', 'q3', '*.b') # send message self.lr.publish('known', 'a.b', 'body', 'props') # wait for route self.ev.wait(timeout=10) # should be in 3 queues for q in ['q1', 'q2', 'q3']: self.assertEquals(self.lr._queues[q].qsize(), 1) #self.assertIn(('known', 'a.b', 'body', 'props'), self.lr._queues[q]) def test_publish_to_queue_with_multiple_matching_binds_only_makes_one_message( self): # exchange/queue/bindings self.lr.declare_exchange('known') self.lr.declare_queue('iamqueue') self.lr.bind('known', 'iamqueue', 'a.*') self.lr.bind('known', 'iamqueue', 'a.b') self.lr.bind('known', 'iamqueue', '*.b') self.assertEquals(self.lr._queues['iamqueue'].qsize(), 0) # send message self.lr.publish('known', 'a.b', 'body', 'props') # wait for route self.ev.wait(timeout=10) # should be in the queue self.assertEquals(self.lr._queues['iamqueue'].qsize(), 1) #self.assertIn(('known', 'a.b', 'body', 'props'), self.lr._queues['iamqueue']) def test_publish_with_binds_and_unbinds(self): # declare exchange/queue self.lr.declare_exchange('known') self.lr.declare_queue('ein') self.assertEquals(self.lr._queues['ein'].qsize(), 0) # send message self.lr.publish('known', 'ein', 'body', 'props') # wait for route self.ev.wait(timeout=10) self.ev.clear() # we need to use again # not bound, so doesn't go into the queue self.assertEquals(self.lr._queues['ein'].qsize(), 0) # bind now self.lr.bind('known', 'ein', 'ein') # send message self.lr.publish('known', 'ein', 'body', 'props') # wait for route self.ev.wait(timeout=10) self.ev.clear() # we need to use again # should be in queue self.assertEquals(self.lr._queues['ein'].qsize(), 1) # send again self.lr.publish('known', 'ein', 'body', 'props') # wait for route self.ev.wait(timeout=10) self.ev.clear() # we need to use again # now 2 in queue self.assertEquals(self.lr._queues['ein'].qsize(), 2) # unbind self.lr.unbind('known', 'ein', 'ein') # send again self.lr.publish('known', 'ein', 'body', 'props') # wait for route self.ev.wait(timeout=10) self.ev.clear() # we need to use again # still 2 in queue self.assertEquals(self.lr._queues['ein'].qsize(), 2) def test__connect_addr(self): self.assertEquals(self.lr._connect_addr, "inproc://%s" % get_sys_name()) def test__child_failed(self): self.lr.gl_ioloop = Mock() fail = Mock() self.lr._child_failed(fail) self.lr.gl_ioloop.kill.assert_called_once_with( exception=fail.exception, block=False) def test__run_ioloop(self): self.lr._gl_pool = Mock() self.lr._run_ioloop() self.lr._gl_pool.join.assert_called_once_with() def test_declare_exchange(self): self.lr.declare_exchange(sentinel.exchange) self.assertIn(sentinel.exchange, self.lr._exchanges) self.assertIsInstance(self.lr._exchanges[sentinel.exchange], TopicTrie) def test_declare_exchange_existing(self): tt = TopicTrie() self.lr._exchanges[sentinel.exchange] = tt self.lr.declare_exchange(sentinel.exchange) self.assertEquals(tt, self.lr._exchanges[sentinel.exchange]) def test_delete_exchange(self): self.lr.declare_exchange(sentinel.exchange) self.lr.delete_exchange(sentinel.exchange) self.assertEquals(self.lr._exchanges, {}) def test_declare_queue(self): self.lr.declare_queue(sentinel.queue) self.assertIn(sentinel.queue, self.lr._queues) def test_declare_queue_made_up(self): q = self.lr.declare_queue('') self.assertIn("q-", q) self.assertIn(q, self.lr._queues) def test_delete_queue(self): self.lr.declare_queue(sentinel.queue) self.lr.delete_queue(sentinel.queue) self.assertNotIn(sentinel.queue, self.lr._queues) def test_delete_queue_deletes_bindings(self): self.lr.declare_exchange(sentinel.exchange) self.lr.declare_queue(sentinel.queue) self.lr.bind(sentinel.exchange, sentinel.queue, 'binder') self.lr.delete_queue(sentinel.queue) self.assertNotIn(sentinel.queue, self.lr._queues) self.assertNotIn(sentinel.queue, self.lr._bindings_by_queue) def test_start_consume(self): self.lr._gl_pool = Mock() self.lr.declare_queue(sentinel.queue) ctag = self.lr.start_consume(sentinel.callback, sentinel.queue) self.assertIn(sentinel.queue, self.lr._consumers) self.assertIn(ctag, self.lr._consumers_by_ctag) self.assertEquals(self.lr._consumers[sentinel.queue], [(ctag, sentinel.callback, False, False, self.lr._gl_pool.spawn.return_value)]) def test_stop_consume(self): self.lr._gl_pool = Mock() self.lr.declare_queue(sentinel.queue) ctag = self.lr.start_consume(sentinel.callback, sentinel.queue) self.lr.stop_consume(ctag) self.assertNotIn(ctag, self.lr._consumers_by_ctag) self.lr._gl_pool.spawn().join.assert_called_once_with(timeout=5) self.lr._gl_pool.spawn().kill.assert_called_once_with() self.assertEquals(len(self.lr._consumers[sentinel.queue]), 0) def test__run_consumer(self): propsmock = Mock() propsmock.copy.return_value = sentinel.props gqueue = Mock() m = (sentinel.exchange, sentinel.routing_key, sentinel.body, propsmock) gqueue.get.side_effect = [m, LocalRouter.ConsumerClosedMessage()] cb = Mock() self.lr._generate_dtag = Mock(return_value=sentinel.dtag) self.lr._run_consumer(sentinel.ctag, sentinel.queue, gqueue, cb) self.assertEquals(cb.call_count, 1) self.assertEquals(cb.call_args[0][0], self.lr) self.assertEquals( dict(cb.call_args[0][1]), { 'consumer_tag': sentinel.ctag, 'delivery_tag': sentinel.dtag, 'redelivered': False, 'exchange': sentinel.exchange, 'routing_key': sentinel.routing_key }) self.assertEquals(dict(cb.call_args[0][2]), {'headers': sentinel.props}) self.assertEquals(cb.call_args[0][3], sentinel.body) self.assertIn((sentinel.ctag, sentinel.queue, m), self.lr._unacked.itervalues()) def test__generate_ctag(self): self.lr._ctag_pool = Mock() self.lr._ctag_pool.get_id.return_value = sentinel.ctagid self.assertEquals(self.lr._generate_ctag(), "zctag-%s" % str(sentinel.ctagid)) def test__return_ctag(self): self.lr._ctag_pool = Mock() self.lr._return_ctag("m-5") self.lr._ctag_pool.release_id.assert_called_once_with(5) def test__generate_and_return_ctag(self): ctag = self.lr._generate_ctag() ctagnum = int(ctag.split("-")[-1]) self.assertIn(ctagnum, self.lr._ctag_pool._ids_in_use) self.lr._return_ctag(ctag) self.assertIn(ctagnum, self.lr._ctag_pool._ids_free) self.assertNotIn(ctagnum, self.lr._ctag_pool._ids_in_use) def test__generate_dtag(self): dtag = self.lr._generate_dtag(sentinel.ctag, sentinel.cnt) self.assertIn(str(sentinel.ctag), dtag) self.assertIn(str(sentinel.cnt), dtag) def test_ack(self): self.lr._unacked[sentinel.dtag] = True self.lr.ack(sentinel.dtag) self.assertEquals(len(self.lr._unacked), 0) def test_reject(self): self.lr._unacked[sentinel.dtag] = (None, None, None) self.lr.reject(sentinel.dtag) self.assertEquals(len(self.lr._unacked), 0) def test_reject_requeue(self): q = Mock() self.lr._queues[sentinel.queue] = q self.lr._unacked[sentinel.dtag] = (None, sentinel.queue, sentinel.m) self.lr.reject(sentinel.dtag, requeue=True) self.assertEquals(len(self.lr._unacked), 0) q.put.assert_called_once_with(sentinel.m) def test_transport_close(self): # no body in localrouter method pass def test_get_stats(self): self.lr.declare_queue(sentinel.queue) self.lr._queues[sentinel.queue].put(sentinel.m) mc, cc = self.lr.get_stats(sentinel.queue) self.assertEquals((mc, cc), (1, 0)) def test_get_stats_with_consumers(self): self.lr.declare_queue(sentinel.queue) self.lr._queues[sentinel.queue].put(sentinel.m) self.lr._consumers[sentinel.queue] = [sentinel.ctag] mc, cc = self.lr.get_stats(sentinel.queue) self.assertEquals((mc, cc), (1, 1)) def test_purge(self): self.lr.declare_queue(sentinel.queue) self.lr._queues[sentinel.queue].put(sentinel.m) self.assertEquals(self.lr._queues[sentinel.queue].qsize(), 1) self.lr.purge(sentinel.queue) self.assertEquals(self.lr._queues[sentinel.queue].qsize(), 0)
class TestLocalRouter(PyonTestCase): def setUp(self): self.lr = LocalRouter(get_sys_name()) self.lr.start() self.addCleanup(self.lr.stop) # make a hook so we can tell when a message gets routed self.ev = Event() def new_route(*args, **kwargs): self.ev.set() self.lr._oldroute(*args, **kwargs) self.lr._oldroute = self.lr._route self.lr._route = new_route def test_publish_to_unknown_exchange(self): self.assertEquals(len(self.lr.errors), 0) self.lr.publish('ex', 'rkey', 'body', 'props') self.ev.wait(timeout=10) self.assertEquals(len(self.lr.errors), 1) def test_publish_to_known_exchange(self): # declare exchange self.lr.declare_exchange('known') # send message self.lr.publish('known', 'rkey', 'body', 'props') # wait for route self.ev.wait(timeout=10) # message is binned but no errors self.assertEquals(len(self.lr.errors), 0) def test_publish_to_queue(self): # declare exchange/queue/binding self.lr.declare_exchange('known') self.lr.declare_queue('iamqueue') self.lr.bind('known', 'iamqueue', 'binzim') self.assertEquals(self.lr._queues['iamqueue'].qsize(), 0) # send message self.lr.publish('known', 'binzim', 'body', 'props') # wait for route self.ev.wait(timeout=10) # should be sitting in a queue waiting self.assertEquals(self.lr._queues['iamqueue'].qsize(), 1) #self.assertIn(('known', 'binzim', 'body', 'props'), self.lr._queues['iamqueue']) def test_publish_to_many_queues(self): # declare exchange/queue/binding self.lr.declare_exchange('known') self.lr.declare_queue('q1') self.lr.bind('known', 'q1', 'a.*') self.lr.declare_queue('q2') self.lr.bind('known', 'q2', 'a.b') self.lr.declare_queue('q3') self.lr.bind('known', 'q3', '*.b') # send message self.lr.publish('known', 'a.b', 'body', 'props') # wait for route self.ev.wait(timeout=10) # should be in 3 queues for q in ['q1','q2','q3']: self.assertEquals(self.lr._queues[q].qsize(), 1) #self.assertIn(('known', 'a.b', 'body', 'props'), self.lr._queues[q]) def test_publish_to_queue_with_multiple_matching_binds_only_makes_one_message(self): # exchange/queue/bindings self.lr.declare_exchange('known') self.lr.declare_queue('iamqueue') self.lr.bind('known', 'iamqueue', 'a.*') self.lr.bind('known', 'iamqueue', 'a.b') self.lr.bind('known', 'iamqueue', '*.b') self.assertEquals(self.lr._queues['iamqueue'].qsize(), 0) # send message self.lr.publish('known', 'a.b', 'body', 'props') # wait for route self.ev.wait(timeout=10) # should be in the queue self.assertEquals(self.lr._queues['iamqueue'].qsize(), 1) #self.assertIn(('known', 'a.b', 'body', 'props'), self.lr._queues['iamqueue']) def test_publish_with_binds_and_unbinds(self): # declare exchange/queue self.lr.declare_exchange('known') self.lr.declare_queue('ein') self.assertEquals(self.lr._queues['ein'].qsize(), 0) # send message self.lr.publish('known', 'ein', 'body', 'props') # wait for route self.ev.wait(timeout=10) self.ev.clear() # we need to use again # not bound, so doesn't go into the queue self.assertEquals(self.lr._queues['ein'].qsize(), 0) # bind now self.lr.bind('known', 'ein', 'ein') # send message self.lr.publish('known', 'ein', 'body', 'props') # wait for route self.ev.wait(timeout=10) self.ev.clear() # we need to use again # should be in queue self.assertEquals(self.lr._queues['ein'].qsize(), 1) # send again self.lr.publish('known', 'ein', 'body', 'props') # wait for route self.ev.wait(timeout=10) self.ev.clear() # we need to use again # now 2 in queue self.assertEquals(self.lr._queues['ein'].qsize(), 2) # unbind self.lr.unbind('known', 'ein', 'ein') # send again self.lr.publish('known', 'ein', 'body', 'props') # wait for route self.ev.wait(timeout=10) self.ev.clear() # we need to use again # still 2 in queue self.assertEquals(self.lr._queues['ein'].qsize(), 2) def test__connect_addr(self): self.assertEquals(self.lr._connect_addr, "inproc://%s" % get_sys_name()) def test__child_failed(self): self.lr.gl_ioloop = Mock() fail = Mock() self.lr._child_failed(fail) self.lr.gl_ioloop.kill.assert_called_once_with(exception=fail.exception, block=False) def test__run_ioloop(self): self.lr._gl_pool = Mock() self.lr._run_ioloop() self.lr._gl_pool.join.assert_called_once_with() def test_declare_exchange(self): self.lr.declare_exchange(sentinel.exchange) self.assertIn(sentinel.exchange, self.lr._exchanges) self.assertIsInstance(self.lr._exchanges[sentinel.exchange], TopicTrie) def test_declare_exchange_existing(self): tt = TopicTrie() self.lr._exchanges[sentinel.exchange] = tt self.lr.declare_exchange(sentinel.exchange) self.assertEquals(tt, self.lr._exchanges[sentinel.exchange]) def test_delete_exchange(self): self.lr.declare_exchange(sentinel.exchange) self.lr.delete_exchange(sentinel.exchange) self.assertEquals(self.lr._exchanges, {}) def test_declare_queue(self): self.lr.declare_queue(sentinel.queue) self.assertIn(sentinel.queue, self.lr._queues) def test_declare_queue_made_up(self): q = self.lr.declare_queue('') self.assertIn("q-", q) self.assertIn(q, self.lr._queues) def test_delete_queue(self): self.lr.declare_queue(sentinel.queue) self.lr.delete_queue(sentinel.queue) self.assertNotIn(sentinel.queue, self.lr._queues) def test_delete_queue_deletes_bindings(self): self.lr.declare_exchange(sentinel.exchange) self.lr.declare_queue(sentinel.queue) self.lr.bind(sentinel.exchange, sentinel.queue, 'binder') self.lr.delete_queue(sentinel.queue) self.assertNotIn(sentinel.queue, self.lr._queues) self.assertNotIn(sentinel.queue, self.lr._bindings_by_queue) def test_start_consume(self): self.lr._gl_pool = Mock() self.lr.declare_queue(sentinel.queue) ctag = self.lr.start_consume(sentinel.callback, sentinel.queue) self.assertIn(sentinel.queue, self.lr._consumers) self.assertIn(ctag, self.lr._consumers_by_ctag) self.assertEquals(self.lr._consumers[sentinel.queue], [(ctag, sentinel.callback, False, False, self.lr._gl_pool.spawn.return_value)]) def test_stop_consume(self): self.lr._gl_pool = Mock() self.lr.declare_queue(sentinel.queue) ctag = self.lr.start_consume(sentinel.callback, sentinel.queue) self.lr.stop_consume(ctag) self.assertNotIn(ctag, self.lr._consumers_by_ctag) self.lr._gl_pool.spawn().join.assert_called_once_with(timeout=5) self.lr._gl_pool.spawn().kill.assert_called_once_with() self.assertEquals(len(self.lr._consumers[sentinel.queue]), 0) def test__run_consumer(self): propsmock = Mock() propsmock.copy.return_value = sentinel.props gqueue = Mock() m = (sentinel.exchange, sentinel.routing_key, sentinel.body, propsmock) gqueue.get.side_effect = [m, LocalRouter.ConsumerClosedMessage()] cb = Mock() self.lr._generate_dtag=Mock(return_value=sentinel.dtag) self.lr._run_consumer(sentinel.ctag, sentinel.queue, gqueue, cb) self.assertEquals(cb.call_count, 1) self.assertEquals(cb.call_args[0][0], self.lr) self.assertEquals(dict(cb.call_args[0][1]), {'consumer_tag': sentinel.ctag, 'delivery_tag': sentinel.dtag, 'redelivered': False, 'exchange': sentinel.exchange, 'routing_key': sentinel.routing_key}) self.assertEquals(dict(cb.call_args[0][2]), {'headers':sentinel.props}) self.assertEquals(cb.call_args[0][3], sentinel.body) self.assertIn((sentinel.ctag, sentinel.queue, m), self.lr._unacked.itervalues()) def test__generate_ctag(self): self.lr._ctag_pool = Mock() self.lr._ctag_pool.get_id.return_value = sentinel.ctagid self.assertEquals(self.lr._generate_ctag(), "zctag-%s" % str(sentinel.ctagid)) def test__return_ctag(self): self.lr._ctag_pool = Mock() self.lr._return_ctag("m-5") self.lr._ctag_pool.release_id.assert_called_once_with(5) def test__generate_and_return_ctag(self): ctag = self.lr._generate_ctag() ctagnum = int(ctag.split("-")[-1]) self.assertIn(ctagnum, self.lr._ctag_pool._ids_in_use) self.lr._return_ctag(ctag) self.assertIn(ctagnum, self.lr._ctag_pool._ids_free) self.assertNotIn(ctagnum, self.lr._ctag_pool._ids_in_use) def test__generate_dtag(self): dtag = self.lr._generate_dtag(sentinel.ctag, sentinel.cnt) self.assertIn(str(sentinel.ctag), dtag) self.assertIn(str(sentinel.cnt), dtag) def test_ack(self): self.lr._unacked[sentinel.dtag] = True self.lr.ack(sentinel.dtag) self.assertEquals(len(self.lr._unacked), 0) def test_reject(self): self.lr._unacked[sentinel.dtag] = (None, None, None) self.lr.reject(sentinel.dtag) self.assertEquals(len(self.lr._unacked), 0) def test_reject_requeue(self): q = Mock() self.lr._queues[sentinel.queue] = q self.lr._unacked[sentinel.dtag] = (None, sentinel.queue, sentinel.m) self.lr.reject(sentinel.dtag, requeue=True) self.assertEquals(len(self.lr._unacked), 0) q.put.assert_called_once_with(sentinel.m) def test_transport_close(self): # no body in localrouter method pass def test_get_stats(self): self.lr.declare_queue(sentinel.queue) self.lr._queues[sentinel.queue].put(sentinel.m) mc, cc = self.lr.get_stats(sentinel.queue) self.assertEquals((mc, cc), (1, 0)) def test_get_stats_with_consumers(self): self.lr.declare_queue(sentinel.queue) self.lr._queues[sentinel.queue].put(sentinel.m) self.lr._consumers[sentinel.queue] = [sentinel.ctag] mc, cc = self.lr.get_stats(sentinel.queue) self.assertEquals((mc, cc), (1, 1)) def test_purge(self): self.lr.declare_queue(sentinel.queue) self.lr._queues[sentinel.queue].put(sentinel.m) self.assertEquals(self.lr._queues[sentinel.queue].qsize(), 1) self.lr.purge(sentinel.queue) self.assertEquals(self.lr._queues[sentinel.queue].qsize(), 0)