Search in sources :

Example 1 with ProtonMessageHandler

use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.

the class MessageForwardingEndpointTest method testMessageHandlerRejectsMalformedMessage.

/**
 * Verifies that the endpoint rejects messages that do not pass formal verification.
 */
@SuppressWarnings({ "unchecked" })
@Test
public void testMessageHandlerRejectsMalformedMessage() {
    // GIVEN an endpoint with an attached client
    final ResourceIdentifier targetAddress = ResourceIdentifier.fromString("telemetry/tenant");
    final ProtonConnection connection = mock(ProtonConnection.class);
    when(connection.getRemoteContainer()).thenReturn("test-client");
    final ProtonReceiver receiver = mock(ProtonReceiver.class);
    when(receiver.getRemoteQoS()).thenReturn(ProtonQoS.AT_MOST_ONCE);
    final DownstreamAdapter adapter = mock(DownstreamAdapter.class);
    doAnswer(invocation -> {
        final Handler<AsyncResult<Void>> resultHandler = invocation.getArgument(1);
        resultHandler.handle(Future.succeededFuture());
        return null;
    }).when(adapter).onClientAttach(any(UpstreamReceiver.class), any(Handler.class));
    final MessageForwardingEndpoint<HonoMessagingConfigProperties> endpoint = getEndpoint(false);
    endpoint.setDownstreamAdapter(adapter);
    endpoint.onLinkAttach(connection, receiver, targetAddress);
    final ArgumentCaptor<ProtonMessageHandler> messageHandler = ArgumentCaptor.forClass(ProtonMessageHandler.class);
    verify(receiver).handler(messageHandler.capture());
    // WHEN a client sends a malformed message
    final Message message = ProtonHelper.message("malformed");
    final ProtonDelivery upstreamDelivery = mock(ProtonDelivery.class);
    messageHandler.getValue().handle(upstreamDelivery, message);
    // THEN the endpoint rejects the message
    final ArgumentCaptor<Rejected> deliveryState = ArgumentCaptor.forClass(Rejected.class);
    verify(upstreamDelivery).disposition(deliveryState.capture(), eq(Boolean.TRUE));
    assertThat(deliveryState.getValue().getError().getCondition(), is(AmqpError.DECODE_ERROR));
    // but does not close the link
    verify(receiver, never()).close();
    // and the message is not forwarded to the downstream adapter
    verify(adapter, never()).processMessage(any(UpstreamReceiver.class), eq(upstreamDelivery), eq(message));
}
Also used : ProtonReceiver(io.vertx.proton.ProtonReceiver) Message(org.apache.qpid.proton.message.Message) ProtonDelivery(io.vertx.proton.ProtonDelivery) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Handler(io.vertx.core.Handler) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) AsyncResult(io.vertx.core.AsyncResult) Test(org.junit.Test)

Example 2 with ProtonMessageHandler

use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.

the class EventConsumerImplTest method testCreateRegistersBiConsumerAsMessageHandler.

