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)
示例#4
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)
示例#8
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)
示例#14
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)
示例#15
0
    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)
示例#18
0
    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"
                )
示例#19
0
    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(