Search in sources :

Example 66 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class VertxBasedAmqpProtocolAdapterTest 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).
 *
 * @param ctx The vert.x test context.
 * @throws InterruptedException if the test execution gets interrupted.
 */
@Test
public void testAdapterSkipsTtdEventOnCmdConnectionCloseIfRemoveConsumerFails(final VertxTestContext ctx) throws InterruptedException {
    // GIVEN an AMQP adapter
    givenAnAdapter(properties);
    givenAnEventSenderForAnyTenant();
    final Promise<Void> startupTracker = Promise.promise();
    startupTracker.future().onComplete(ctx.succeedingThenComplete());
    adapter.start(startupTracker);
    assertThat(ctx.awaitCompletion(2, TimeUnit.SECONDS)).isTrue();
    // to which a device is connected
    final Device authenticatedDevice = new Device(TEST_TENANT_ID, TEST_DEVICE);
    final Record record = new RecordImpl();
    record.set(AmqpAdapterConstants.KEY_CLIENT_DEVICE, Device.class, authenticatedDevice);
    final ProtonConnection deviceConnection = mock(ProtonConnection.class);
    when(deviceConnection.attachments()).thenReturn(record);
    final ArgumentCaptor<Handler<ProtonConnection>> connectHandler = VertxMockSupport.argumentCaptorHandler();
    verify(server).connectHandler(connectHandler.capture());
    connectHandler.getValue().handle(deviceConnection);
    // that wants to receive commands
    final CommandConsumer commandConsumer = mock(CommandConsumer.class);
    when(commandConsumer.close(any())).thenReturn(Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_PRECON_FAILED)));
    when(commandConsumerFactory.createCommandConsumer(eq(TEST_TENANT_ID), eq(TEST_DEVICE), VertxMockSupport.anyHandler(), any(), any())).thenReturn(Future.succeededFuture(commandConsumer));
    final String sourceAddress = getCommandEndpoint();
    final ProtonSender sender = getSender(sourceAddress);
    adapter.handleRemoteSenderOpenForCommands(deviceConnection, sender);
    // WHEN the connection to the device is lost
    final ArgumentCaptor<Handler<AsyncResult<ProtonConnection>>> closeHandler = VertxMockSupport.argumentCaptorHandler();
    verify(deviceConnection).closeHandler(closeHandler.capture());
    closeHandler.getValue().handle(Future.succeededFuture(deviceConnection));
    // THEN the adapter closes the command consumer
    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(TEST_TENANT_ID, TEST_DEVICE, -1);
    // no 'disconnectedTtdEvent' event with TTD = 0
    assertEmptyNotificationHasNotBeenSentDownstream(TEST_TENANT_ID, TEST_DEVICE, 0);
}
Also used : Device(org.eclipse.hono.auth.Device) Handler(io.vertx.core.Handler) RecordImpl(org.apache.qpid.proton.engine.impl.RecordImpl) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonSender(io.vertx.proton.ProtonSender) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Record(org.apache.qpid.proton.engine.Record) Test(org.junit.jupiter.api.Test)

Example 67 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class VertxBasedAmqpProtocolAdapterTest method getConnection.

private ProtonConnection getConnection(final Device device) {
    final ProtonConnection conn = mock(ProtonConnection.class);
    final Record record = mock(Record.class);
    when(record.get(anyString(), eq(Device.class))).thenReturn(device);
    when(conn.attachments()).thenReturn(record);
    return conn;
}
Also used : ProtonConnection(io.vertx.proton.ProtonConnection) Device(org.eclipse.hono.auth.Device) Record(org.apache.qpid.proton.engine.Record)

Example 68 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class VertxBasedAmqpProtocolAdapterTest method testConnectionFailsForAuthenticatedDeviceIfAdapterLevelConnectionLimitIsExceeded.

/**
 * Verifies that an authenticated device's attempt to establish a connection fails if
 * the adapter's connection limit is exceeded.
 */
