use of io.vertx.junit5.Timeout in project hono by eclipse.
the class CommandAndControlMqttIT method testSendCommandViaAmqpFailsForMalformedMessage.
/**
* Verifies that the adapter rejects malformed command messages sent by applications.
* <p>
* This test is applicable only if the messaging network type is AMQP.
*
* @param endpointConfig The endpoints to use for sending/receiving commands.
* @param ctx The vert.x test context.
* @throws InterruptedException if not all commands and responses are exchanged in time.
*/
@ParameterizedTest(name = IntegrationTestSupport.PARAMETERIZED_TEST_NAME_PATTERN)
@MethodSource("allCombinations")
@Timeout(timeUnit = TimeUnit.SECONDS, value = 20)
@AssumeMessagingSystem(type = MessagingType.amqp)
public void testSendCommandViaAmqpFailsForMalformedMessage(final MqttCommandEndpointConfiguration endpointConfig, final VertxTestContext ctx) throws InterruptedException {
final String commandTargetDeviceId = endpointConfig.isSubscribeAsGateway() ? helper.setupGatewayDeviceBlocking(tenantId, deviceId, 5) : deviceId;
final AtomicReference<GenericSenderLink> amqpCmdSenderRef = new AtomicReference<>();
final String linkTargetAddress = endpointConfig.getSenderLinkTargetAddress(tenantId);
final VertxTestContext setup = new VertxTestContext();
final Checkpoint ready = setup.checkpoint(2);
createConsumer(tenantId, msg -> {
// expect empty notification with TTD -1
setup.verify(() -> assertThat(msg.getContentType()).isEqualTo(EventConstants.CONTENT_TYPE_EMPTY_NOTIFICATION));
final TimeUntilDisconnectNotification notification = msg.getTimeUntilDisconnectNotification().orElse(null);
LOGGER.info("received notification [{}]", notification);
if (notification.getTtd() == -1) {
ready.flag();
}
}).compose(consumer -> helper.registry.addDeviceToTenant(tenantId, deviceId, password)).compose(ok -> connectToAdapter(IntegrationTestSupport.getUsername(deviceId, tenantId), password)).compose(conAck -> subscribeToCommands(commandTargetDeviceId, msg -> {
// all commands should get rejected because they fail to pass the validity check
ctx.failNow(new IllegalStateException("should not have received command"));
}, endpointConfig, MqttQoS.AT_MOST_ONCE)).compose(ok -> helper.createGenericAmqpMessageSender(endpointConfig.getNorthboundEndpoint(), tenantId)).onComplete(setup.succeeding(genericSender -> {
LOGGER.debug("created generic sender for sending commands [target address: {}]", linkTargetAddress);
amqpCmdSenderRef.set(genericSender);
ready.flag();
}));
assertWithMessage("setup of adapter finished within %s seconds", IntegrationTestSupport.getTestSetupTimeout()).that(setup.awaitCompletion(IntegrationTestSupport.getTestSetupTimeout(), TimeUnit.SECONDS)).isTrue();
if (setup.failed()) {
ctx.failNow(setup.causeOfFailure());
return;
}
final Checkpoint failedAttempts = ctx.checkpoint(2);
final String messageAddress = endpointConfig.getCommandMessageAddress(tenantId, commandTargetDeviceId);
LOGGER.debug("sending command message lacking subject");
final Message messageWithoutSubject = ProtonHelper.message("input data");
messageWithoutSubject.setAddress(messageAddress);
messageWithoutSubject.setMessageId("message-id");
messageWithoutSubject.setReplyTo("reply/to/address");
amqpCmdSenderRef.get().sendAndWaitForOutcome(messageWithoutSubject, NoopSpan.INSTANCE).onComplete(ctx.failing(t -> {
ctx.verify(() -> assertThat(t).isInstanceOf(ClientErrorException.class));
failedAttempts.flag();
}));
LOGGER.debug("sending command message lacking message ID and correlation ID");
final Message messageWithoutId = ProtonHelper.message("input data");
messageWithoutId.setAddress(messageAddress);
messageWithoutId.setSubject("setValue");
messageWithoutId.setReplyTo("reply/to/address");
amqpCmdSenderRef.get().sendAndWaitForOutcome(messageWithoutId, NoopSpan.INSTANCE).onComplete(ctx.failing(t -> {
ctx.verify(() -> assertThat(t).isInstanceOf(ClientErrorException.class));
failedAttempts.flag();
}));
}
use of io.vertx.junit5.Timeout in project hono by eclipse.
the class HttpTestBase method testUploadMessageFailsForDisabledGateway.
/**
* Verifies that the HTTP adapter rejects messages from a disabled gateway for an enabled device with a 403.
*
* @param ctx The test context
*/
@Test
@Timeout(timeUnit = TimeUnit.SECONDS, value = 20)
public void testUploadMessageFailsForDisabledGateway(final VertxTestContext ctx) {
// GIVEN a device that is connected via a disabled gateway
final Tenant tenant = new Tenant();
final Device gateway = new Device().setEnabled(Boolean.FALSE);
final String gatewayId = helper.getRandomDeviceId(tenantId);
final Device device = new Device().setVia(Collections.singletonList(gatewayId));
helper.registry.addDeviceForTenant(tenantId, tenant, gatewayId, gateway, PWD).compose(ok -> helper.registry.registerDevice(tenantId, deviceId, device)).compose(ok -> {
// WHEN the gateway tries to upload a message for the device
final MultiMap requestHeaders = MultiMap.caseInsensitiveMultiMap().add(HttpHeaders.CONTENT_TYPE, "text/plain").add(HttpHeaders.AUTHORIZATION, getBasicAuth(tenantId, gatewayId, PWD));
return httpClient.update(String.format("%s/%s/%s", getEndpointUri(), tenantId, deviceId), Buffer.buffer("hello"), requestHeaders, ResponsePredicate.status(HttpURLConnection.HTTP_FORBIDDEN));
}).onComplete(ctx.succeedingThenComplete());
}
use of io.vertx.junit5.Timeout in project hono by eclipse.
the class HttpTestBase method testUploadMessageFailsForDisabledDevice.
/**
* Verifies that the HTTP adapter rejects messages from a disabled device with a 404.
*
* @param ctx The test context
*/
@Test
@Timeout(timeUnit = TimeUnit.SECONDS, value = 20)
public void testUploadMessageFailsForDisabledDevice(final VertxTestContext ctx) {
// GIVEN a disabled device
final Tenant tenant = new Tenant();
final Device device = new Device().setEnabled(Boolean.FALSE);
helper.registry.addDeviceForTenant(tenantId, tenant, deviceId, device, PWD).compose(ok -> {
// WHEN the device tries to upload a message
final MultiMap requestHeaders = MultiMap.caseInsensitiveMultiMap().add(HttpHeaders.CONTENT_TYPE, "text/plain").add(HttpHeaders.AUTHORIZATION, authorization);
return httpClient.create(getEndpointUri(), Buffer.buffer("hello"), requestHeaders, ResponsePredicate.status(HttpURLConnection.HTTP_NOT_FOUND));
}).onComplete(ctx.succeedingThenComplete());
}
use of io.vertx.junit5.Timeout in project hono by eclipse.
the class HttpTestBase method testUploadFailsForWrongCredentials.
/**
* Verifies that the adapter fails to authenticate a device that is providing
* wrong credentials.
*
* @param ctx The vert.x test context.
* @throws InterruptedException if the test fails.
*/
@Test
@Timeout(timeUnit = TimeUnit.SECONDS, value = 20)
public void testUploadFailsForWrongCredentials(final VertxTestContext ctx) throws InterruptedException {
final VertxTestContext setup = new VertxTestContext();
final Tenant tenant = new Tenant();
final MultiMap requestHeaders = MultiMap.caseInsensitiveMultiMap().add(HttpHeaders.CONTENT_TYPE, "text/plain").add(HttpHeaders.AUTHORIZATION, getBasicAuth(tenantId, deviceId, "wrong password")).add(HttpHeaders.ORIGIN, ORIGIN_URI);
// GIVEN a device
helper.registry.addDeviceForTenant(tenantId, tenant, deviceId, PWD).onComplete(setup.succeedingThenComplete());
assertThat(setup.awaitCompletion(5, TimeUnit.SECONDS)).isTrue();
if (setup.failed()) {
ctx.failNow(setup.causeOfFailure());
return;
}
// WHEN a device tries to upload data and authenticate using wrong credentials
httpClient.create(getEndpointUri(), Buffer.buffer("hello"), requestHeaders, ResponsePredicate.status(HttpURLConnection.HTTP_UNAUTHORIZED)).onComplete(ctx.succeedingThenComplete());
}
use of io.vertx.junit5.Timeout in project hono by eclipse.
the class TelemetryHttpIT method testUploadQos1MessageFailsIfDeliveryStateNotUpdated.
/**
* Verifies that the upload of a QoS 1 telemetry message fails with a 503 status code
* when the consumer doesn't update the message delivery state and the
* <em>sendMessageTimeout</em> has elapsed.
*
* @param vertx The vert.x instance.
* @param ctx The test context
* @throws InterruptedException if test is interrupted while running.
*/
@Test
@AssumeMessagingSystem(type = MessagingType.amqp)
public void testUploadQos1MessageFailsIfDeliveryStateNotUpdated(final Vertx vertx, final VertxTestContext ctx) throws InterruptedException {
final AmqpApplicationClient amqpApplicationClient = (AmqpApplicationClient) helper.applicationClient;
// GIVEN a device and a north bound message consumer that doesn't update the message delivery state
final Tenant tenant = new Tenant();
final Checkpoint messageReceived = ctx.checkpoint();
final Checkpoint deliveryStateCheckDone = ctx.checkpoint();
final Checkpoint httpResponseReceived = ctx.checkpoint();
final VertxTestContext setup = new VertxTestContext();
final AtomicReference<ProtonDelivery> deliveryRef = new AtomicReference<>();
helper.registry.addDeviceForTenant(tenantId, tenant, deviceId, PWD).compose(ok -> amqpApplicationClient.createTelemetryConsumer(tenantId, msg -> {
final Promise<Void> result = Promise.promise();
final var delivery = msg.getMessageContext().getDelivery();
deliveryRef.set(delivery);
logger.debug("received message: {}", msg.getMessageContext().getRawMessage());
ctx.verify(() -> {
assertThat(delivery.remotelySettled()).isFalse();
assertThat(delivery.getRemoteState()).isNull();
});
messageReceived.flag();
// don't update the delivery state here
return result.future();
}, remoteClose -> {
})).onComplete(setup.succeedingThenComplete());
assertThat(setup.awaitCompletion(IntegrationTestSupport.getTestSetupTimeout(), TimeUnit.SECONDS)).isTrue();
if (setup.failed()) {
ctx.failNow(setup.causeOfFailure());
return;
}
// WHEN the device tries to upload a telemetry message
final MultiMap requestHeaders = MultiMap.caseInsensitiveMultiMap().add(HttpHeaders.CONTENT_TYPE, "binary/octet-stream").add(HttpHeaders.AUTHORIZATION, authorization).add(HttpHeaders.ORIGIN, ORIGIN_URI).add(Constants.HEADER_QOS_LEVEL, "1");
final Future<HttpResponse<Buffer>> httpResponseFuture = httpClient.create(getEndpointUri(), Buffer.buffer("hello"), requestHeaders, // THEN the message gets rejected by the HTTP adapter with a 503
ResponsePredicate.status(HttpURLConnection.HTTP_UNAVAILABLE));
httpResponseFuture.onComplete(ctx.succeeding(response -> {
ctx.verify(() -> {
final var body = response.bodyAsJsonObject();
assertThat(body.getString(RequestResponseApiConstants.FIELD_ERROR)).isEqualTo(ServiceInvocationException.getLocalizedMessage(SendMessageTimeoutException.CLIENT_FACING_MESSAGE_KEY));
});
httpResponseReceived.flag();
// verify that the telemetry message delivery is remotely settled via the timeout handling in the adapter
vertx.setTimer(50, tid -> {
ctx.verify(() -> {
final ProtonDelivery delivery = deliveryRef.get();
assertThat(delivery).isNotNull();
assertThat(delivery.remotelySettled()).isTrue();
assertThat(delivery.getRemoteState()).isNotNull();
assertThat(delivery.getRemoteState().getType()).isEqualTo(DeliveryState.DeliveryStateType.Released);
});
deliveryStateCheckDone.flag();
});
}));
}
Aggregations