/**
 * Verifies that the message delivery for a received event is forwarded to the
 * registered event consumer.
 *
 * @param ctx The test context.
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testCreateRegistersBiConsumerAsMessageHandler(final TestContext ctx) {
    // GIVEN an event consumer that releases all messages
    final Async consumerCreation = ctx.async();
    final BiConsumer<ProtonDelivery, Message> eventConsumer = (delivery, message) -> {
        ProtonHelper.released(delivery, true);
    };
    final RecordImpl attachments = new RecordImpl();
    final Source source = mock(Source.class);
    when(source.toString()).thenReturn("event/tenant");
    final ProtonReceiver receiver = mock(ProtonReceiver.class);
    when(receiver.getSource()).thenReturn(source);
    when(receiver.attachments()).thenReturn(attachments);
    when(receiver.getRemoteQoS()).thenReturn(ProtonQoS.AT_LEAST_ONCE);
    when(receiver.open()).then(answer -> {
        consumerCreation.complete();
        return receiver;
    });
    final ProtonConnection con = mock(ProtonConnection.class);
    when(con.createReceiver(anyString())).thenReturn(receiver);
    when(receiver.openHandler(any(Handler.class))).thenAnswer(invocation -> {
        final Handler handler = invocation.getArgument(0);
        handler.handle(Future.succeededFuture(receiver));
        return receiver;
    });
    final ArgumentCaptor<ProtonMessageHandler> messageHandler = ArgumentCaptor.forClass(ProtonMessageHandler.class);
    EventConsumerImpl.create(vertx.getOrCreateContext(), new ClientConfigProperties(), con, "tenant", eventConsumer, open -> {
    }, remoteDetach -> {
    });
    consumerCreation.await();
    verify(receiver).handler(messageHandler.capture());
    // WHEN an event is received
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    final Message msg = mock(Message.class);
    messageHandler.getValue().handle(delivery, msg);
    // THEN the message is released and settled
    verify(delivery).disposition(any(Released.class), eq(Boolean.TRUE));
}
Also used : TestContext(io.vertx.ext.unit.TestContext) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonReceiver(io.vertx.proton.ProtonReceiver) Async(io.vertx.ext.unit.Async) ProtonDelivery(io.vertx.proton.ProtonDelivery) RunWith(org.junit.runner.RunWith) Timeout(io.vertx.ext.unit.junit.Timeout) ArgumentCaptor(org.mockito.ArgumentCaptor) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) RecordImpl(org.apache.qpid.proton.engine.impl.RecordImpl) After(org.junit.After) BiConsumer(java.util.function.BiConsumer) Message(org.apache.qpid.proton.message.Message) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) Before(org.junit.Before) Vertx(io.vertx.core.Vertx) Test(org.junit.Test) ProtonHelper(io.vertx.proton.ProtonHelper) ProtonQoS(io.vertx.proton.ProtonQoS) VertxUnitRunner(io.vertx.ext.unit.junit.VertxUnitRunner) Released(org.apache.qpid.proton.amqp.messaging.Released) Future(io.vertx.core.Future) Mockito(org.mockito.Mockito) Source(org.apache.qpid.proton.amqp.transport.Source) Rule(org.junit.Rule) Handler(io.vertx.core.Handler) ProtonReceiver(io.vertx.proton.ProtonReceiver) Released(org.apache.qpid.proton.amqp.messaging.Released) ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Handler(io.vertx.core.Handler) RecordImpl(org.apache.qpid.proton.engine.impl.RecordImpl) Source(org.apache.qpid.proton.amqp.transport.Source) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Async(io.vertx.ext.unit.Async) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) Test(org.junit.Test)

Example 3 with ProtonMessageHandler

use of io.vertx.proton.ProtonMessageHandler in project vertx-proton by vert-x3.

the class ProtonReceiverImplTest method testMultiTransferMessage.

/**
 * Verifies that the receiver accepts a multi-transfer message that does
 * not exceed the link's max-message-size and delivers it to the application layer.
 */
