コード例 #1
0
def test_transaction_calls(mockpika):
    """Test that calls to create, commit, abort transactions are passed to Pika properly."""
    pytest.xfail("Transactions not implemented in pika transport yet")
    transport = PikaTransport()
    transport.connect()
    mockconn = mockpika.BlockingConnection
    mockchannel = mockconn.return_value.channel.return_value
    mockproperties = mockpika.BasicProperties

    transport._transaction_begin()
    mockchannel.tx_select.assert_called_once()

    transport._send("destination",
                    mock.sentinel.message,
                    transaction=mock.sentinel.txid)
    args, kwargs = mockchannel.basic_publish.call_args
    assert not args
    assert kwargs == {
        "exchange": "",
        "routing_key": "destination",
        "body": mock.sentinel.message,
        "mandatory": True,
        "properties": mock.ANY,
    }
    assert mockproperties.call_args[1] == {"headers": {}, "delivery_mode": 2}

    transport._transaction_abort()
    mockchannel.tx_rollback.assert_called_once()

    transport._transaction_commit()
    mockchannel.tx_commit.assert_called_once()
コード例 #2
0
def test_broadcasting_message_with_expiration(mockpika, mock_pikathread):
    """Test sending a message that expires some time in the future"""
    message_lifetime = 120
    transport = PikaTransport()
    transport.connect()

    mockproperties = mockpika.BasicProperties

    transport._broadcast(str(mock.sentinel.exchange),
                         mock.sentinel.message,
                         expiration=message_lifetime)

    mock_pikathread.send.assert_called_once()
    args, kwargs = mock_pikathread.send.call_args
    assert not args
    assert mockproperties.return_value.expiration == str(message_lifetime *
                                                         1000)
    assert kwargs == {
        "exchange": str(mock.sentinel.exchange),
        "routing_key": "",
        "body": mock.sentinel.message,
        "properties": mock.ANY,
        "mandatory": False,
        "transaction_id": None,
    }
コード例 #3
0
def test_send_message(mockpika, mock_pikathread):
    """Test the message sending function"""
    transport = PikaTransport()
    transport.connect()

    mockproperties = mockpika.BasicProperties

    transport._send(mock.sentinel.queue, mock.sentinel.message)
    mock_pikathread.send.assert_called_once()
    args, kwargs = mock_pikathread.send.call_args

    assert not args
    assert kwargs == {
        "exchange": "",
        "routing_key": str(mock.sentinel.queue),
        "body": mock.sentinel.message,
        "mandatory": True,
        "properties": mock.ANY,
        "transaction_id": None,
    }
    assert mockproperties.call_args[1].get("headers") == {}
    assert int(mockproperties.call_args[1].get("delivery_mode")) == 2

    # Was a test for delayed sending, this is advanced in rabbitMQ and
    # to be implemented later
    with pytest.raises(AssertionError):
        transport._send(
            str(mock.sentinel.queue),
            mock.sentinel.message,
            headers={"hdr": mock.sentinel.header},
            delay=123,
        )
コード例 #4
0
def test_broadcast_status(mockpika, mock_pikathread):
    """Test the status broadcast function."""
    transport = PikaTransport()
    transport.connect()

    mockproperties = mockpika.BasicProperties

    transport.broadcast_status({
        "status": str(mock.sentinel.status),
        "host": "localhost",
        "workflows": True
    })

    mock_pikathread.send.assert_called_once()
    args, kwargs = mock_pikathread.send.call_args
    assert not args
    assert int(mockproperties.call_args[1].get("delivery_mode")) == 2
    assert int(mockproperties.return_value.expiration) == 1000 * 15
    assert kwargs == {
        "exchange": "transient.status",
        "routing_key": "",
        "body": mock.ANY,
        "properties": mock.ANY,
        "mandatory": False,
        "transaction_id": None,
    }
    statusdict = json.loads(kwargs.get("body"))
    assert statusdict["status"] == str(mock.sentinel.status)
