Search in sources :

Example 1 with MqttSubscribeMessage

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);
}
Also used : MqttSubscribeMessage(io.vertx.mqtt.messages.MqttSubscribeMessage) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) MqttTopicSubscription(io.vertx.mqtt.MqttTopicSubscription) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) AuthHandler(org.eclipse.hono.adapter.auth.device.AuthHandler) Handler(io.vertx.core.Handler)

Example 2 with MqttSubscribeMessage

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);
}
Also used : MqttSubscribeMessage(io.vertx.mqtt.messages.MqttSubscribeMessage) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) MqttTopicSubscription(io.vertx.mqtt.MqttTopicSubscription) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) ClientErrorException(org.eclipse.hono.client.ClientErrorException) AuthHandler(org.eclipse.hono.adapter.auth.device.AuthHandler) Handler(io.vertx.core.Handler) Test(org.junit.jupiter.api.Test)

Example 3 with MqttSubscribeMessage

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);
}
Also used : MqttSubscribeMessage(io.vertx.mqtt.messages.MqttSubscribeMessage) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) MqttTopicSubscription(io.vertx.mqtt.MqttTopicSubscription) ArrayList(java.util.ArrayList) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) List(java.util.List) ArrayList(java.util.ArrayList) Test(org.junit.jupiter.api.Test)

Aggregations

MqttEndpoint (io.vertx.mqtt.MqttEndpoint)3 MqttTopicSubscription (io.vertx.mqtt.MqttTopicSubscription)3 MqttSubscribeMessage (io.vertx.mqtt.messages.MqttSubscribeMessage)3 CommandConsumer (org.eclipse.hono.client.command.CommandConsumer)3 Handler (io.vertx.core.Handler)2 AuthHandler (org.eclipse.hono.adapter.auth.device.AuthHandler)2 Test (org.junit.jupiter.api.Test)2 ArrayList (java.util.ArrayList)1 List (java.util.List)1 ClientErrorException (org.eclipse.hono.client.ClientErrorException)1