use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.
the class ProtonBasedApplicationClientTest method testCreateTelemetryConsumerReleasesMessageOnException.
/**
* Verifies that the message consumer created by the factory catches an exception
* thrown by the client provided handler and releases the message.
*
* @param ctx The vert.x test context.
*/
@Test
@SuppressWarnings("unchecked")
void testCreateTelemetryConsumerReleasesMessageOnException(final VertxTestContext ctx) {
// GIVEN a client provided message handler that throws an exception on
// each message received
final Handler<DownstreamMessage<AmqpMessageContext>> consumer = VertxMockSupport.mockHandler();
doThrow(new IllegalArgumentException("message does not contain required properties"), new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST)).when(consumer).handle(any(DownstreamMessage.class));
client.createTelemetryConsumer("tenant", consumer, t -> {
}).onComplete(ctx.succeeding(mc -> {
final ArgumentCaptor<ProtonMessageHandler> messageHandler = ArgumentCaptor.forClass(ProtonMessageHandler.class);
ctx.verify(() -> {
verify(connection).createReceiver(eq("telemetry/tenant"), eq(ProtonQoS.AT_LEAST_ONCE), messageHandler.capture(), anyInt(), anyBoolean(), VertxMockSupport.anyHandler());
final var msg = ProtonHelper.message();
// WHEN a message is received and the client provided consumer
// throws an IllegalArgumentException
var delivery = mock(ProtonDelivery.class);
messageHandler.getValue().handle(delivery, msg);
// THEN the message is forwarded to the client provided handler
verify(consumer).handle(any(DownstreamMessage.class));
// AND the AMQP message is being released
verify(delivery).disposition(any(Released.class), eq(Boolean.TRUE));
// WHEN a message is received and the client provided consumer
// throws a ClientErrorException
delivery = mock(ProtonDelivery.class);
messageHandler.getValue().handle(delivery, msg);
// THEN the message is forwarded to the client provided handler
verify(consumer, times(2)).handle(any(DownstreamMessage.class));
// AND the AMQP message is being rejected
verify(delivery).disposition(any(Rejected.class), eq(Boolean.TRUE));
});
ctx.completeNow();
}));
}
use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.
the class CommandAndControlAmqpIT method connectAndSubscribe.
private void connectAndSubscribe(final VertxTestContext ctx, final String commandTargetDeviceId, final AmqpCommandEndpointConfiguration endpointConfig, final BiFunction<ProtonReceiver, ProtonSender, ProtonMessageHandler> commandConsumerFactory, final int expectedNoOfCommands) throws InterruptedException {
final VertxTestContext setup = new VertxTestContext();
final Checkpoint setupDone = setup.checkpoint();
final Checkpoint notificationReceived = setup.checkpoint();
connectToAdapter(tenantId, deviceId, password, () -> createEventConsumer(tenantId, msg -> {
// expect empty notification with TTD -1
ctx.verify(() -> assertThat(msg.getContentType()).isEqualTo(EventConstants.CONTENT_TYPE_EMPTY_NOTIFICATION));
final TimeUntilDisconnectNotification notification = msg.getTimeUntilDisconnectNotification().orElse(null);
log.debug("received notification [{}]", notification);
ctx.verify(() -> assertThat(notification).isNotNull());
if (notification.getTtd() == -1) {
notificationReceived.flag();
}
})).compose(con -> createProducer(null, ProtonQoS.AT_LEAST_ONCE)).compose(sender -> subscribeToCommands(endpointConfig, tenantId, commandTargetDeviceId).map(recv -> {
recv.handler(commandConsumerFactory.apply(recv, sender));
// make sure that there are always enough credits, even if commands are sent faster than answered
recv.flow(expectedNoOfCommands);
return null;
})).onComplete(setup.succeeding(v -> setupDone.flag()));
assertWithMessage("connect and subscribe finished within %s seconds", IntegrationTestSupport.getTestSetupTimeout()).that(setup.awaitCompletion(IntegrationTestSupport.getTestSetupTimeout(), TimeUnit.SECONDS)).isTrue();
if (setup.failed()) {
ctx.failNow(setup.causeOfFailure());
}
}
use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.
the class ProtonBasedNotificationReceiverTest method testThatCorrectHandlerIsInvoked.
/**
* Verifies that the receiver decodes the notifications it receives and invokes the correct handler.
*
* @param ctx The vert.x test context.
*/
@Test
public void testThatCorrectHandlerIsInvoked(final VertxTestContext ctx) {
final String tenantId = "my-tenant";
final String deviceId = "my-device";
final Instant creationTime = Instant.parse("2007-12-03T10:15:30Z");
final TenantChangeNotification tenantChangeNotification = new TenantChangeNotification(LifecycleChange.CREATE, tenantId, creationTime, false);
final Message tenantChangeNotificationMsg = ProtonHelper.message();
MessageHelper.setJsonPayload(tenantChangeNotificationMsg, JsonObject.mapFrom(tenantChangeNotification));
final DeviceChangeNotification deviceChangeNotification = new DeviceChangeNotification(LifecycleChange.CREATE, tenantId, deviceId, creationTime, false);
final Message deviceChangeNotificationMsg = ProtonHelper.message();
MessageHelper.setJsonPayload(deviceChangeNotificationMsg, JsonObject.mapFrom(deviceChangeNotification));
final CredentialsChangeNotification credentialsChangeNotification = new CredentialsChangeNotification(tenantId, deviceId, creationTime);
final Message credentialsChangeNotificationMsg = ProtonHelper.message();
MessageHelper.setJsonPayload(credentialsChangeNotificationMsg, JsonObject.mapFrom(credentialsChangeNotification));
final AllDevicesOfTenantDeletedNotification allDevicesOfTenantDeletedChangeNotification = new AllDevicesOfTenantDeletedNotification(tenantId, creationTime);
final Message allDevicesOfTenantDeletedChangeNotificationMsg = ProtonHelper.message();
MessageHelper.setJsonPayload(allDevicesOfTenantDeletedChangeNotificationMsg, JsonObject.mapFrom(allDevicesOfTenantDeletedChangeNotification));
final Checkpoint handlerInvokedCheckpoint = ctx.checkpoint(4);
client.registerConsumer(TenantChangeNotification.TYPE, notification -> ctx.verify(() -> {
assertThat(notification).isInstanceOf(TenantChangeNotification.class);
handlerInvokedCheckpoint.flag();
}));
client.registerConsumer(DeviceChangeNotification.TYPE, notification -> ctx.verify(() -> {
assertThat(notification).isInstanceOf(DeviceChangeNotification.class);
handlerInvokedCheckpoint.flag();
}));
client.registerConsumer(CredentialsChangeNotification.TYPE, notification -> ctx.verify(() -> {
assertThat(notification).isInstanceOf(CredentialsChangeNotification.class);
handlerInvokedCheckpoint.flag();
}));
client.registerConsumer(AllDevicesOfTenantDeletedNotification.TYPE, notification -> ctx.verify(() -> {
assertThat(notification).isInstanceOf(AllDevicesOfTenantDeletedNotification.class);
handlerInvokedCheckpoint.flag();
}));
// WHEN starting the client
client.start().onComplete(ctx.succeeding(v -> ctx.verify(() -> {
// THEN the receiver links got created
final Map<String, ProtonMessageHandler> receiverMsgHandlersPerAddress = assertReceiverLinkCreated(connection);
assertThat(receiverMsgHandlersPerAddress).containsKey(NotificationAddressHelper.getAddress(TenantChangeNotification.TYPE));
assertThat(receiverMsgHandlersPerAddress).containsKey(NotificationAddressHelper.getAddress(DeviceChangeNotification.TYPE));
assertThat(receiverMsgHandlersPerAddress).containsKey(NotificationAddressHelper.getAddress(CredentialsChangeNotification.TYPE));
assertThat(receiverMsgHandlersPerAddress).containsKey(NotificationAddressHelper.getAddress(AllDevicesOfTenantDeletedNotification.TYPE));
final ProtonMessageHandler tenantChangeReceiverMsgHandler = receiverMsgHandlersPerAddress.get(NotificationAddressHelper.getAddress(TenantChangeNotification.TYPE));
final ProtonMessageHandler deviceChangeReceiverMsgHandler = receiverMsgHandlersPerAddress.get(NotificationAddressHelper.getAddress(DeviceChangeNotification.TYPE));
final ProtonMessageHandler credentialsChangeReceiverMsgHandler = receiverMsgHandlersPerAddress.get(NotificationAddressHelper.getAddress(CredentialsChangeNotification.TYPE));
final ProtonMessageHandler allDevicesOfTenantDeletedChangeReceiverMsgHandler = receiverMsgHandlersPerAddress.get(NotificationAddressHelper.getAddress(AllDevicesOfTenantDeletedNotification.TYPE));
// and sending notifications on the links
tenantChangeReceiverMsgHandler.handle(mock(ProtonDelivery.class), tenantChangeNotificationMsg);
deviceChangeReceiverMsgHandler.handle(mock(ProtonDelivery.class), deviceChangeNotificationMsg);
credentialsChangeReceiverMsgHandler.handle(mock(ProtonDelivery.class), credentialsChangeNotificationMsg);
allDevicesOfTenantDeletedChangeReceiverMsgHandler.handle(mock(ProtonDelivery.class), allDevicesOfTenantDeletedChangeNotificationMsg);
// causes the client to receive the notifications and the handlerInvokedCheckpoint to get flagged
})));
}
use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.
the class ProtonBasedNotificationReceiverTest method testRegisterCommandConsumer.
/**
* Verifies that the client with a registered consumer receives notification messages.
*
* @param ctx The vert.x test context.
*/
@Test
public void testRegisterCommandConsumer(final VertxTestContext ctx) {
final String tenantId = "my-tenant";
final Instant creationTime = Instant.parse("2007-12-03T10:15:30Z");
final TenantChangeNotification notification = new TenantChangeNotification(LifecycleChange.CREATE, tenantId, creationTime, false);
final Message notificationMessage = ProtonHelper.message();
MessageHelper.setJsonPayload(notificationMessage, JsonObject.mapFrom(notification));
// GIVEN a client where a TenantChangeNotification consumer gets registered
final AtomicReference<TenantChangeNotification> receivedNotificationRef = new AtomicReference<>();
client.registerConsumer(TenantChangeNotification.TYPE, receivedNotificationRef::set);
// WHEN starting the client
client.start().onComplete(ctx.succeeding(v -> {
ctx.verify(() -> {
// THEN a receiver link got created
final ProtonMessageHandler receiverMessageHandler = AmqpClientUnitTestHelper.assertReceiverLinkCreated(connection);
// and sending a notification on the link
receiverMessageHandler.handle(mock(ProtonDelivery.class), notificationMessage);
// causes the client to receive the notification
assertThat(receivedNotificationRef.get()).isNotNull();
});
ctx.completeNow();
}));
}
Aggregations