@SuppressWarnings("unchecked")
@Test
public void testMultiTransferMessage() {
    int maxFrameSize = 512;
    int maxMessageSize = 800;
    Transport transport = mock(Transport.class);
    when(transport.getMaxFrameSize()).thenReturn(maxFrameSize);
    Connection con = mock(Connection.class);
    ProtonConnectionImpl conImpl = new ProtonConnectionImpl(mock(Vertx.class), "hostname", mock(ContextInternal.class));
    when(con.getTransport()).thenReturn(transport);
    when(con.getContext()).thenReturn(conImpl);
    Session session = mock(Session.class);
    ProtonSessionImpl sessionImpl = new ProtonSessionImpl(session);
    when(session.getConnection()).thenReturn(con);
    when(session.getContext()).thenReturn(sessionImpl);
    when(session.getIncomingCapacity()).thenReturn(10_000);
    when(session.getIncomingBytes()).thenReturn(10_000);
    Receiver r = mock(Receiver.class);
    when(r.getLocalState()).thenReturn(EndpointState.ACTIVE);
    when(r.getSession()).thenReturn(session);
    when(r.getMaxMessageSize()).thenReturn(new UnsignedLong(maxMessageSize));
    ProtonReceiverImpl recImpl = new ProtonReceiverImpl(r);
    when(r.getContext()).thenReturn(recImpl);
    ProtonMessageHandler messageHandler = mock(ProtonMessageHandler.class);
    Handler<ProtonReceiver> maxMessageSizeExceededHandler = mock(Handler.class);
    ProtonReceiverImpl receiver = new ProtonReceiverImpl(r);
    receiver.handler(messageHandler);
    receiver.maxMessageSizeExceededHandler(maxMessageSizeExceededHandler);
    byte[] encodedMessage = createEncodedMessage(maxMessageSize);
    assertTrue(encodedMessage.length > maxFrameSize);
    assertTrue(encodedMessage.length <= 2 * maxFrameSize);
    assertTrue(encodedMessage.length <= maxMessageSize);
    byte[] chunk0 = new byte[maxFrameSize];
    System.arraycopy(encodedMessage, 0, chunk0, 0, chunk0.length);
    ReadableBuffer frame0 = ReadableBuffer.ByteBufferReader.wrap(chunk0);
    Delivery delivery0 = mock(Delivery.class);
    when(delivery0.getLink()).thenReturn(r);
    when(delivery0.isPartial()).thenReturn(true);
    when(delivery0.available()).thenReturn(chunk0.length);
    when(delivery0.isSettled()).thenReturn(false);
    byte[] chunk1 = new byte[encodedMessage.length - maxFrameSize];
    System.arraycopy(encodedMessage, maxFrameSize, chunk1, 0, chunk1.length);
    ReadableBuffer frame1 = ReadableBuffer.ByteBufferReader.wrap(chunk1);
    Delivery delivery1 = mock(Delivery.class);
    when(delivery1.getLink()).thenReturn(r);
    when(delivery1.isPartial()).thenReturn(false);
    when(delivery1.available()).thenReturn(chunk1.length);
    when(delivery1.isSettled()).thenReturn(false);
    when(r.current()).thenReturn(delivery0, delivery1);
    when(r.recv()).thenReturn(frame0, frame1);
    // WHEN delivering the message in two consecutive transfer frames
    receiver.onDelivery();
    receiver.onDelivery();
    // THEN the disposition in reply to the second transfer has state accepted
    verify(delivery1).disposition(any(Accepted.class));
    // and the receiver has been advanced to the next delivery
    verify(r).advance();
    // and the sender has been issued a new credit
    verify(r).flow(1);
    // and the message has been delivered to the application layer
    verify(messageHandler).handle(any(ProtonDelivery.class), any(Message.class));
    // and the link is not being closed
    verify(r, never()).close();
    verify(maxMessageSizeExceededHandler, never()).handle(any(ProtonReceiver.class));
}
Also used : ProtonReceiver(io.vertx.proton.ProtonReceiver) UnsignedLong(org.apache.qpid.proton.amqp.UnsignedLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) Connection(org.apache.qpid.proton.engine.Connection) ProtonReceiver(io.vertx.proton.ProtonReceiver) Receiver(org.apache.qpid.proton.engine.Receiver) ContextInternal(io.vertx.core.impl.ContextInternal) Vertx(io.vertx.core.Vertx) ReadableBuffer(org.apache.qpid.proton.codec.ReadableBuffer) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Delivery(org.apache.qpid.proton.engine.Delivery) ProtonDelivery(io.vertx.proton.ProtonDelivery) Transport(org.apache.qpid.proton.engine.Transport) Session(org.apache.qpid.proton.engine.Session) Test(org.junit.Test)

Example 4 with ProtonMessageHandler

use of io.vertx.proton.ProtonMessageHandler in project vertx-proton by vert-x3.

the class ProtonReceiverImplTest method testSingleTransferExceedingMaxMessageSizeResultsInLinkBeingDetached.

/**
 * Verifies that the receiver detaches the link with an
 * amqp:link:message-size-exceeded error code when receiving a single-transfer message that
 * exceeds the link's max-message-size.
 */