@Test
public void testConnectionFailsForAuthenticatedDeviceIfAdapterLevelConnectionLimitIsExceeded() {
    // GIVEN an AMQP adapter that requires devices to authenticate
    properties.setAuthenticationRequired(true);
    givenAnAdapter(properties);
    // WHEN the adapter's connection limit exceeds
    when(connectionLimitManager.isLimitExceeded()).thenReturn(true);
    // WHEN a device connects
    final Device authenticatedDevice = new Device(TEST_TENANT_ID, TEST_DEVICE);
    final Record record = new RecordImpl();
    record.set(AmqpAdapterConstants.KEY_CLIENT_DEVICE, Device.class, authenticatedDevice);
    record.set(AmqpAdapterConstants.KEY_TLS_CIPHER_SUITE, String.class, "BUMLUX_CIPHER");
    final ProtonConnection deviceConnection = mock(ProtonConnection.class);
    when(deviceConnection.attachments()).thenReturn(record);
    adapter.onConnectRequest(deviceConnection);
    @SuppressWarnings("unchecked") final ArgumentCaptor<Handler<AsyncResult<ProtonConnection>>> openHandler = ArgumentCaptor.forClass(Handler.class);
    verify(deviceConnection).openHandler(openHandler.capture());
    openHandler.getValue().handle(Future.succeededFuture(deviceConnection));
    // THEN the connection count should be incremented when the connection is opened
    final InOrder metricsInOrderVerifier = inOrder(metrics);
    metricsInOrderVerifier.verify(metrics).incrementConnections(TEST_TENANT_ID);
    // AND the adapter should close the connection right after it opened it
    final ArgumentCaptor<Handler<AsyncResult<ProtonConnection>>> closeHandler = VertxMockSupport.argumentCaptorHandler();
    verify(deviceConnection).closeHandler(closeHandler.capture());
    closeHandler.getValue().handle(Future.succeededFuture());
    final ArgumentCaptor<ErrorCondition> errorConditionCaptor = ArgumentCaptor.forClass(ErrorCondition.class);
    verify(deviceConnection).setCondition(errorConditionCaptor.capture());
    assertEquals(AmqpError.UNAUTHORIZED_ACCESS, errorConditionCaptor.getValue().getCondition());
    // AND the connection count should be decremented accordingly when the connection is closed
    metricsInOrderVerifier.verify(metrics).decrementConnections(TEST_TENANT_ID);
    verify(metrics).reportConnectionAttempt(ConnectionAttemptOutcome.ADAPTER_CONNECTIONS_EXCEEDED, TEST_TENANT_ID, "BUMLUX_CIPHER");
}
Also used : ProtonConnection(io.vertx.proton.ProtonConnection) InOrder(org.mockito.InOrder) Device(org.eclipse.hono.auth.Device) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) Handler(io.vertx.core.Handler) Record(org.apache.qpid.proton.engine.Record) RecordImpl(org.apache.qpid.proton.engine.impl.RecordImpl) Test(org.junit.jupiter.api.Test)

Example 69 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class VertxBasedAmqpProtocolAdapterTest method testAdapterSupportsAnonymousRelay.

/**
 * Verifies that the adapter offers the ANONYMOUS-RELAY capability
 * in its open frame when a device connects.
 */
