def _create_channel(self): """ Test helper method, creates mocked up broker interaction. """ ch = RecvChannel() ch._declare_exchange = Mock() ch._declare_queue = Mock() ch._declare_queue.return_value = sentinel.anon_queue ch._bind = Mock() return ch
def create_channel(): ch = RecvChannel() ch._declare_exchange = mxp ch._declare_queue = mdq ch._bind = mb return ch
class TestRecvChannel(PyonTestCase): def setUp(self): self.ch = RecvChannel() def _create_channel(self): """ Test helper method, creates mocked up broker interaction. """ ch = RecvChannel() ch._declare_exchange = Mock() ch._declare_queue = Mock() ch._declare_queue.return_value = sentinel.anon_queue ch._bind = Mock() return ch def test_setup_listener(self): # sub in mocks for _declare_exchange, _declare_queue, _bind mxp = Mock() mdq = Mock() mdq.return_value = sentinel.anon_queue mb = Mock() def create_channel(): ch = RecvChannel() ch._declare_exchange = mxp ch._declare_queue = mdq ch._bind = mb return ch ch = create_channel() self.assertFalse(ch._setup_listener_called) # call setup listener, defining xp, queue, binding ch.setup_listener( NameTrio(sentinel.xp, sentinel.queue, sentinel.binding)) self.assertTrue(hasattr(ch, '_recv_name')) self.assertTrue(hasattr(ch._recv_name, 'exchange')) self.assertTrue(hasattr(ch._recv_name, 'queue')) self.assertEquals(ch._recv_name.exchange, sentinel.xp) self.assertEquals(ch._recv_name.queue, sentinel.queue) mxp.assert_called_once_with(sentinel.xp) mdq.assert_called_once_with(sentinel.queue) mb.assert_called_once_with(sentinel.binding) # you can only call setup_listener once self.assertTrue(ch._setup_listener_called) # calling it again does nothing, does not touch anything ch.setup_listener(NameTrio(sentinel.xp2, sentinel.queue2)) self.assertTrue(hasattr(ch._recv_name, 'exchange')) self.assertTrue(hasattr(ch._recv_name, 'queue')) self.assertEquals(ch._recv_name.exchange, sentinel.xp) self.assertEquals(ch._recv_name.queue, sentinel.queue) mxp.assert_called_once_with(sentinel.xp) mdq.assert_called_once_with(sentinel.queue) mb.assert_called_once_with(sentinel.binding) # call setup listener, passing a custom bind this time ch = create_channel() ch.setup_listener(NameTrio(sentinel.xp2, sentinel.queue2), binding=sentinel.binding) mxp.assert_called_with(sentinel.xp2) mdq.assert_called_with(sentinel.queue2) mb.assert_called_with(sentinel.binding) # call setup_listener, use anonymous queue name and no binding (will get return value we set above) ch = create_channel() ch.setup_listener(NameTrio(sentinel.xp3)) mxp.assert_called_with(sentinel.xp3) mdq.assert_called_with(None) mb.assert_called_with(sentinel.anon_queue) # call setup_listener with anon queue name but with binding ch = create_channel() ch.setup_listener(NameTrio(sentinel.xp4), binding=sentinel.binding2) mxp.assert_called_with(sentinel.xp4) mdq.assert_called_with(None) mb.assert_called_with(sentinel.binding2) def test_setup_listener_existing_recv_name(self): ch = self._create_channel() recv_name = NameTrio(sentinel.xp, sentinel.queue, sentinel.binding) ch._recv_name = recv_name ch.setup_listener() self.assertEquals(ch._recv_name, recv_name) def test_setup_listener_existing_recv_name_with_differing_name(self): ch = self._create_channel() recv_name = NameTrio(sentinel.xp, sentinel.queue, sentinel.binding) ch._recv_name = recv_name ch.setup_listener( name=NameTrio(sentinel.xp, sentinel.queue, sentinel.notbinding)) self.assertNotEquals(ch._recv_name, recv_name) self.assertEquals(ch._recv_name.exchange, sentinel.xp) self.assertEquals(ch._recv_name.queue, sentinel.queue) self.assertEquals(ch._recv_name.binding, sentinel.notbinding) def test__destroy_queue_no_recv_name(self): self.assertRaises(AssertionError, self.ch.destroy_listener) def test__destroy_queue(self): self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch._transport = Mock(BaseTransport) self.ch._amq_chan = sentinel.amq_chan self.ch.destroy_listener() self.assertTrue(self.ch._transport.delete_queue_impl.called) self.assertIn('queue', self.ch._transport.delete_queue_impl.call_args[1]) self.assertIn( sentinel.queue, self.ch._transport.delete_queue_impl.call_args[1].itervalues()) def test_destroy_listener(self): m = Mock() self.ch._destroy_queue = m self.ch.destroy_listener() m.assert_called_once_with() def test__destroy_binding_no_recv_name_or_binding(self): self.assertRaises(AssertionError, self.ch._destroy_binding) def test__destroy_binding(self): self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch._recv_binding = sentinel.binding self.ch._transport = Mock(BaseTransport) self.ch._amq_chan = sentinel.amq_chan self.ch._destroy_binding() self.assertTrue(self.ch._transport.unbind_impl.called) self.assertIn('queue', self.ch._transport.unbind_impl.call_args[1]) self.assertIn('exchange', self.ch._transport.unbind_impl.call_args[1]) self.assertIn('binding', self.ch._transport.unbind_impl.call_args[1]) self.assertIn(sentinel.queue, self.ch._transport.unbind_impl.call_args[1].itervalues()) self.assertIn(sentinel.xp, self.ch._transport.unbind_impl.call_args[1].itervalues()) self.assertIn(sentinel.binding, self.ch._transport.unbind_impl.call_args[1].itervalues()) def test_start_consume(self): ac = Mock(pchannel.Channel) self.ch._amq_chan = ac self.ch._fsm.current_state = self.ch.S_ACTIVE ac.basic_consume.return_value = sentinel.consumer_tag # set up recv name for queue self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch.start_consume() self.assertEquals(self.ch._fsm.current_state, self.ch.S_CONSUMING) self.assertEquals(self.ch._consumer_tag, sentinel.consumer_tag) ac.basic_consume.assert_called_once_with( self.ch._on_deliver, queue=sentinel.queue, no_ack=self.ch._consumer_no_ack, exclusive=self.ch._consumer_exclusive) def test_start_consume_already_started(self): self.ch._fsm.current_state = self.ch.S_CONSUMING self.assertRaises(ExceptionFSM, self.ch.start_consume) @patch('pyon.net.channel.log') def test_start_consume_with_consumer_tag_and_auto_delete(self, mocklog): ac = Mock(pchannel.Channel) self.ch._amq_chan = ac self.ch._fsm.current_state = self.ch.S_ACTIVE # set up recv name for queue self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch._consumer_tag = sentinel.consumer_tag self.ch._queue_auto_delete = True self.ch.start_consume() self.assertTrue(mocklog.warn.called) def test_stop_consume(self): ac = Mock(pchannel.Channel) self.ch._amq_chan = ac # pretend we're consuming self.ch._fsm.current_state = self.ch.S_CONSUMING # callback sideffect! def basic_cancel_side(*args, **kwargs): cbparam = kwargs.get('callback') cbparam() ac.basic_cancel.side_effect = basic_cancel_side # set a sentinel as our consumer tag self.ch._consumer_tag = sentinel.consumer_tag # now make the call self.ch.stop_consume() self.assertEquals(self.ch._fsm.current_state, self.ch.S_ACTIVE) self.assertTrue(ac.basic_cancel.called) self.assertIn(sentinel.consumer_tag, ac.basic_cancel.call_args[0]) def test_stop_consume_havent_started(self): # we're not consuming, so this should raise self.ch._fsm.current_state = self.ch.S_ACTIVE self.assertRaises(ExceptionFSM, self.ch.stop_consume) @patch('pyon.net.channel.log') def test_stop_consume_raises_warning_with_auto_delete(self, mocklog): ac = Mock(pchannel.Channel) self.ch._amq_chan = ac self.ch._consumer_tag = sentinel.consumer_tag self.ch._recv_name = NameTrio(sentinel.ex, sentinel.queue, sentinel.binding) self.ch._fsm.current_state = self.ch.S_CONSUMING self.ch._ensure_amq_chan = Mock() self.ch._sync_call = Mock() self.ch._queue_auto_delete = True self.ch.stop_consume() self.assertTrue(mocklog.debug.called) self.assertIn(sentinel.queue, mocklog.debug.call_args[0]) def test_recv(self): # replace recv_queue with a mock obj rqmock = Mock(spec=queue.Queue) self.ch._recv_queue = rqmock rqmock.get.return_value = sentinel.recv m = self.ch.recv() self.assertEquals(m, sentinel.recv) self.assertTrue(rqmock.get.called) def test_recv_shutdown(self): # replace recv_queue with a mock obj rqmock = Mock(spec=queue.Queue) self.ch._recv_queue = rqmock rqmock.get.return_value = ChannelShutdownMessage() self.assertRaises(ChannelClosedError, self.ch.recv) @patch('pyon.net.channel.BaseChannel') @patch('pyon.net.channel.ChannelShutdownMessage') @patch('pyon.net.channel.log', Mock()) # to avoid having to put it in signature def test_close_impl(self, mockshutdown, mockbasechannel): # no auto stop consuming, no auto delete of queue without recv_name set # should have a shutdown message inserted mockrq = Mock(spec=queue.Queue) self.ch._recv_queue = mockrq self.ch.close_impl() # odd test quirk: have to assert mockshutdown was called once here (by close_impl), # before i can test that put was called with it, becuase i have to call it again just # to get the return value of it. mockshutdown.assert_called_once_with() mockrq.put.assert_called_once_with(mockshutdown()) mockbasechannel.close_impl.assert_called_once_with(self.ch) def test_declare_queue(self): self.ch._transport = Mock(BaseTransport) self.ch._amq_chan = sentinel.amq_chan # needs a recv name self.ch._recv_name = (NameTrio(str(sentinel.xp))) qd = self.ch._declare_queue(str( sentinel.queue)) # can't join a sentinel self.assertTrue(self.ch._transport.declare_queue_impl.called) self.assertIn('queue', self.ch._transport.declare_queue_impl.call_args[1]) self.assertIn('auto_delete', self.ch._transport.declare_queue_impl.call_args[1]) self.assertIn('durable', self.ch._transport.declare_queue_impl.call_args[1]) composed = ".".join([str(sentinel.xp), str(sentinel.queue)]) self.assertIn( composed, self.ch._transport.declare_queue_impl.call_args[1].itervalues()) self.assertIn( self.ch._queue_auto_delete, self.ch._transport.declare_queue_impl.call_args[1].itervalues()) self.assertIn( self.ch._queue_durable, self.ch._transport.declare_queue_impl.call_args[1].itervalues()) # should have set recv_name self.assertTrue(hasattr(self.ch._recv_name, 'exchange')) self.assertTrue(hasattr(self.ch._recv_name, 'queue')) self.assertEquals(self.ch._recv_name.exchange, str(sentinel.xp)) # we passed in str() versions self.assertEquals(self.ch._recv_name.queue, self.ch._transport.declare_queue_impl()) self.assertEquals(qd, self.ch._transport.declare_queue_impl()) def test__bind_no_name(self): self.assertRaises(AssertionError, self.ch._bind, sentinel.binding) def test__bind(self): self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch._amq_chan = Mock() self.ch._transport = Mock() self.ch._bind(sentinel.binding) self.assertTrue(self.ch._transport.bind_impl.called) self.assertIn('queue', self.ch._transport.bind_impl.call_args[1]) self.assertIn('exchange', self.ch._transport.bind_impl.call_args[1]) self.assertIn('binding', self.ch._transport.bind_impl.call_args[1]) self.assertIn(sentinel.queue, self.ch._transport.bind_impl.call_args[1].itervalues()) self.assertIn(sentinel.xp, self.ch._transport.bind_impl.call_args[1].itervalues()) self.assertIn(sentinel.binding, self.ch._transport.bind_impl.call_args[1].itervalues()) def test__on_deliver(self): # mock up the method frame (delivery_tag is really only one we care about) m = Mock() m.consumer_tag = sentinel.consumer_tag m.delivery_tag = sentinel.delivery_tag m.redelivered = sentinel.redelivered m.exchange = sentinel.exchange m.routing_key = sentinel.routing_key # mock up the header-frame h = Mock() h.headers = {'this_exists': sentinel.exists} # use a mock for the recv queue rqmock = Mock(spec=queue.Queue) self.ch._recv_queue = rqmock # now we can call! self.ch._on_deliver(sentinel.chan, m, h, sentinel.body) # assert the call rqmock.put.assert_called_once_with( (sentinel.body, h.headers, sentinel.delivery_tag)) # assert the headers look ok self.assertIn(sentinel.exists, rqmock.put.call_args[0][0][1].itervalues()) def test_ack(self): ac = Mock(spec=pchannel.Channel) self.ch._amq_chan = ac self.ch.ack(sentinel.delivery_tag) ac.basic_ack.assert_called_once_with(sentinel.delivery_tag) def test_reject(self): ac = Mock(spec=pchannel.Channel) self.ch._amq_chan = ac self.ch.reject(sentinel.delivery_tag, requeue=True) ac.basic_reject.assert_called_once_with(sentinel.delivery_tag, requeue=True) def test_reset(self): self.ch.reset() self.assertEquals(self.ch._fsm.current_state, self.ch.S_INIT) def test_reset_when_consuming(self): # have to setup a lot here, can't just mock # _on_stop_consume because the FSM holds onto it ac = Mock(pchannel.Channel) self.ch._amq_chan = ac # pretend we're consuming self.ch._fsm.current_state = self.ch.S_CONSUMING # callback sideffect! def basic_cancel_side(*args, **kwargs): cbparam = kwargs.get('callback') cbparam() ac.basic_cancel.side_effect = basic_cancel_side # set a sentinel as our consumer tag self.ch._consumer_tag = sentinel.consumer_tag self.ch.reset() self.assertEquals(self.ch._fsm.current_state, self.ch.S_ACTIVE) self.assertTrue(ac.basic_cancel.called) def test_get_stats(self): self.ch._amq_chan = sentinel.amq_chan self.ch._transport = Mock() self.ch._recv_name = NameTrio(sentinel.ex, sentinel.queue) self.ch.get_stats() self.ch._transport.get_stats.assert_called_once_with( sentinel.amq_chan, queue=sentinel.queue)
class TestRecvChannel(PyonTestCase): def setUp(self): self.ch = RecvChannel() def _create_channel(self): """ Test helper method, creates mocked up broker interaction. """ ch = RecvChannel() ch._declare_exchange = Mock() ch._declare_queue = Mock() ch._declare_queue.return_value = sentinel.anon_queue ch._bind = Mock() return ch def test_setup_listener(self): # sub in mocks for _declare_exchange, _declare_queue, _bind mxp = Mock() mdq = Mock() mdq.return_value = sentinel.anon_queue mb = Mock() def create_channel(): ch = RecvChannel() ch._declare_exchange = mxp ch._declare_queue = mdq ch._bind = mb return ch ch = create_channel() self.assertFalse(ch._setup_listener_called) # call setup listener, defining xp, queue, binding ch.setup_listener(NameTrio(sentinel.xp, sentinel.queue, sentinel.binding)) self.assertTrue(hasattr(ch, '_recv_name')) self.assertTrue(hasattr(ch._recv_name, 'exchange')) self.assertTrue(hasattr(ch._recv_name, 'queue')) self.assertEquals(ch._recv_name.exchange, sentinel.xp) self.assertEquals(ch._recv_name.queue, sentinel.queue) mxp.assert_called_once_with(sentinel.xp) mdq.assert_called_once_with(sentinel.queue) mb.assert_called_once_with(sentinel.binding) # you can only call setup_listener once self.assertTrue(ch._setup_listener_called) # calling it again does nothing, does not touch anything ch.setup_listener(NameTrio(sentinel.xp2, sentinel.queue2)) self.assertTrue(hasattr(ch._recv_name, 'exchange')) self.assertTrue(hasattr(ch._recv_name, 'queue')) self.assertEquals(ch._recv_name.exchange, sentinel.xp) self.assertEquals(ch._recv_name.queue, sentinel.queue) mxp.assert_called_once_with(sentinel.xp) mdq.assert_called_once_with(sentinel.queue) mb.assert_called_once_with(sentinel.binding) # call setup listener, passing a custom bind this time ch = create_channel() ch.setup_listener(NameTrio(sentinel.xp2, sentinel.queue2), binding=sentinel.binding) mxp.assert_called_with(sentinel.xp2) mdq.assert_called_with(sentinel.queue2) mb.assert_called_with(sentinel.binding) # call setup_listener, use anonymous queue name and no binding (will get return value we set above) ch = create_channel() ch.setup_listener(NameTrio(sentinel.xp3)) mxp.assert_called_with(sentinel.xp3) mdq.assert_called_with(None) mb.assert_called_with(sentinel.anon_queue) # call setup_listener with anon queue name but with binding ch = create_channel() ch.setup_listener(NameTrio(sentinel.xp4), binding=sentinel.binding2) mxp.assert_called_with(sentinel.xp4) mdq.assert_called_with(None) mb.assert_called_with(sentinel.binding2) def test_setup_listener_existing_recv_name(self): ch = self._create_channel() recv_name = NameTrio(sentinel.xp, sentinel.queue, sentinel.binding) ch._recv_name = recv_name ch.setup_listener() self.assertEquals(ch._recv_name, recv_name) def test_setup_listener_existing_recv_name_with_differing_name(self): ch = self._create_channel() recv_name = NameTrio(sentinel.xp, sentinel.queue, sentinel.binding) ch._recv_name = recv_name ch.setup_listener(name=NameTrio(sentinel.xp, sentinel.queue, sentinel.notbinding)) self.assertNotEquals(ch._recv_name, recv_name) self.assertEquals(ch._recv_name.exchange, sentinel.xp) self.assertEquals(ch._recv_name.queue, sentinel.queue) self.assertEquals(ch._recv_name.binding, sentinel.notbinding) def test__destroy_queue_no_recv_name(self): self.assertRaises(AssertionError, self.ch.destroy_listener) def test__destroy_queue(self): self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch.on_channel_open(Mock(BaseTransport)) self.ch.destroy_listener() self.assertTrue(self.ch._transport.delete_queue_impl.called) self.assertIn('queue', self.ch._transport.delete_queue_impl.call_args[1]) self.assertIn(sentinel.queue, self.ch._transport.delete_queue_impl.call_args[1].itervalues()) def test_destroy_listener(self): m = Mock() self.ch._destroy_queue = m self.ch.destroy_listener() m.assert_called_once_with() def test__destroy_binding_no_recv_name_or_binding(self): self.assertRaises(AssertionError, self.ch._destroy_binding) def test__destroy_binding(self): self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch._recv_binding = sentinel.binding self.ch.on_channel_open(Mock(BaseTransport)) self.ch._destroy_binding() self.assertTrue(self.ch._transport.unbind_impl.called) self.assertIn('queue', self.ch._transport.unbind_impl.call_args[1]) self.assertIn('exchange', self.ch._transport.unbind_impl.call_args[1]) self.assertIn('binding', self.ch._transport.unbind_impl.call_args[1]) self.assertIn(sentinel.queue, self.ch._transport.unbind_impl.call_args[1].itervalues()) self.assertIn(sentinel.xp, self.ch._transport.unbind_impl.call_args[1].itervalues()) self.assertIn(sentinel.binding, self.ch._transport.unbind_impl.call_args[1].itervalues()) def test_start_consume(self): transport = MagicMock() self.ch.on_channel_open(transport) self.ch._fsm.current_state = self.ch.S_ACTIVE transport.start_consume_impl.return_value = sentinel.consumer_tag # set up recv name for queue self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch.start_consume() self.assertTrue(self.ch._consuming) self.assertEquals(self.ch._fsm.current_state, self.ch.S_ACTIVE) self.assertEquals(self.ch._consumer_tag, sentinel.consumer_tag) transport.start_consume_impl.assert_called_once_with(self.ch._on_deliver, queue=sentinel.queue, no_ack=self.ch._consumer_no_ack, exclusive=self.ch._consumer_exclusive) def test_start_consume_already_started(self): self.ch._on_start_consume = Mock() self.ch._consuming = True self.ch.start_consume() # noops due to consuming flag already on self.assertFalse(self.ch._on_start_consume.called) @patch('pyon.net.channel.log') def test_start_consume_with_consumer_tag_and_auto_delete(self, mocklog): transport = AMQPTransport(Mock()) self.ch.on_channel_open(transport) self.ch._fsm.current_state = self.ch.S_ACTIVE # set up recv name for queue self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch._consumer_tag = sentinel.consumer_tag self.ch._queue_auto_delete = True self.ch.start_consume() self.assertTrue(mocklog.warn.called) def test_stop_consume(self): transport = MagicMock() self.ch.on_channel_open(transport) # pretend we're consuming self.ch._fsm.current_state = self.ch.S_ACTIVE self.ch._consuming = True # set a sentinel as our consumer tag self.ch._consumer_tag = sentinel.consumer_tag # now make the call self.ch.stop_consume() self.assertEquals(self.ch._fsm.current_state, self.ch.S_ACTIVE) self.assertFalse(self.ch._consuming) self.assertTrue(transport.stop_consume_impl.called) self.assertIn(sentinel.consumer_tag, transport.stop_consume_impl.call_args[0]) def test_stop_consume_havent_started(self): self.ch._on_stop_consume = Mock() self.ch.stop_consume() self.assertFalse(self.ch._on_stop_consume.called) def test_stop_consume_raises_warning_with_auto_delete(self): transport = AMQPTransport(Mock()) transport.stop_consume_impl = Mock() self.ch.on_channel_open(transport) #transport.channel_number = sentinel.channel_number self.ch._consumer_tag = sentinel.consumer_tag self.ch._recv_name = NameTrio(sentinel.ex, sentinel.queue, sentinel.binding) self.ch._fsm.current_state = self.ch.S_ACTIVE self.ch._consuming = True #self.ch._ensure_transport = MagicMock() self.ch._queue_auto_delete = True self.ch.stop_consume() self.assertTrue(self.ch._transport.stop_consume_impl.called) self.assertIn(self.ch._consumer_tag, self.ch._transport.stop_consume_impl.call_args[0]) def test_recv(self): # replace recv_queue with a mock obj rqmock = Mock(spec=RecvChannel.SizeNotifyQueue) self.ch._recv_queue = rqmock rqmock.get.return_value = sentinel.recv m = self.ch.recv() self.assertEquals(m, sentinel.recv) self.assertTrue(rqmock.get.called) def test_recv_shutdown(self): # replace recv_queue with a mock obj rqmock = Mock(spec=RecvChannel.SizeNotifyQueue) self.ch._recv_queue = rqmock rqmock.get.return_value = ChannelShutdownMessage() self.assertRaises(ChannelClosedError, self.ch.recv) @patch('pyon.net.channel.BaseChannel') @patch('pyon.net.channel.ChannelShutdownMessage') @patch('pyon.net.channel.log', Mock()) # to avoid having to put it in signature def test_close_impl(self, mockshutdown, mockbasechannel): # no auto stop consuming, no auto delete of queue without recv_name set # should have a shutdown message inserted mockrq = Mock(spec=RecvChannel.SizeNotifyQueue) self.ch._recv_queue = mockrq self.ch.close_impl() # odd test quirk: have to assert mockshutdown was called once here (by close_impl), # before i can test that put was called with it, becuase i have to call it again just # to get the return value of it. mockshutdown.assert_called_once_with() mockrq.put.assert_called_once_with(mockshutdown()) mockbasechannel.close_impl.assert_called_once_with(self.ch) def test_declare_queue(self): self.ch.on_channel_open(Mock(BaseTransport)) # needs a recv name self.ch._recv_name = (NameTrio(str(sentinel.xp))) qd = self.ch._declare_queue(str(sentinel.queue)) # can't join a sentinel self.assertTrue(self.ch._transport.declare_queue_impl.called) self.assertIn('queue', self.ch._transport.declare_queue_impl.call_args[1]) self.assertIn('auto_delete', self.ch._transport.declare_queue_impl.call_args[1]) self.assertIn('durable', self.ch._transport.declare_queue_impl.call_args[1]) composed = ".".join([str(sentinel.xp), str(sentinel.queue)]) self.assertIn(composed, self.ch._transport.declare_queue_impl.call_args[1].itervalues()) self.assertIn(self.ch.queue_auto_delete, self.ch._transport.declare_queue_impl.call_args[1].itervalues()) self.assertIn(self.ch.queue_durable, self.ch._transport.declare_queue_impl.call_args[1].itervalues()) # should have set recv_name self.assertTrue(hasattr(self.ch._recv_name, 'exchange')) self.assertTrue(hasattr(self.ch._recv_name, 'queue')) self.assertEquals(self.ch._recv_name.exchange, str(sentinel.xp)) # we passed in str() versions self.assertEquals(self.ch._recv_name.queue, self.ch._transport.declare_queue_impl()) self.assertEquals(qd, self.ch._transport.declare_queue_impl()) def test__bind_no_name(self): self.assertRaises(AssertionError, self.ch._bind, sentinel.binding) def test__bind(self): self.ch._recv_name = NameTrio(sentinel.xp, sentinel.queue) self.ch.on_channel_open(Mock()) self.ch._bind(sentinel.binding) self.assertTrue(self.ch._transport.bind_impl.called) self.assertIn('queue', self.ch._transport.bind_impl.call_args[1]) self.assertIn('exchange', self.ch._transport.bind_impl.call_args[1]) self.assertIn('binding', self.ch._transport.bind_impl.call_args[1]) self.assertIn(sentinel.queue, self.ch._transport.bind_impl.call_args[1].itervalues()) self.assertIn(sentinel.xp, self.ch._transport.bind_impl.call_args[1].itervalues()) self.assertIn(sentinel.binding, self.ch._transport.bind_impl.call_args[1].itervalues()) def test__on_deliver(self): # mock up the method frame (delivery_tag is really only one we care about) m = Mock() m.consumer_tag = sentinel.consumer_tag m.delivery_tag = sentinel.delivery_tag m.redelivered = sentinel.redelivered m.exchange = sentinel.exchange m.routing_key = sentinel.routing_key # mock up the header-frame h = Mock() h.headers = { 'this_exists': sentinel.exists } # use a mock for the recv queue rqmock = Mock(spec=RecvChannel.SizeNotifyQueue) self.ch._recv_queue = rqmock # now we can call! self.ch._on_deliver(sentinel.chan, m, h, sentinel.body) # assert the call rqmock.put.assert_called_once_with((sentinel.body, h.headers, sentinel.delivery_tag)) # assert the headers look ok self.assertIn(sentinel.exists, rqmock.put.call_args[0][0][1].itervalues()) def test_ack(self): transport = Mock() transport.channel_number = sentinel.channel_number self.ch.on_channel_open(transport) self.ch.ack(sentinel.delivery_tag) transport.ack_impl.assert_called_once_with(sentinel.delivery_tag) def test_reject(self): transport = Mock() transport.channel_number = sentinel.channel_number self.ch.on_channel_open(transport) self.ch.reject(sentinel.delivery_tag, requeue=True) transport.reject_impl.assert_called_once_with(sentinel.delivery_tag, requeue=True) def test_reset(self): self.ch.reset() self.assertEquals(self.ch._fsm.current_state, self.ch.S_INIT) def test_reset_when_consuming(self): # have to setup a lot here, can't just mock # _on_stop_consume because the FSM holds onto it transport = MagicMock() self.ch.on_channel_open(transport) # pretend we're consuming self.ch._fsm.current_state = self.ch.S_ACTIVE self.ch._consuming = True # set a sentinel as our consumer tag self.ch._consumer_tag = sentinel.consumer_tag self.ch.reset() self.assertEquals(self.ch._fsm.current_state, self.ch.S_ACTIVE) self.assertTrue(transport.stop_consume_impl.called) def test_get_stats(self): transport = Mock() self.ch.on_channel_open(transport) self.ch._recv_name = NameTrio(sentinel.ex, sentinel.queue) self.ch.get_stats() self.ch._transport.get_stats_impl.assert_called_once_with(queue=sentinel.queue) def test_purge(self): transport = Mock() self.ch.on_channel_open(transport) self.ch._recv_name = NameTrio(sentinel.ex, sentinel.queue) self.ch._purge() self.ch._transport.purge_impl.assert_called_once_with(queue=sentinel.queue)
class TestRecvChannel(PyonTestCase): def setUp(self): self.ch = RecvChannel() def test_setup_listener(self): # sub in mocks for _declare_exchange_point, _declare_queue, _bind mxp = Mock() mdq = Mock() mdq.return_value = sentinel.anon_queue mb = Mock() def create_channel(): ch = RecvChannel() ch._declare_exchange_point = mxp ch._declare_queue = mdq ch._bind = mb return ch ch = create_channel() self.assertFalse(ch._setup_listener_called) # call setup listener, defining xp, queue, default binding (will get our return value above) becuase there's no meat to _declare_queue ch.setup_listener((sentinel.xp, sentinel.queue)) self.assertTrue(hasattr(ch, '_recv_name')) self.assertEquals(ch._recv_name, (sentinel.xp, sentinel.queue)) mxp.assert_called_once_with(sentinel.xp) mdq.assert_called_once_with(sentinel.queue) mb.assert_called_once_with(sentinel.anon_queue) # you can only call setup_listener once self.assertTrue(ch._setup_listener_called) # calling it again does nothing, does not touch anything ch.setup_listener((sentinel.xp2, sentinel.queue2)) self.assertEquals(ch._recv_name, (sentinel.xp, sentinel.queue)) mxp.assert_called_once_with(sentinel.xp) mdq.assert_called_once_with(sentinel.queue) mb.assert_called_once_with(sentinel.anon_queue) # call setup listener, passing a custom bind this time ch = create_channel() ch.setup_listener((sentinel.xp2, sentinel.queue2), binding=sentinel.binding) mxp.assert_called_with(sentinel.xp2) mdq.assert_called_with(sentinel.queue2) mb.assert_called_with(sentinel.binding) # call setup_listener, use anonymous queue name and no binding (will get return value we set above) ch = create_channel() ch.setup_listener((sentinel.xp3, None)) mxp.assert_called_with(sentinel.xp3) mdq.assert_called_with(None) mb.assert_called_with(sentinel.anon_queue) # call setup_listener with anon queue name but with binding ch = create_channel() ch.setup_listener((sentinel.xp4, None), binding=sentinel.binding2) mxp.assert_called_with(sentinel.xp4) mdq.assert_called_with(None) mb.assert_called_with(sentinel.binding2) def test__destroy_queue_no_recv_name(self): self.assertRaises(AssertionError, self.ch.destroy_listener) def test__destroy_queue(self): self.ch._recv_name = (sentinel.xp, sentinel.queue) def side(*args, **kwargs): cb = kwargs.get('callback') cb() ac = Mock(spec=pchannel.Channel) self.ch._amq_chan = ac ac.queue_delete.side_effect = side self.ch.destroy_listener() self.assertTrue(ac.queue_delete.called) self.assertIn('queue', ac.queue_delete.call_args[1]) self.assertIn(sentinel.queue, ac.queue_delete.call_args[1].itervalues()) def test_destroy_listener(self): m = Mock() self.ch._destroy_queue = m self.ch.destroy_listener() m.assert_called_once_with() def test__destroy_binding_no_recv_name_or_binding(self): self.assertRaises(AssertionError, self.ch._destroy_binding) def test__destroy_binding(self): self.ch._recv_name = (sentinel.xp, sentinel.queue) self.ch._recv_binding = sentinel.binding def side(*args, **kwargs): cb = kwargs.get('callback') cb() ac = Mock(spec=pchannel.Channel) self.ch._amq_chan = ac ac.queue_unbind.side_effect = side self.ch._destroy_binding() self.assertTrue(ac.queue_unbind.called) self.assertIn('queue', ac.queue_unbind.call_args[1]) self.assertIn('exchange', ac.queue_unbind.call_args[1]) self.assertIn('routing_key', ac.queue_unbind.call_args[1]) self.assertIn(sentinel.queue, ac.queue_unbind.call_args[1].itervalues()) self.assertIn(sentinel.xp, ac.queue_unbind.call_args[1].itervalues()) self.assertIn(sentinel.binding, ac.queue_unbind.call_args[1].itervalues()) def test_start_consume(self): ac = Mock(pchannel.Channel) self.ch._amq_chan = ac ac.basic_consume.return_value = sentinel.consumer_tag # set up recv name for queue self.ch._recv_name = (sentinel.xp, sentinel.queue) self.ch.start_consume() self.assertTrue(self.ch._consuming) self.assertEquals(self.ch._consumer_tag, sentinel.consumer_tag) ac.basic_consume.assert_called_once_with(self.ch._on_deliver, queue=sentinel.queue, no_ack=self.ch._consumer_no_ack, exclusive=self.ch._consumer_exclusive) def test_start_consume_already_started(self): self.ch._consuming = True self.assertRaises(ChannelError, self.ch.start_consume) @patch('pyon.net.channel.log') def test_start_consume_with_consumer_tag_and_auto_delete(self, mocklog): ac = Mock(pchannel.Channel) self.ch._amq_chan = ac # set up recv name for queue self.ch._recv_name = (sentinel.xp, sentinel.queue) self.ch._consumer_tag = sentinel.consumer_tag self.ch._queue_auto_delete = True self.ch.start_consume() self.assertTrue(mocklog.warn.called) def test_stop_consume(self): ac = Mock(pchannel.Channel) self.ch._amq_chan = ac # pretend we're consuming self.ch._consuming = True # callback sideffect! def basic_cancel_side(*args, **kwargs): cbparam = kwargs.get('callback') cbparam() ac.basic_cancel.side_effect = basic_cancel_side # set a sentinel as our consumer tag self.ch._consumer_tag = sentinel.consumer_tag # now make the call self.ch.stop_consume() self.assertFalse(self.ch._consuming) self.assertTrue(ac.basic_cancel.called) self.assertIn(sentinel.consumer_tag, ac.basic_cancel.call_args[0]) def test_stop_consume_havent_started(self): # we're not consuming, so this should raise self.assertRaises(ChannelError, self.ch.stop_consume) def test_recv(self): # replace recv_queue with a mock obj rqmock = Mock(spec=queue.Queue) self.ch._recv_queue = rqmock rqmock.get.return_value = sentinel.recv m = self.ch.recv() self.assertEquals(m, sentinel.recv) self.assertTrue(rqmock.get.called) def test_recv_shutdown(self): # replace recv_queue with a mock obj rqmock = Mock(spec=queue.Queue) self.ch._recv_queue = rqmock rqmock.get.return_value = ChannelShutdownMessage() self.assertRaises(ChannelClosedError, self.ch.recv) @patch('pyon.net.channel.BaseChannel') @patch('pyon.net.channel.ChannelShutdownMessage') @patch('pyon.net.channel.log', Mock()) # to avoid having to put it in signature def test_close_impl(self, mockshutdown, mockbasechannel): # no auto stop consuming, no auto delete of queue without recv_name set # should have a shutdown message inserted mockrq = Mock(spec=queue.Queue) self.ch._recv_queue = mockrq self.ch.close_impl() # odd test quirk: have to assert mockshutdown was called once here (by close_impl), # before i can test that put was called with it, becuase i have to call it again just # to get the return value of it. mockshutdown.assert_called_once_with() mockrq.put.assert_called_once_with(mockshutdown()) mockbasechannel.close_impl.assert_called_once_with(self.ch) @patch('pyon.net.channel.BaseChannel') @patch('pyon.net.channel.log', Mock()) # to avoid having to put it in signature def test_close_impl_stops_consuming(self, mockbasechannel): self.ch._consuming = True scmock = Mock() self.ch.stop_consume = scmock self.ch.close_impl() scmock.assert_called_once_with() def test_declare_queue(self): # sideeffect that passes a result back (important here) framemock = Mock() framemock.method.queue = sentinel.queue def side(*args, **kwargs): cb = kwargs.get('callback') cb(framemock) ac = Mock(spec=pchannel.Channel) self.ch._amq_chan = ac ac.queue_declare.side_effect = side # needs a recv name self.ch._recv_name = (str(sentinel.xp), None) qd = self.ch._declare_queue(str(sentinel.queue)) # can't join a sentinel self.assertTrue(ac.queue_declare.called) self.assertIn('queue', ac.queue_declare.call_args[1]) self.assertIn('auto_delete', ac.queue_declare.call_args[1]) self.assertIn('durable', ac.queue_declare.call_args[1]) composed = ".".join([str(sentinel.xp), str(sentinel.queue)]) self.assertIn(composed, ac.queue_declare.call_args[1].itervalues()) self.assertIn(self.ch._queue_auto_delete, ac.queue_declare.call_args[1].itervalues()) self.assertIn(self.ch._queue_durable, ac.queue_declare.call_args[1].itervalues()) # should have set recv_name self.assertEquals(self.ch._recv_name, (str(sentinel.xp), sentinel.queue)) self.assertEquals(qd, sentinel.queue) def test__bind_no_name(self): self.assertRaises(AssertionError, self.ch._bind, sentinel.binding) def test__bind(self): self.ch._recv_name = (sentinel.xp, sentinel.queue) def side(*args, **kwargs): cb = kwargs.get('callback') cb() ac = Mock(spec=pchannel.Channel) ac.queue_bind.side_effect = side self.ch._amq_chan = ac self.ch._bind(sentinel.binding) self.assertTrue(ac.queue_bind.called) self.assertIn('queue', ac.queue_bind.call_args[1]) self.assertIn('exchange', ac.queue_bind.call_args[1]) self.assertIn('routing_key', ac.queue_bind.call_args[1]) self.assertIn(sentinel.queue, ac.queue_bind.call_args[1].itervalues()) self.assertIn(sentinel.xp, ac.queue_bind.call_args[1].itervalues()) self.assertIn(sentinel.binding, ac.queue_bind.call_args[1].itervalues()) def test__on_deliver(self): # mock up the method frame (delivery_tag is really only one we care about) m = Mock() m.consumer_tag = sentinel.consumer_tag m.delivery_tag = sentinel.delivery_tag m.redelivered = sentinel.redelivered m.exchange = sentinel.exchange m.routing_key = sentinel.routing_key # mock up the header-frame h = Mock() h.headers = { 'this_exists': sentinel.exists } # use a mock for the recv queue rqmock = Mock(spec=queue.Queue) self.ch._recv_queue = rqmock # now we can call! self.ch._on_deliver(sentinel.chan, m, h, sentinel.body) # assert the call rqmock.put.assert_called_once_with((sentinel.body, h.headers, sentinel.delivery_tag)) # assert the headers look ok self.assertIn(sentinel.exists, rqmock.put.call_args[0][0][1].itervalues()) def test_ack(self): ac = Mock(spec=pchannel.Channel) self.ch._amq_chan = ac self.ch.ack(sentinel.delivery_tag) ac.basic_ack.assert_called_once_with(sentinel.delivery_tag) def test_reject(self): ac = Mock(spec=pchannel.Channel) self.ch._amq_chan = ac def side(*args, **kwargs): cb = kwargs.get('callback') cb() ac.basic_reject.side_effect = side self.ch.reject(sentinel.delivery_tag, requeue=True) self.assertTrue(ac.basic_reject.called) self.assertIn(sentinel.delivery_tag, ac.basic_reject.call_args[0]) self.assertIn('requeue', ac.basic_reject.call_args[1]) self.assertIn(True, ac.basic_reject.call_args[1].itervalues())