@Test
public void testSingleTransferExceedingMaxMessageSizeResultsInLinkBeingDetached() {
    int maxFrameSize = 800;
    long maxMessageSize = 500;
    Transport transport = mock(Transport.class);
    when(transport.getMaxFrameSize()).thenReturn(maxFrameSize);
    Connection con = mock(Connection.class);
    ProtonConnectionImpl conImpl = new ProtonConnectionImpl(mock(Vertx.class), "hostname", mock(ContextInternal.class));
    when(con.getTransport()).thenReturn(transport);
    when(con.getContext()).thenReturn(conImpl);
    Session session = mock(Session.class);
    ProtonSessionImpl sessionImpl = new ProtonSessionImpl(session);
    when(session.getConnection()).thenReturn(con);
    when(session.getContext()).thenReturn(sessionImpl);
    when(session.getIncomingCapacity()).thenReturn(10_000);
    when(session.getIncomingBytes()).thenReturn(10_000);
    Receiver r = mock(Receiver.class);
    when(r.getLocalState()).thenReturn(EndpointState.ACTIVE);
    when(r.getSession()).thenReturn(session);
    when(r.getMaxMessageSize()).thenReturn(new UnsignedLong(maxMessageSize));
    ProtonReceiverImpl recImpl = new ProtonReceiverImpl(r);
    when(r.getContext()).thenReturn(recImpl);
    ProtonMessageHandler messageHandler = mock(ProtonMessageHandler.class);
    ProtonReceiverImpl receiver = new ProtonReceiverImpl(r);
    receiver.handler(messageHandler);
    byte[] encodedMessage = createEncodedMessage(700);
    assertTrue(encodedMessage.length <= maxFrameSize);
    assertTrue(encodedMessage.length > maxMessageSize);
    ReadableBuffer frame0 = ReadableBuffer.ByteBufferReader.wrap(encodedMessage);
    Delivery delivery0 = mock(Delivery.class);
    when(delivery0.getLink()).thenReturn(r);
    when(delivery0.isPartial()).thenReturn(false);
    when(delivery0.available()).thenReturn(encodedMessage.length);
    when(delivery0.isSettled()).thenReturn(false);
    when(r.current()).thenReturn(delivery0);
    when(r.recv()).thenReturn(frame0);
    // WHEN delivering the message in a single transfer frame
    receiver.onDelivery();
    // THEN the receiver is being detached with the expected error condition
    verify(r).detach();
    ArgumentCaptor<ErrorCondition> conditionCapture = ArgumentCaptor.forClass(ErrorCondition.class);
    verify(r).setCondition(conditionCapture.capture());
    ErrorCondition errorCondition = conditionCapture.getValue();
    assertNotNull(errorCondition);
    assertEquals("Unxpected error condition", LinkError.MESSAGE_SIZE_EXCEEDED, errorCondition.getCondition());
    // and the message is not being delivered to the application layer
    verify(messageHandler, never()).handle(any(ProtonDelivery.class), any(Message.class));
}
Also used : UnsignedLong(org.apache.qpid.proton.amqp.UnsignedLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) Connection(org.apache.qpid.proton.engine.Connection) ProtonReceiver(io.vertx.proton.ProtonReceiver) Receiver(org.apache.qpid.proton.engine.Receiver) ContextInternal(io.vertx.core.impl.ContextInternal) Vertx(io.vertx.core.Vertx) ReadableBuffer(org.apache.qpid.proton.codec.ReadableBuffer) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Delivery(org.apache.qpid.proton.engine.Delivery) ProtonDelivery(io.vertx.proton.ProtonDelivery) Transport(org.apache.qpid.proton.engine.Transport) Session(org.apache.qpid.proton.engine.Session) Test(org.junit.Test)

Example 5 with ProtonMessageHandler

use of io.vertx.proton.ProtonMessageHandler in project vertx-proton by vert-x3.

the class ProtonReceiverImplTest method testMultiTransferExceedingMaxMessageSizeWithMaxMessageSizeExceededHandler.

/**
 * Verifies that the receivers maxMessageSizeExceeded closes the link with an
 * when receiving a multi-transfer message that exceeds the link's max-message-size.
 */