コード例 #5
0
def test_instantiate_link_and_connect_to_broker(mock_pikathread):
    """Test the Pika connection routine."""
    transport = PikaTransport()
    assert not transport.is_connected()

    transport.connect()
    mock_pikathread.start.assert_called_once()
    mock_pikathread.start.side_effect = RuntimeError

    assert transport.is_connected()

    with pytest.raises(RuntimeError):
        transport.connect()

    mock_pikathread.join.assert_not_called()
    assert transport.is_connected()

    transport.disconnect()

    mock_pikathread.join.assert_called_once()
    mock_pikathread.connection_alive = False
    assert not transport.is_connected()

    transport.disconnect()

    assert mock_pikathread.join.call_count == 2
    assert not transport.is_connected()
コード例 #6
0
def test_messages_are_serialized_for_transport(mock_pikathread):
    banana = {"entry": [0, "banana"]}
    banana_str = '{"entry": [0, "banana"]}'
    transport = PikaTransport()
    transport.connect()

    transport.send(str(mock.sentinel.queue1), banana)
    mock_pikathread.send.assert_called_once()
    args, kwargs = mock_pikathread.send.call_args
    assert not args
    assert kwargs == {
        "exchange": "",
        "routing_key": str(mock.sentinel.queue1),
        "body": banana_str,
        "properties": pika.BasicProperties(delivery_mode=2, headers={}),
        "mandatory": True,
        "transaction_id": None,
    }

    transport.broadcast(str(mock.sentinel.queue2), banana)
    args, kwargs = mock_pikathread.send.call_args
    assert not args
    assert kwargs == {
        "exchange": str(mock.sentinel.queue2),
        "routing_key": "",
        "body": banana_str,
        "properties": pika.BasicProperties(delivery_mode=2, headers={}),
        "mandatory": False,
        "transaction_id": None,
    }

    with pytest.raises(TypeError):
        transport.send(str(mock.sentinel.queue), mock.sentinel.unserializable)
コード例 #7
0
def pikatransport(revert_classvariables, connection_params):
    # connection_params is unused here, but implements the fixture skipping
    # logic following a single test, instead of attempting a connection for
    # every individual test.
    pt = PikaTransport()
    pt.connect()
    yield pt
    pt.disconnect()
コード例 #8
0
def test_error_handling_when_connecting_to_broker(mockpika, mock_pikathread):
    """Test the Pika connection routine."""
    transport = PikaTransport()
    mock_pikathread.start.side_effect = pika.exceptions.AMQPConnectionError
    mockpika.exceptions = pika.exceptions

    with pytest.raises(workflows.Disconnected):
        transport.connect()

    assert transport.is_connected() is mock_pikathread.connection_alive
コード例 #9
0
def test_subscribe_to_queue(mock_pikathread):
    """Test subscribing to a queue (producer-consumer), callback functions and unsubscribe"""
    transport = PikaTransport()
    transport.connect()

    mock_cb = mock.Mock()
    transport._subscribe(1, str(mock.sentinel.queue1), mock_cb)

    mock_pikathread.subscribe_queue.assert_called_once()

    args, kwargs = mock_pikathread.subscribe_queue.call_args
    assert not args
    assert kwargs == {
        "auto_ack": True,
        "callback": mock.ANY,
        "subscription_id": 1,
        "prefetch_count": 1,
        "queue": str(mock.sentinel.queue1),
        "reconnectable": False,
    }

    transport._subscribe(2, str(mock.sentinel.queue2), mock_cb)

    assert mock_pikathread.subscribe_queue.call_count == 2
    args, kwargs = mock_pikathread.subscribe_queue.call_args
    assert not args
    assert kwargs == {
        "auto_ack": True,
        "callback": mock.ANY,
        "subscription_id": 2,
        "prefetch_count": 1,
        "queue": str(mock.sentinel.queue2),
        "reconnectable": False,
    }

    transport._subscribe(3,
                         str(mock.sentinel.queue3),
                         mock_cb,
                         acknowledgement=True)
    assert mock_pikathread.subscribe_queue.call_count == 3
    args, kwargs = mock_pikathread.subscribe_queue.call_args
    assert not args
    assert kwargs == {
        "auto_ack": False,
        "callback": mock.ANY,
        "subscription_id": 3,
        "prefetch_count": 1,
        "queue": str(mock.sentinel.queue3),
        "reconnectable": False,
    }

    transport._unsubscribe(1)
    mock_pikathread.unsubscribe.assert_called_once_with(1)
    transport._unsubscribe(2)
    mock_pikathread.unsubscribe.assert_called_with(2)