@Test
public void testAdapterSupportsAnonymousRelay() {
    // GIVEN an AMQP adapter with a configured server.
    givenAnAdapter(properties);
    // WHEN a device connects
    final Device authenticatedDevice = new Device(TEST_TENANT_ID, TEST_DEVICE);
    final Record record = new RecordImpl();
    record.set(AmqpAdapterConstants.KEY_CLIENT_DEVICE, Device.class, authenticatedDevice);
    final ProtonConnection deviceConnection = mock(ProtonConnection.class);
    when(deviceConnection.attachments()).thenReturn(record);
    when(deviceConnection.getRemoteContainer()).thenReturn("deviceContainer");
    adapter.onConnectRequest(deviceConnection);
    final ArgumentCaptor<Handler<AsyncResult<ProtonConnection>>> openHandler = VertxMockSupport.argumentCaptorHandler();
    verify(deviceConnection).openHandler(openHandler.capture());
    openHandler.getValue().handle(Future.succeededFuture(deviceConnection));
    // THEN the adapter's open frame contains the ANONYMOUS-RELAY capability
    verify(deviceConnection).setOfferedCapabilities(argThat(caps -> Arrays.asList(caps).contains(Constants.CAP_ANONYMOUS_RELAY)));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) ProtonConnection(io.vertx.proton.ProtonConnection) BeforeEach(org.junit.jupiter.api.BeforeEach) Arrays(java.util.Arrays) LifecycleChange(org.eclipse.hono.notification.deviceregistry.LifecycleChange) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) ProcessingOutcome(org.eclipse.hono.service.metric.MetricsTags.ProcessingOutcome) MessagingType(org.eclipse.hono.util.MessagingType) EventBus(io.vertx.core.eventbus.EventBus) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Mockito.doAnswer(org.mockito.Mockito.doAnswer) Map(java.util.Map) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) AmqpError(org.apache.qpid.proton.amqp.transport.AmqpError) CommandContext(org.eclipse.hono.client.command.CommandContext) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) EventConstants(org.eclipse.hono.util.EventConstants) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) Span(io.opentracing.Span) NotificationEventBusSupport(org.eclipse.hono.notification.NotificationEventBusSupport) Mockito.mock(org.mockito.Mockito.mock) VertxTestContext(io.vertx.junit5.VertxTestContext) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) Target(org.apache.qpid.proton.amqp.messaging.Target) ArgumentMatchers.anyBoolean(org.mockito.ArgumentMatchers.anyBoolean) Commands(org.eclipse.hono.client.command.Commands) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) AsyncResult(io.vertx.core.AsyncResult) CommandConstants(org.eclipse.hono.util.CommandConstants) Direction(org.eclipse.hono.service.metric.MetricsTags.Direction) Vertx(io.vertx.core.Vertx) Mockito.times(org.mockito.Mockito.times) ProtonHelper(io.vertx.proton.ProtonHelper) Released(org.apache.qpid.proton.amqp.messaging.Released) SpanContext(io.opentracing.SpanContext) Mockito.never(org.mockito.Mockito.never) ConnectionAttemptOutcome(org.eclipse.hono.service.metric.MetricsTags.ConnectionAttemptOutcome) ResourceLimitChecks(org.eclipse.hono.adapter.resourcelimits.ResourceLimitChecks) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) ProtonReceiver(io.vertx.proton.ProtonReceiver) ArgumentMatchers.argThat(org.mockito.ArgumentMatchers.argThat) DeviceChangeNotification(org.eclipse.hono.notification.deviceregistry.DeviceChangeNotification) Context(io.vertx.core.Context) ProtonServer(io.vertx.proton.ProtonServer) Timeout(io.vertx.junit5.Timeout) EndpointType(org.eclipse.hono.service.metric.MetricsTags.EndpointType) NotificationType(org.eclipse.hono.notification.NotificationType) TracingMockSupport(org.eclipse.hono.test.TracingMockSupport) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) Binary(org.apache.qpid.proton.amqp.Binary) AllDevicesOfTenantDeletedNotification(org.eclipse.hono.notification.deviceregistry.AllDevicesOfTenantDeletedNotification) Data(org.apache.qpid.proton.amqp.messaging.Data) MetricsTags(org.eclipse.hono.service.metric.MetricsTags) ProtonQoS(io.vertx.proton.ProtonQoS) Instant(java.time.Instant) MessageHelper(org.eclipse.hono.util.MessageHelper) VertxExtension(io.vertx.junit5.VertxExtension) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) Test(org.junit.jupiter.api.Test) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) Buffer(io.vertx.core.buffer.Buffer) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) Mockito.inOrder(org.mockito.Mockito.inOrder) ProtonSender(io.vertx.proton.ProtonSender) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) QoS(org.eclipse.hono.util.QoS) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) AbstractNotification(org.eclipse.hono.notification.AbstractNotification) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ProtonDelivery(io.vertx.proton.ProtonDelivery) ConnectionLimitManager(org.eclipse.hono.adapter.limiting.ConnectionLimitManager) HashMap(java.util.HashMap) ClientErrorException(org.eclipse.hono.client.ClientErrorException) ConnectionEventProducer(org.eclipse.hono.adapter.monitoring.ConnectionEventProducer) CommandResponseSender(org.eclipse.hono.client.command.CommandResponseSender) Constants(org.eclipse.hono.util.Constants) ProtocolAdapterTestSupport(org.eclipse.hono.adapter.test.ProtocolAdapterTestSupport) TelemetryConstants(org.eclipse.hono.util.TelemetryConstants) ArgumentCaptor(org.mockito.ArgumentCaptor) RecordImpl(org.apache.qpid.proton.engine.impl.RecordImpl) Message(org.apache.qpid.proton.message.Message) HttpUtils(org.eclipse.hono.service.http.HttpUtils) TenantChangeNotification(org.eclipse.hono.notification.deviceregistry.TenantChangeNotification) InOrder(org.mockito.InOrder) Promise(io.vertx.core.Promise) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) Mockito.verify(org.mockito.Mockito.verify) ApplicationProperties(org.apache.qpid.proton.amqp.messaging.ApplicationProperties) CommandResponse(org.eclipse.hono.client.command.CommandResponse) TenantObject(org.eclipse.hono.util.TenantObject) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) Source(org.apache.qpid.proton.amqp.transport.Source) Adapter(org.eclipse.hono.util.Adapter) Handler(io.vertx.core.Handler) Record(org.apache.qpid.proton.engine.Record) ProtonConnection(io.vertx.proton.ProtonConnection) Device(org.eclipse.hono.auth.Device) Handler(io.vertx.core.Handler) Record(org.apache.qpid.proton.engine.Record) RecordImpl(org.apache.qpid.proton.engine.impl.RecordImpl) Test(org.junit.jupiter.api.Test)

