示例#1
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)
示例#2
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)