コード例 #10
0
def test_ack_message(mock_pikathread):
    transport = PikaTransport()
    transport.connect()

    transport._ack(mock.sentinel.messageid, mock.sentinel.sub_id)
    mock_pikathread.ack.assert_called_once_with(
        mock.sentinel.messageid,
        mock.sentinel.sub_id,
        multiple=False,
        transaction_id=None,
    )
コード例 #11
0
def test_nack_message(mock_pikathread):
    """Test that the _nack function call is properly forwarded to pika"""
    transport = PikaTransport()
    transport.connect()

    transport._nack(mock.sentinel.messageid, mock.sentinel.sub_id)

    mock_pikathread.nack.assert_called_once_with(
        mock.sentinel.messageid,
        mock.sentinel.sub_id,
        multiple=False,
        requeue=True,
        transaction_id=None,
    )
コード例 #12
0
def test_messages_are_not_serialized_for_raw_transport(_mockpika,
                                                       mock_pikathread):
    """Test the raw sending methods"""
    banana = '{"entry": [0, "banana"]}'
    transport = PikaTransport()
    transport.connect()

    transport.raw_send(str(mock.sentinel.queue1), banana)
    mock_pikathread.send.assert_called_once()
    args, kwargs = mock_pikathread.send.call_args
    assert not args
    assert kwargs == {
        "exchange": "",
        "routing_key": str(mock.sentinel.queue1),
        "body": banana,
        "mandatory": True,
        "properties": mock.ANY,
        "transaction_id": None,
    }

    mock_pikathread.send.reset_mock()
    transport.raw_broadcast(str(mock.sentinel.queue2), banana)
    mock_pikathread.send.assert_called_once()
    args, kwargs = mock_pikathread.send.call_args
    assert not args
    assert kwargs == {
        "exchange": str(mock.sentinel.queue2),
        "routing_key": "",
        "body": banana,
        "properties": mock.ANY,
        "mandatory": False,
        "transaction_id": None,
    }

    mock_pikathread.send.reset_mock()
    transport.raw_send(str(mock.sentinel.queue), mock.sentinel.unserializable)
    mock_pikathread.send.assert_called_once()
    args, kwargs = mock_pikathread.send.call_args
    assert not args
    assert kwargs == {
        "exchange": "",
        "routing_key": str(mock.sentinel.queue),
        "body": mock.sentinel.unserializable,
        "mandatory": True,
        "properties": mock.ANY,
        "transaction_id": None,
    }
コード例 #13
0
def test_send_broadcast(mockpika, mock_pikathread):
    """Test the broadcast sending function"""
    transport = PikaTransport()
    transport.connect()
    mockproperties = mockpika.BasicProperties

    transport._broadcast(str(mock.sentinel.exchange), mock.sentinel.message)

    mock_pikathread.send.assert_called_once()
    args, kwargs = mock_pikathread.send.call_args
    assert not args
    properties = mockproperties.call_args[1]
    assert properties.get("headers") in (None, {})
    assert kwargs == {
        "exchange": str(mock.sentinel.exchange),
        "routing_key": "",
        "body": mock.sentinel.message,
        "properties": mock.ANY,
        "mandatory": False,
        "transaction_id": None,
    }

    transport._broadcast(
        str(mock.sentinel.exchange),
        mock.sentinel.message,
        headers=mock.sentinel.headers,
    )

    mock_pikathread.send.call_count == 2
    args, kwargs = mock_pikathread.send.call_args
    assert not args
    properties = mockproperties.call_args[1]
    assert properties == {"headers": mock.sentinel.headers, "delivery_mode": 2}
    assert kwargs == {
        "exchange": str(mock.sentinel.exchange),
        "routing_key": "",
        "body": mock.sentinel.message,
        "properties": mock.ANY,
        "mandatory": False,
        "transaction_id": None,
    }

    # Delay not implemented yet
    with pytest.raises(AssertionError):
        transport._broadcast(str(mock.sentinel.exchange),
                             mock.sentinel.message,
                             delay=123)
