use of io.vertx.proton.ProtonSender in project hono by eclipse.
the class ForwardingEventDownstreamAdapterTest method testProcessMessageReleasesMessageIfNoCreditIsAvailable.
/**
* Verifies that an event is released if no downstream credit is available.
*
* @param ctx The test context.
*/
@SuppressWarnings("unchecked")
@Test
public void testProcessMessageReleasesMessageIfNoCreditIsAvailable(final TestContext ctx) {
final UpstreamReceiver client = newClient();
final ProtonDelivery delivery = mock(ProtonDelivery.class);
when(delivery.remotelySettled()).thenReturn(Boolean.FALSE);
// GIVEN an adapter with a connection to a downstream container
ProtonSender sender = newMockSender(false);
when(sender.sendQueueFull()).thenReturn(true);
ForwardingEventDownstreamAdapter adapter = new ForwardingEventDownstreamAdapter(vertx, newMockSenderFactory(sender));
adapter.setMetrics(mock(MessagingMetrics.class));
adapter.setDownstreamConnectionFactory(newMockConnectionFactory(false));
adapter.start(Future.future());
adapter.addSender(client, sender);
// WHEN processing an event
Message msg = ProtonHelper.message(EVENT_MSG_CONTENT);
MessageHelper.addDeviceId(msg, DEVICE_ID);
adapter.processMessage(client, delivery, msg);
// THEN the message is released
verify(delivery).disposition(any(Released.class), eq(Boolean.TRUE));
// and not delivered to the downstream container
verify(sender, never()).send(any(Message.class), any(Handler.class));
}
use of io.vertx.proton.ProtonSender in project hono by eclipse.
the class ForwardingDownstreamAdapterTest method testDownstreamLinkHandlerClosesUpstreamReceiver.
@SuppressWarnings({ "unchecked", "rawtypes" })
private void testDownstreamLinkHandlerClosesUpstreamReceiver(final BiConsumer<ProtonSender, ArgumentCaptor<Handler>> handlerCaptor) {
final UpstreamReceiver client = newClient();
final ProtonSender downstreamSender = newMockSender(false);
when(downstreamSender.isOpen()).thenReturn(Boolean.FALSE);
final HandlerCapturingConnectionFactory factory = new HandlerCapturingConnectionFactory(con);
// GIVEN an adapter connected to a downstream container
givenADownstreamAdapter(downstreamSender);
adapter.setDownstreamConnectionFactory(factory);
adapter.start(Future.future());
adapter.onClientAttach(client, s -> {
});
final ArgumentCaptor<Handler> captor = ArgumentCaptor.forClass(Handler.class);
handlerCaptor.accept(downstreamSender, captor);
// WHEN the downstream container detaches the sender link
captor.getValue().handle(Future.succeededFuture(downstreamSender));
// THEN the upstream client is closed
verify(client).close(any());
// and the sender is removed from the list of active senders
assertTrue(adapter.isActiveSendersEmpty());
}
use of io.vertx.proton.ProtonSender in project hono by eclipse.
the class RequestResponseEndpoint method onLinkAttach.
/**
* Handles a client's request to establish a link for receiving responses
* to service invocations.
* <p>
* This method registers a consumer on the vert.x event bus for the given reply-to address.
* Response messages received over the event bus are transformed into AMQP messages using
* the {@link #getAmqpReply(EventBusMessage)} method and sent to the client over the established
* link.
*
* @param con The AMQP connection that the link is part of.
* @param sender The link to establish.
* @param replyToAddress The reply-to address to create a consumer on the event bus for.
*/
@Override
public final void onLinkAttach(final ProtonConnection con, final ProtonSender sender, final ResourceIdentifier replyToAddress) {
if (isValidReplyToAddress(replyToAddress)) {
logger.debug("establishing sender link with client [{}]", sender.getName());
final MessageConsumer<JsonObject> replyConsumer = vertx.eventBus().consumer(replyToAddress.toString(), message -> {
// TODO check for correct session here...?
if (logger.isTraceEnabled()) {
logger.trace("forwarding reply to client [{}]: {}", sender.getName(), message.body().encodePrettily());
}
final EventBusMessage response = EventBusMessage.fromJson(message.body());
filterResponse(Constants.getClientPrincipal(con), response).recover(t -> {
final int status = Optional.of(t).map(cause -> {
if (cause instanceof ServiceInvocationException) {
return ((ServiceInvocationException) cause).getErrorCode();
} else {
return null;
}
}).orElse(HttpURLConnection.HTTP_INTERNAL_ERROR);
return Future.succeededFuture(response.getResponse(status));
}).map(filteredResponse -> {
final Message amqpReply = getAmqpReply(filteredResponse);
sender.send(amqpReply);
return null;
});
});
sender.setQoS(ProtonQoS.AT_LEAST_ONCE);
sender.closeHandler(senderClosed -> {
logger.debug("client [{}] closed sender link, removing associated event bus consumer [{}]", sender.getName(), replyConsumer.address());
replyConsumer.unregister();
if (senderClosed.succeeded()) {
senderClosed.result().close();
}
});
sender.open();
} else {
logger.debug("client [{}] provided invalid reply-to address", sender.getName());
sender.setCondition(ProtonHelper.condition(AmqpError.INVALID_FIELD, String.format("reply-to address must have the following format %s/<tenant>/<reply-address>", getName())));
sender.close();
}
}
use of io.vertx.proton.ProtonSender in project hono by eclipse.
the class AbstractHonoClientTest method testCreateSenderFails.
@SuppressWarnings({ "unchecked", "rawtypes" })
private void testCreateSenderFails(final Supplier<ErrorCondition> errorSupplier, final Predicate<Throwable> failureAssertion) {
final Record attachments = new RecordImpl();
final ProtonSender sender = mock(ProtonSender.class);
when(sender.getRemoteCondition()).thenReturn(errorSupplier.get());
when(sender.attachments()).thenReturn(attachments);
final ProtonConnection con = mock(ProtonConnection.class);
when(con.createSender(anyString())).thenReturn(sender);
final Future<ProtonSender> result = AbstractHonoClient.createSender(context, props, con, "target", ProtonQoS.AT_LEAST_ONCE, null);
final ArgumentCaptor<Handler> openHandler = ArgumentCaptor.forClass(Handler.class);
verify(sender).openHandler(openHandler.capture());
openHandler.getValue().handle(Future.failedFuture(new IllegalStateException()));
assertTrue(result.failed());
assertTrue(failureAssertion.test(result.cause()));
}
use of io.vertx.proton.ProtonSender in project hono by eclipse.
the class HonoClientUnitTestHelper method mockProtonSender.
/**
* Creates a mocked Proton sender which always returns {@code true} when its isOpen method is called.
*
* @return The mocked sender.
*/
public static final ProtonSender mockProtonSender() {
final ProtonSender sender = mock(ProtonSender.class);
when(sender.isOpen()).thenReturn(Boolean.TRUE);
return sender;
}
Aggregations