use of io.vertx.mqtt.messages.MqttSubscribeMessage in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method testOnSubscribeRegistersAndClosesConnection.
private void testOnSubscribeRegistersAndClosesConnection(final MqttQoS qos) {
// GIVEN a device connected to an adapter
givenAnAdapter(properties);
givenAnEventSenderForAnyTenant();
final MqttEndpoint endpoint = mockEndpoint();
// 10 seconds
when(endpoint.keepAliveTimeSeconds()).thenReturn(10);
// WHEN a device subscribes to commands
final CommandConsumer commandConsumer = mock(CommandConsumer.class);
when(commandConsumer.close(any())).thenReturn(Future.succeededFuture());
when(commandConsumerFactory.createCommandConsumer(eq("tenant"), eq("deviceId"), VertxMockSupport.anyHandler(), any(), any())).thenReturn(Future.succeededFuture(commandConsumer));
final List<MqttTopicSubscription> subscriptions = Collections.singletonList(newMockTopicSubscription(getCommandSubscriptionTopic("tenant", "deviceId"), qos));
final MqttSubscribeMessage msg = mock(MqttSubscribeMessage.class);
when(msg.messageId()).thenReturn(15);
when(msg.topicSubscriptions()).thenReturn(subscriptions);
final var mqttDeviceEndpoint = adapter.createMqttDeviceEndpoint(endpoint, null, OptionalInt.empty());
endpoint.closeHandler(handler -> mqttDeviceEndpoint.onClose());
mqttDeviceEndpoint.onSubscribe(msg);
// THEN the adapter creates a command consumer that is checked periodically
verify(commandConsumerFactory).createCommandConsumer(eq("tenant"), eq("deviceId"), VertxMockSupport.anyHandler(), any(), any());
// and the adapter registers a hook on the connection to the device
final ArgumentCaptor<Handler<Void>> closeHookCaptor = VertxMockSupport.argumentCaptorHandler();
verify(endpoint).closeHandler(closeHookCaptor.capture());
// which closes the command consumer when the device disconnects
closeHookCaptor.getValue().handle(null);
verify(commandConsumer).close(any());
// and sends an empty notification downstream with TTD 0
assertEmptyNotificationHasBeenSentDownstream("tenant", "deviceId", 0);
}
use of io.vertx.mqtt.messages.MqttSubscribeMessage in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method testAdapterSkipsTtdEventOnCmdConnectionCloseIfRemoveConsumerFails.
/**
* Verifies that the adapter doesn't send a 'disconnectedTtdEvent' on connection loss
* when removal of the command consumer mapping entry fails (which would be the case
* when another command consumer mapping had been registered in the mean time, meaning
* the device has already reconnected).
*/
@Test
public void testAdapterSkipsTtdEventOnCmdConnectionCloseIfRemoveConsumerFails() {
// GIVEN a device connected to an adapter
givenAnAdapter(properties);
givenAnEventSenderForAnyTenant();
final MqttEndpoint endpoint = mockEndpoint();
when(endpoint.isConnected()).thenReturn(true);
// 10 seconds
when(endpoint.keepAliveTimeSeconds()).thenReturn(10);
// WHEN a device subscribes to commands
final CommandConsumer commandConsumer = mock(CommandConsumer.class);
when(commandConsumer.close(any())).thenReturn(Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_PRECON_FAILED)));
when(commandConsumerFactory.createCommandConsumer(eq("tenant"), eq("deviceId"), VertxMockSupport.anyHandler(), any(), any())).thenReturn(Future.succeededFuture(commandConsumer));
final List<MqttTopicSubscription> subscriptions = Collections.singletonList(newMockTopicSubscription(getCommandSubscriptionTopic("tenant", "deviceId"), MqttQoS.AT_MOST_ONCE));
final MqttSubscribeMessage msg = mock(MqttSubscribeMessage.class);
when(msg.messageId()).thenReturn(15);
when(msg.topicSubscriptions()).thenReturn(subscriptions);
final var mqttDeviceEndpoint = adapter.createMqttDeviceEndpoint(endpoint, null, OptionalInt.empty());
endpoint.closeHandler(handler -> mqttDeviceEndpoint.onClose());
mqttDeviceEndpoint.onSubscribe(msg);
// THEN the adapter creates a command consumer that is checked periodically
verify(commandConsumerFactory).createCommandConsumer(eq("tenant"), eq("deviceId"), VertxMockSupport.anyHandler(), any(), any());
// and the adapter registers a hook on the connection to the device
final ArgumentCaptor<Handler<Void>> closeHookCaptor = VertxMockSupport.argumentCaptorHandler();
verify(endpoint).closeHandler(closeHookCaptor.capture());
// which closes the command consumer when the device disconnects
closeHookCaptor.getValue().handle(null);
when(endpoint.isConnected()).thenReturn(false);
verify(commandConsumer).close(any());
// and since closing the command consumer fails with a precon-failed exception
// there is only one notification sent during consumer creation,
assertEmptyNotificationHasBeenSentDownstream("tenant", "deviceId", -1);
// no 'disconnectedTtdEvent' event with TTD = 0
assertEmptyNotificationHasNotBeenSentDownstream("tenant", "deviceId", 0);
}
use of io.vertx.mqtt.messages.MqttSubscribeMessage in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method testOnSubscribeIncludesStatusCodeForEachFilter.
/**
* Verifies that the adapter includes a status code for each topic filter in its SUBACK packet.
*/
@SuppressWarnings("unchecked")
@Test
public void testOnSubscribeIncludesStatusCodeForEachFilter() {
// GIVEN a device connected to an adapter
givenAnAdapter(properties);
givenAnEventSenderForAnyTenant();
final MqttEndpoint endpoint = mockEndpoint();
when(endpoint.isConnected()).thenReturn(true);
// WHEN a device sends a SUBSCRIBE packet for several unsupported filters
final List<MqttTopicSubscription> subscriptions = new ArrayList<>();
subscriptions.add(newMockTopicSubscription("unsupported/#", MqttQoS.AT_LEAST_ONCE));
subscriptions.add(newMockTopicSubscription("bumlux/+/+/#", MqttQoS.AT_MOST_ONCE));
subscriptions.add(newMockTopicSubscription("bumlux/+/+/#", MqttQoS.AT_MOST_ONCE));
// and for subscribing to commands
final CommandConsumer commandConsumer = mock(CommandConsumer.class);
when(commandConsumer.close(any())).thenReturn(Future.succeededFuture());
when(commandConsumerFactory.createCommandConsumer(eq("tenant-1"), eq("device-A"), VertxMockSupport.anyHandler(), any(), any())).thenReturn(Future.succeededFuture(commandConsumer));
subscriptions.add(newMockTopicSubscription(getCommandSubscriptionTopic("tenant-1", "device-A"), MqttQoS.AT_MOST_ONCE));
subscriptions.add(newMockTopicSubscription(getCommandSubscriptionTopic("tenant-1", "device-B"), MqttQoS.EXACTLY_ONCE));
final MqttSubscribeMessage msg = mock(MqttSubscribeMessage.class);
when(msg.messageId()).thenReturn(15);
when(msg.topicSubscriptions()).thenReturn(subscriptions);
final var mqttDeviceEndpoint = adapter.createMqttDeviceEndpoint(endpoint, null, OptionalInt.empty());
mqttDeviceEndpoint.onSubscribe(msg);
// THEN the adapter sends a SUBACK packet to the device
// which contains a failure status code for each unsupported filter
final ArgumentCaptor<List<MqttQoS>> codeCaptor = ArgumentCaptor.forClass(List.class);
verify(endpoint).subscribeAcknowledge(eq(15), codeCaptor.capture());
assertThat(codeCaptor.getValue()).hasSize(5);
assertThat(codeCaptor.getValue().get(0)).isEqualTo(MqttQoS.FAILURE);
assertThat(codeCaptor.getValue().get(1)).isEqualTo(MqttQoS.FAILURE);
assertThat(codeCaptor.getValue().get(2)).isEqualTo(MqttQoS.FAILURE);
assertThat(codeCaptor.getValue().get(3)).isEqualTo(MqttQoS.AT_MOST_ONCE);
// and sends an empty notification downstream with TTD -1
assertEmptyNotificationHasBeenSentDownstream("tenant-1", "device-A", -1);
}
Aggregations