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));
}
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));
}
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));
}
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));
}
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));
}
Aggregations