@SuppressWarnings("unchecked")
@Test
public void testMultiTransferExceedingMaxMessageSizeWithMaxMessageSizeExceededHandler() {
    int maxFrameSize = 512;
    long maxMessageSize = 650;
    Transport transport = mock(Transport.class);
    when(transport.getMaxFrameSize()).thenReturn(maxFrameSize);
    Connection con = mock(Connection.class);
    ProtonConnectionImpl conImpl = new ProtonConnectionImpl(mock(Vertx.class), "hostname", mock(ContextInternal.class));
    when(con.getTransport()).thenReturn(transport);
    when(con.getContext()).thenReturn(conImpl);
    Session session = mock(Session.class);
    ProtonSessionImpl sessionImpl = new ProtonSessionImpl(session);
    when(session.getConnection()).thenReturn(con);
    when(session.getContext()).thenReturn(sessionImpl);
    when(session.getIncomingCapacity()).thenReturn(10_000);
    when(session.getIncomingBytes()).thenReturn(10_000);
    Receiver r = mock(Receiver.class);
    when(r.getLocalState()).thenReturn(EndpointState.ACTIVE);
    when(r.getSession()).thenReturn(session);
    when(r.getMaxMessageSize()).thenReturn(new UnsignedLong(maxMessageSize));
    ProtonReceiverImpl recImpl = new ProtonReceiverImpl(r);
    when(r.getContext()).thenReturn(recImpl);
    ProtonMessageHandler messageHandler = mock(ProtonMessageHandler.class);
    Handler<ProtonReceiver> maxMessageSizeExceededHandler = mock(Handler.class);
    doAnswer(invocation -> {
        // Contrary to the default behaviour of detaching, the handler will close the link manually.
        ProtonReceiver receiver = invocation.getArgument(0);
        receiver.close();
        when(r.getLocalState()).thenReturn(EndpointState.CLOSED);
        return null;
    }).when(maxMessageSizeExceededHandler).handle(any(ProtonReceiver.class));
    ProtonReceiverImpl receiver = new ProtonReceiverImpl(r);
    receiver.handler(messageHandler);
    receiver.maxMessageSizeExceededHandler(maxMessageSizeExceededHandler);
    byte[] encodedMessage = createEncodedMessage(700);
    assertTrue(encodedMessage.length > maxFrameSize);
    assertTrue(encodedMessage.length <= 2 * maxFrameSize);
    assertTrue(encodedMessage.length > maxMessageSize);
    byte[] chunk0 = new byte[maxFrameSize];
    System.arraycopy(encodedMessage, 0, chunk0, 0, chunk0.length);
    ReadableBuffer frame0 = ReadableBuffer.ByteBufferReader.wrap(chunk0);
    Delivery delivery0 = mock(Delivery.class);
    when(delivery0.getLink()).thenReturn(r);
    when(delivery0.isPartial()).thenReturn(true);
    when(delivery0.available()).thenReturn(chunk0.length);
    when(delivery0.isSettled()).thenReturn(false);
    byte[] chunk1 = new byte[encodedMessage.length - maxFrameSize];
    System.arraycopy(encodedMessage, maxFrameSize, chunk1, 0, chunk1.length);
    ReadableBuffer frame1 = ReadableBuffer.ByteBufferReader.wrap(chunk1);
    Delivery delivery1 = mock(Delivery.class);
    when(delivery1.getLink()).thenReturn(r);
    when(delivery1.isPartial()).thenReturn(false);
    when(delivery1.available()).thenReturn(chunk1.length);
    when(delivery1.isSettled()).thenReturn(false);
    when(r.current()).thenReturn(delivery0, delivery1);
    when(r.recv()).thenReturn(frame0, frame1);
    // WHEN delivering the message in two consecutive transfer frames
    receiver.onDelivery();
    receiver.onDelivery();
    // THEN the maxMessageSizeExceeded handler is being invoked
    verify(maxMessageSizeExceededHandler).handle(receiver);
    // and the receiver has been closed by the maxMessageSizeExceeded handler
    verify(r).close();
    verify(r, never()).detach();
    // and the message is not being delivered to the application layer
    verify(messageHandler, never()).handle(any(ProtonDelivery.class), any(Message.class));
}
Also used : ProtonReceiver(io.vertx.proton.ProtonReceiver) UnsignedLong(org.apache.qpid.proton.amqp.UnsignedLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) Connection(org.apache.qpid.proton.engine.Connection) ProtonReceiver(io.vertx.proton.ProtonReceiver) Receiver(org.apache.qpid.proton.engine.Receiver) ContextInternal(io.vertx.core.impl.ContextInternal) Vertx(io.vertx.core.Vertx) ReadableBuffer(org.apache.qpid.proton.codec.ReadableBuffer) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Delivery(org.apache.qpid.proton.engine.Delivery) ProtonDelivery(io.vertx.proton.ProtonDelivery) Transport(org.apache.qpid.proton.engine.Transport) Session(org.apache.qpid.proton.engine.Session) Test(org.junit.Test)

Aggregations

ProtonMessageHandler (io.vertx.proton.ProtonMessageHandler)14 ProtonReceiver (io.vertx.proton.ProtonReceiver)13 Vertx (io.vertx.core.Vertx)11 Future (io.vertx.core.Future)9 ProtonDelivery (io.vertx.proton.ProtonDelivery)9 Message (org.apache.qpid.proton.message.Message)9 Handler (io.vertx.core.Handler)8 ProtonQoS (io.vertx.proton.ProtonQoS)8 ProtonHelper (io.vertx.proton.ProtonHelper)7 Truth.assertThat (com.google.common.truth.Truth.assertThat)5 Timeout (io.vertx.junit5.Timeout)5 VertxExtension (io.vertx.junit5.VertxExtension)5 VertxTestContext (io.vertx.junit5.VertxTestContext)5 HttpURLConnection (java.net.HttpURLConnection)5 TimeUnit (java.util.concurrent.TimeUnit)5 MessageHelper (org.eclipse.hono.util.MessageHelper)5 Test (org.junit.Test)5 BeforeEach (org.junit.jupiter.api.BeforeEach)5 Test (org.junit.jupiter.api.Test)5 ExtendWith (org.junit.jupiter.api.extension.ExtendWith)5