コード例 #14
0
def test_anonymous_connection(mockpika, mock_pikathread,
                              revert_classvariables):
    """check that a specified configuration file is read, that command line
    parameters have precedence and are passed on the pika layer"""

    mockconn = mock.Mock()
    mockpika.BlockingConnection.return_value = mockconn
    parser = optparse.OptionParser()
    transport = PikaTransport()
    transport.add_command_line_options(parser)

    parser.parse_args(["--rabbit-user="******"--rabbit-pass="******"", "")
コード例 #15
0
def test_check_config_file_behaviour(mockpika, mock_pikathread, tmp_path,
                                     revert_classvariables):
    """Check that a specified configuration file is read, that command line
    parameters have precedence and are passed on to the pika layer."""

    parser = optparse.OptionParser()
    transport = PikaTransport()
    transport.add_command_line_options(parser)

    cfgfile = tmp_path / "config"
    cfgfile.write_text("""
        # An example pika configuration file
        # Only lines in the [pika] block will be interpreted

        [rabbit]
        host = localhost
        port = 5672
        username = someuser
        password = somesecret
        vhost = namespace
        """)

    parser.parse_args(
        ["--rabbit-conf",
         str(cfgfile), "--rabbit-user", mock.sentinel.user])

    transport = PikaTransport()
    transport.connect()

    mock_pikathread.start.assert_called_once()
    mockpika.PlainCredentials.assert_called_once_with(mock.sentinel.user,
                                                      "somesecret")
    args, kwargs = mockpika.ConnectionParameters.call_args
    assert not args
    assert kwargs == {
        "host": "localhost",
        "port": 5672,
        "virtual_host": "namespace",
        "credentials": mockpika.PlainCredentials.return_value,
    }

    with pytest.raises(workflows.Error):
        parser.parse_args(["--rabbit-conf", ""])
コード例 #16
0
def test_error_handling_on_broadcast(mockpika):
    """Unrecoverable errors during broadcasting should lead to one reconnection attempt.
    Further errors should raise an Exception, further send attempts to try to reconnect."""
    pytest.xfail("Don't understand send lifecycle errors yet")
    transport = PikaTransport()
    transport.connect()
    mockconn = mockpika.BlockingConnection
    mockchannel = mockconn.return_value.channel.return_value
    mockchannel.basic_publish.side_effect = pika.exceptions.AMQPChannelError()
    mockpika.exceptions = pika.exceptions

    assert mockconn.call_count == 1
    with pytest.raises(workflows.Disconnected):
        transport._broadcast(str(mock.sentinel.channel), mock.sentinel.message)
    assert not transport.is_connected()
    assert mockconn.call_count == 2

    mockchannel.basic_publish.side_effect = None
    transport._broadcast(str(mock.sentinel.channel), mock.sentinel.message)
    assert transport.is_connected()
    assert mockconn.call_count == 3
コード例 #17
0
def test_error_handling_on_subscribing(mockpika, mock_pikathread):
    """Unrecoverable errors during subscribing should mark the connection as disconnected."""
    mock_cb = mock.Mock()

    transport = PikaTransport()
    transport.connect()
    mockpika.exceptions = pika.exceptions
    mock_pikathread.connection_alive = False
    mock_pikathread.subscribe_queue.return_value.result.side_effect = (
        pika.exceptions.AMQPChannelError)

    with pytest.raises(workflows.Disconnected):
        transport._subscribe(1, str(mock.sentinel.queue1), mock_cb)
    assert not transport.is_connected()

    # Now try connectionError instead of ChannelError
    mock_pikathread.subscribe_queue.return_value.result.side_effect = (
        pika.exceptions.AMQPConnectionError)

    with pytest.raises(workflows.Disconnected):
        transport._subscribe(1, str(mock.sentinel.queue1), mock_cb)
    assert not transport.is_connected()
コード例 #18
0
def test_subscribe_to_broadcast(mock_pikathread):
    """Test subscribing to a queue (producer-consumer), callback functions and unsubscribe"""
    mock_cb = mock.Mock()
    transport = PikaTransport()
    transport.connect()

    transport._subscribe_broadcast(1, str(mock.sentinel.queue1), mock_cb)

    mock_pikathread.subscribe_broadcast.assert_called_once()
    args, kwargs = mock_pikathread.subscribe_broadcast.call_args
    assert not args
    assert kwargs == {
        "callback": mock.ANY,
        "exchange": str(mock.sentinel.queue1),
        "subscription_id": 1,
        "reconnectable": False,
    }

    transport._subscribe_broadcast(
        2,
        str(mock.sentinel.queue2),
        mock_cb,
    )

    assert mock_pikathread.subscribe_broadcast.call_count == 2
    args, kwargs = mock_pikathread.subscribe_broadcast.call_args
    assert not args
    assert kwargs == {
        "callback": mock.ANY,
        "exchange": str(mock.sentinel.queue2),
        "subscription_id": 2,
        "reconnectable": False,
    }

    transport._unsubscribe(1)
    mock_pikathread.unsubscribe.assert_called_once_with(1)
    transport._unsubscribe(2)
    mock_pikathread.unsubscribe.assert_called_with(2)
コード例 #19
0
def test_sending_message_with_expiration(mockpika, mock_pikathread):
    """Test sending a message that expires some time in the future."""
    transport = PikaTransport()
    transport.connect()
    mockproperties = mockpika.BasicProperties

    transport._send(str(mock.sentinel.queue),
                    mock.sentinel.message,
                    expiration=120)

    mock_pikathread.send.assert_called_once()

    args, kwargs = mock_pikathread.send.call_args
    assert not args
    assert kwargs == {
        "exchange": "",
        "routing_key": str(mock.sentinel.queue),
        "body": mock.sentinel.message,
        "mandatory": True,
        "properties": mock.ANY,
        "transaction_id": None,
    }
    assert int(mockproperties.return_value.expiration) == 120 * 1000
コード例 #20
0
def test_messages_are_deserialized_after_transport(mock_pikathread):
    """Test the message serialization."""
    banana = {"entry": [0, "banana"]}
    banana_str = '{"entry": [0, "banana"]}'
    transport = PikaTransport()
    transport.connect()

    # Test subscriptions
    callback = mock.Mock()
    transport.subscribe("queue", callback)

    mock_properties = mock.Mock()
    mock_properties.headers = {"mock_header": 1}

    # Extract the function passed to pikathread, and call it
    args, kwargs = mock_pikathread.subscribe_queue.call_args
    message_handler = kwargs["callback"]
    message_handler(
        mock.Mock(),
        mock.Mock(),
        mock_properties,
        banana_str,
    )
    callback.assert_called_once()
    args, kwargs = callback.call_args
    assert not kwargs
    assert args[1] == banana

    message_handler(mock.Mock(), mock.Mock(), mock_properties,
                    mock.sentinel.undeserializable)
    args, kwargs = callback.call_args
    assert not kwargs
    assert args[1] == mock.sentinel.undeserializable

    # Test broadcast subscriptions
    callback = mock.Mock()
    transport.subscribe_broadcast("queue", callback)
    message_handler = mock_pikathread.subscribe_broadcast.call_args[1][
        "callback"]

    message_handler(mock.Mock(), mock.Mock(), mock_properties, banana_str)
    callback.assert_called_once()
    args, kwargs = callback.call_args
    assert not kwargs
    assert args[1] == banana

    message_handler(mock.Mock(), mock.Mock(), mock_properties,
                    mock.sentinel.undeserializable)
    args, kwargs = callback.call_args
    assert not kwargs
    assert args[1] == mock.sentinel.undeserializable

    # Test subscriptions with mangling disabled
    callback = mock.Mock()
    transport.subscribe("queue", callback, disable_mangling=True)
    message_handler = mock_pikathread.subscribe_queue.call_args[1]["callback"]
    message_handler(mock.Mock(), mock.Mock(), mock_properties, banana_str)
    callback.assert_called_once()
    args, kwargs = callback.call_args
    assert not kwargs
    assert args[1] == banana_str

    # Test broadcast subscriptions with mangling disabled
    callback = mock.Mock()
    transport.subscribe_broadcast("queue", callback, disable_mangling=True)
    message_handler = mock_pikathread.subscribe_broadcast.call_args[1][
        "callback"]
    message_handler(mock.Mock(), mock.Mock(), mock_properties, banana_str)
    callback.assert_called_once()
    args, kwargs = callback.call_args
    assert not kwargs
    assert args[1] == banana_str