Example 70 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class VertxBasedAmqpProtocolAdapterTest method testAdapterClosesCommandConsumer.

/**
 * Verifies that the adapter closes a corresponding command consumer if
 * the connection to a device fails unexpectedly.
 *
 * @param ctx The vert.x test context.
 * @throws InterruptedException if the test execution gets interrupted.
 */
private void testAdapterClosesCommandConsumer(final VertxTestContext ctx, final Handler<ProtonConnection> connectionLossTrigger) throws InterruptedException {
    // GIVEN an AMQP adapter
    givenAnAdapter(properties);
    givenAnEventSenderForAnyTenant();
    final Promise<Void> startupTracker = Promise.promise();
    startupTracker.future().onComplete(ctx.succeedingThenComplete());
    adapter.start(startupTracker);
    assertThat(ctx.awaitCompletion(2, TimeUnit.SECONDS)).isTrue();
    // to which a device is connected
    final Device authenticatedDevice = new Device(TEST_TENANT_ID, TEST_DEVICE);
    final Record record = new RecordImpl();
    record.set(AmqpAdapterConstants.KEY_CLIENT_DEVICE, Device.class, authenticatedDevice);
    final ProtonConnection deviceConnection = mock(ProtonConnection.class);
    when(deviceConnection.attachments()).thenReturn(record);
    final ArgumentCaptor<Handler<ProtonConnection>> connectHandler = VertxMockSupport.argumentCaptorHandler();
    verify(server).connectHandler(connectHandler.capture());
    connectHandler.getValue().handle(deviceConnection);
    // that wants to receive commands
    final CommandConsumer commandConsumer = mock(CommandConsumer.class);
    when(commandConsumer.close(any())).thenReturn(Future.succeededFuture());
    when(commandConsumerFactory.createCommandConsumer(eq(TEST_TENANT_ID), eq(TEST_DEVICE), VertxMockSupport.anyHandler(), any(), any())).thenReturn(Future.succeededFuture(commandConsumer));
    final String sourceAddress = getCommandEndpoint();
    final ProtonSender sender = getSender(sourceAddress);
    adapter.handleRemoteSenderOpenForCommands(deviceConnection, sender);
    // WHEN the connection to the device is lost
    connectionLossTrigger.handle(deviceConnection);
    // THEN the adapter closes the command consumer
    verify(commandConsumer).close(any());
    // and sends an empty event with TTD = 0 downstream
    assertEmptyNotificationHasBeenSentDownstream(TEST_TENANT_ID, TEST_DEVICE, 0);
}
Also used : ProtonConnection(io.vertx.proton.ProtonConnection) ProtonSender(io.vertx.proton.ProtonSender) Device(org.eclipse.hono.auth.Device) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) Handler(io.vertx.core.Handler) Record(org.apache.qpid.proton.engine.Record) RecordImpl(org.apache.qpid.proton.engine.impl.RecordImpl) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString)

Aggregations

Device (org.eclipse.hono.auth.Device)115 HttpURLConnection (java.net.HttpURLConnection)74 Test (org.junit.jupiter.api.Test)72 Future (io.vertx.core.Future)69 ClientErrorException (org.eclipse.hono.client.ClientErrorException)67 Buffer (io.vertx.core.buffer.Buffer)66 Handler (io.vertx.core.Handler)63 TenantObject (org.eclipse.hono.util.TenantObject)63 Promise (io.vertx.core.Promise)59 Constants (org.eclipse.hono.util.Constants)58 Span (io.opentracing.Span)55 RegistrationAssertion (org.eclipse.hono.util.RegistrationAssertion)55 SpanContext (io.opentracing.SpanContext)53 VertxTestContext (io.vertx.junit5.VertxTestContext)52 VertxExtension (io.vertx.junit5.VertxExtension)51 MessageHelper (org.eclipse.hono.util.MessageHelper)51 ExtendWith (org.junit.jupiter.api.extension.ExtendWith)51 Mockito.when (org.mockito.Mockito.when)51 Truth.assertThat (com.google.common.truth.Truth.assertThat)50 ResourceIdentifier (org.eclipse.hono.util.ResourceIdentifier)47