def test_consume_from_exchange_and_queue(self): """ Verify RMQConsumer can consume from an exchange, binding it to a specific queue. """ msg_received = None event = threading.Event() def on_msg(msg): event.set() nonlocal msg_received msg_received = msg # Consume consume_key = self.consumer.consume( ConsumeParams(on_msg), exchange_params=ExchangeParams("exchange_fanout", exchange_type=ExchangeType.fanout), queue_params=QueueParams("queue_fanout_receiver")) self.assertEqual(consume_key, "queue_fanout_receiver|exchange_fanout") # Wait for ConsumeOK event.wait(timeout=1.0) self.assertTrue(isinstance(msg_received, ConsumeOK)) # Send a message and verify it is delivered OK event.clear() self.producer.publish(b"body", exchange_params=ExchangeParams( "exchange_fanout", exchange_type=ExchangeType.fanout)) event.wait(timeout=1.0) self.assertEqual(msg_received, b"body")
def test_consume_from_direct_exchange(self): """ Verify RMQConsumer can consume from a direct exchange and routing key. """ msg_received = None event = threading.Event() def on_msg(msg): event.set() nonlocal msg_received msg_received = msg # Consume consume_key = self.consumer.consume( ConsumeParams(on_msg), exchange_params=ExchangeParams("exchange"), routing_key="bla.bla") self.assertEqual(consume_key, "exchange|bla.bla") # Wait for ConsumeOK event.wait(timeout=1.0) self.assertTrue(isinstance(msg_received, ConsumeOK)) # Send a message and verify it is delivered OK event.clear() self.producer.publish(b"body", exchange_params=ExchangeParams("exchange"), routing_key="bla.bla") event.wait(timeout=1.0) self.assertEqual(msg_received, b"body")
def test_confirm_mode_delays_buffer_until_confirm_mode_ok(self): """ Verify that, if confirm mode has been activated, buffered publishes are not sent on 'on_ready', but rather 'on_confirm_select_ok'. """ # Prep self.producer.activate_confirm_mode(lambda _:...) self.producer.on_close() exchange_params = ExchangeParams("exchange") # Test + assertions _pub_key = self.producer.publish(b"body", exchange_params=exchange_params) self.assertNotEqual(_pub_key, None) self.producer.declare_exchange.assert_not_called() self.assertEqual(len(self.producer._buffered_messages), 1) self.producer.on_ready() self.producer.declare_exchange.assert_not_called() self.assertEqual(len(self.producer._buffered_messages), 1) self.producer.on_confirm_select_ok(Mock()) self.producer.declare_exchange.assert_called() self.assertEqual(len(self.producer._buffered_messages), 0)
def test_consume_queue_exchange_and_routing_key(self): """ Verify possibility to provide both an exchange, routing_key and a queue to the consume method. """ # Prep def on_msg(): pass consume = ConsumeParams(on_msg) queue = QueueParams("queue") exchange = ExchangeParams("exchange") # Run test self.consumer.consume(consume, queue_params=queue, exchange_params=exchange, routing_key="routing_key") # Assertions consume_key = _gen_consume_key(queue=queue.queue, exchange=exchange.exchange, routing_key="routing_key") consume_instance = self.consumer._consumes[consume_key] self.assertEqual(consume_instance.consume_params, consume) self.assertEqual(consume_instance.queue_params, queue) self.assertEqual(consume_instance.exchange_params, exchange) self.assertEqual(consume_instance.routing_key, "routing_key") self.consumer.declare_queue.assert_called_with(queue, callback=ANY)
def test_publish_including_publish_params(self): """ Verify that PublishParams are passed as expected when calling publish. """ # Prep exchange_params = ExchangeParams("exchange") publish_params = PublishParams() routing_key = "routing_key" # Run test + assertions self.producer.publish(b"body", exchange_params=exchange_params, routing_key=routing_key, publish_params=publish_params) self.producer.declare_exchange.assert_called_with(exchange_params, callback=ANY) self.producer.on_exchange_declared(b"body", exchange_params, None, routing_key="", publish_params=publish_params) self.producer.basic_publish.assert_called_with( b"body", exchange=exchange_params.exchange, routing_key="", publish_params=publish_params)
def test_publish_using_exchange_and_routing_key(self): """ Verify that publishing using both exchange and routing key has the expected behavior. """ # Prep exchange_params = ExchangeParams("exchange") routing_key = "routing_key" # Run test + assertions self.producer.publish(b"body", exchange_params=exchange_params, routing_key=routing_key) self.producer.declare_exchange.assert_called_with(exchange_params, callback=ANY) self.producer.on_exchange_declared(b"body", exchange_params, None, routing_key=routing_key, publish_params=None) self.producer.basic_publish.assert_called_with( b"body", exchange=exchange_params.exchange, routing_key=routing_key, publish_params=None)
def test_confirm_mode(self): """ Verify confirm mode pushes publish_keys to users on successful delivery. """ msg_received = None event = threading.Event() def on_confirm(confirm): event.set() nonlocal msg_received msg_received = confirm # Activate confirm mode self.producer.activate_confirm_mode(on_confirm) # Wait for ConfirmModeOK event.wait(timeout=1.0) self.assertTrue(isinstance(msg_received, ConfirmModeOK)) # Send a message and verify it is delivered OK event.clear() publish_key = self.producer.publish( b"body", exchange_params=ExchangeParams("exchange_direct"), ) event.wait(timeout=1.0) self.assertEqual(msg_received, publish_key) self.assertEqual(len(self.producer._unacked_publishes.keys()), 0)
def test_on_exchange_declared(self): """ Verify that the correct action follows a successful exchange declaration. """ # Prep self.consumer.bind_queue = Mock() exchange_params = ExchangeParams("exchange") consume_params = ConsumeParams(lambda _: ...) queue_params = QueueParams("queue") # Run test self.consumer.on_exchange_declared(exchange_params, None, consume_params=consume_params, queue_params=queue_params) # Assertions call_args = self.consumer.bind_queue.call_args queue_bind_params = call_args.args[0] self.consumer.bind_queue.assert_called_with( queue_bind_params, callback=ANY ) self.assertEqual(queue_bind_params.queue, consume_params.queue) self.assertEqual(queue_bind_params.exchange, exchange_params.exchange) self.assertEqual(queue_bind_params.routing_key, None)
def test_buffer_publishes_with_confirm_mode_on(self): """ Verify buffering publishes, with confirm mode on, and then starting the producer results in a correct number of messages being sent successfully, measured by counting and verifying the Basic.Acks received from the broker. """ producer = RMQProducer() event = threading.Event() key_dict = dict() def on_confirm(confirm): if not isinstance(confirm, ConfirmModeOK): key_dict.pop(confirm) if len(key_dict.keys()) == 0: event.set() # Activate confirm mode producer.activate_confirm_mode(on_confirm) # Buffer a few publishes key_dict[producer.publish( b"body", exchange_params=ExchangeParams("exchange_direct"))] = False key_dict[producer.publish( b"body", exchange_params=ExchangeParams("exchange_direct"))] = False key_dict[producer.publish( b"body", exchange_params=ExchangeParams("exchange_direct"))] = False self.assertEqual(len(producer._unacked_publishes.keys()), 0) self.assertEqual(len(producer._buffered_messages), 3) # Start the producer producer.start() self.assertTrue(started(producer)) # Await all confirms event.wait(timeout=1.0) self.assertEqual(len(producer._unacked_publishes.keys()), 0) # Stop the extra producer producer.stop()
def test_publish_using_both_queue_params_and_exchange_params(self): """ Verify that a ValueError is raised if both queue and exchange parameters are provided to publish. """ # Prep queue_params = QueueParams("queue") exchange_params = ExchangeParams("exchange") # Run test + assertions with self.assertRaises(ValueError): self.producer.publish(b"body", exchange_params=exchange_params, queue_params=queue_params)
def test_confirm_mode_publish_key_returned_by_publish(self): """ Verify that a publish key is generated and returned by publish if confirm mode is activated. """ # Prep publish_key = None def on_confirm(delivery_notification): if delivery_notification == publish_key: return elif isinstance(delivery_notification, ConfirmModeOK): return self.fail("delivery notification did not match the generated " "publish key") self.producer.activate_confirm_mode(on_confirm) self.producer.confirm_delivery.assert_called_with( self.producer.on_delivery_confirmed, callback=self.producer.on_confirm_select_ok) self.producer.on_confirm_select_ok(None) exchange_params = ExchangeParams("exchange") # Test publish_key = self.producer.publish(b"body", exchange_params=exchange_params) self.producer.declare_exchange.assert_called() self.producer.on_exchange_declared(b"body", exchange_params, None, publish_key=publish_key) self.producer.basic_publish.assert_called_with( b"body", exchange=exchange_params.exchange, routing_key="", publish_params=ANY) # 1 is the delivery tag self.assertEqual(self.producer._unacked_publishes[1], publish_key) frame = Mock() ack = Basic.Ack() ack.delivery_tag = 1 frame.method = ack self.producer.on_delivery_confirmed(frame) self.assertEqual(len(self.producer._unacked_publishes.keys()), 0)
def test_publish_using_exchange_params(self): """Verify possibility to publish to an exchange.""" # Prep exchange_params = ExchangeParams("exchange") # Run test + assertions self.producer.publish(b"body", exchange_params=exchange_params) self.producer.declare_exchange.assert_called_with(exchange_params, callback=ANY) self.producer.on_exchange_declared(b"body", exchange_params, None, routing_key="", publish_params=None) self.producer.basic_publish.assert_called_with( b"body", exchange=exchange_params.exchange, routing_key="", publish_params=None)
def test_publish_before_confirm_mode_ok_buffers_the_publish(self): """ Verify that any call to publish before confirm mode ok (when confirm mode has been activated) leads to the call being buffered and delayed until 'on_confirm_select_ok'. """ # Prep self.producer.activate_confirm_mode(lambda _:...) exchange_params = ExchangeParams("exchange") # Test + assertions _pub_key = self.producer.publish(b"body", exchange_params=exchange_params) self.assertNotEqual(_pub_key, None) self.producer.declare_exchange.assert_not_called() self.assertEqual(len(self.producer._buffered_messages), 1) self.producer.on_confirm_select_ok(Mock()) self.producer.declare_exchange.assert_called() self.assertEqual(len(self.producer._buffered_messages), 0)
def test_on_queue_declared_exchange(self): """ Verify that the correct action follows a successful queue declare when exchange is specified. """ # Prep self.consumer.declare_exchange = Mock() frame = Mock() consume_params = ConsumeParams(lambda _: ...) queue_params = QueueParams("queue") exchange_params = ExchangeParams("exchange") # Run test self.consumer.on_queue_declared(frame, consume_params=consume_params, queue_params=queue_params, exchange_params=exchange_params) # Assertions self.assertTrue(isinstance(consume_params.queue, Mock)) self.consumer.declare_exchange.assert_called_with( exchange_params, callback=ANY)
def test_consume_exchange_only(self): """Verify possibility to consume from an exchange.""" # Prep def on_msg(): pass consume = ConsumeParams(on_msg) exchange = ExchangeParams("exchange") # Run test self.consumer.consume(consume, exchange_params=exchange) # # Assertions # Verify consume instance exists in consumer instance consume_key = _gen_consume_key(exchange=exchange.exchange) consume_instance = self.consumer._consumes[consume_key] self.assertEqual(consume_instance.consume_params, consume) self.assertEqual(consume_instance.exchange_params, exchange) # Always starts with queue declare, can't verify call params since # queue is autogenerated if not provided, and the other arg is a # callback constructed from functools.partial. self.consumer.declare_queue.assert_called()
def test_declare_exchange(self): """ Verify declaring an exchange. """ # Prep exchange_params = ExchangeParams("exchange") def on_exchange_declared(): ... # Test self.conn_imp.declare_exchange(exchange_params, callback=on_exchange_declared) # Assert self.conn_imp._channel.exchange_declare.assert_called_with( exchange_params.exchange, exchange_type=exchange_params.exchange_type, durable=exchange_params.durable, auto_delete=exchange_params.auto_delete, internal=exchange_params.internal, arguments=exchange_params.arguments, callback=on_exchange_declared)
def test_publish_is_delayed_until_producer_connection_ready(self): """ Verify that the producer buffers messages that are to be sent when the producer connection is not in a ready state, and that the buffered messages are sent upon the producer becoming ready. """ # Prep exchange_params = ExchangeParams("exchange") frame_mock = Mock() frame_mock.method.queue = "queue" queue_params = QueueParams("queue") # Run test + assertions self.producer.on_close() self.producer.publish(b"body", exchange_params=exchange_params) self.producer.publish(b"body", queue_params=queue_params) self.assertEqual(2, len(self.producer._buffered_messages)) self.producer.on_ready() self.producer.declare_exchange.assert_called_with(exchange_params, callback=ANY) self.producer.declare_queue.assert_called_with(queue_params, callback=ANY)
def test_on_close_marks_consumes_stopped(self): """Verify a call to on_close marks all consumes as stopped.""" queue_consume = ConsumeParams(lambda _: ...) queue = QueueParams("queue") self.consumer.consume(queue_consume, queue_params=queue) exchange_consume = ConsumeParams(lambda _: ...) exchange = ExchangeParams("exchange") self.consumer.consume(exchange_consume, exchange_params=exchange) # Fake having all consumes started for _, consume in self.consumer._consumes.items(): consume.consumer_tag = "some tag" # Run test self.consumer.on_close() # Checks for _, consume in self.consumer._consumes.items(): if consume.consumer_tag == "some tag": self.fail( "a consume did not have its consumer tag cleared when " "on_close was called" )
def test_on_ready_starts_consumes(self): """ Verify that a call to on_ready results in re-issuing of all active consumes. """ # Prep self.consumer._handle_consume = Mock() queue_params = QueueParams("queue") exchange_params = ExchangeParams("exchange") self.consumer.consume(ConsumeParams(lambda _: ...), queue_params=queue_params) self.consumer.consume(ConsumeParams(lambda _: ...), exchange_params=exchange_params) # Run test self.consumer.on_ready() # Assertions self.consumer._handle_consume.assert_has_calls( (call(ANY, queue_params, None, None), call(ANY, None, exchange_params, None),) )
producer = RMQProducer() producer.start() def stop(*args): producer.stop() sys.exit(0) signal.signal(signal.SIGINT, stop) producer.publish(b"queue publish 1", queue_params=QueueParams("queue")) producer.publish(b"queue publish 2", queue_params=QueueParams("queue")) producer.publish(b"queue publish 3", queue_params=QueueParams("queue")) producer.publish(b"exchange publish 1", exchange_params=ExchangeParams("direct"), routing_key="rkey") producer.publish(b"exchange publish 2", exchange_params=ExchangeParams( "fanout", exchange_type=ExchangeType.fanout)) time.sleep(0.3) producer.activate_confirm_mode(lambda x: print(x)) producer.publish(b"exchange publish 2", exchange_params=ExchangeParams( "fanout", exchange_type=ExchangeType.fanout)) producer.publish(b"exchange publish 2", exchange_params=ExchangeParams( "fanout", exchange_type=ExchangeType.fanout)) producer.publish(b"exchange publish 2", exchange_params=ExchangeParams(