use of org.eclipse.hono.client.command.CommandResponseSender in project hono by eclipse.
the class CommandResponseResourceTest method testUploadCommandResponseFailsForRejectedOutcome.
/**
* Verifies that the adapter fails the upload of a command response with a 4.00
* response code if it is rejected by the downstream peer.
*
* @param ctx The vert.x test context.
*/
@Test
public void testUploadCommandResponseFailsForRejectedOutcome(final VertxTestContext ctx) {
// GIVEN an adapter with a downstream application attached
givenAnAdapter(properties);
final var resource = givenAResource(adapter);
final Promise<Void> outcome = Promise.promise();
final CommandResponseSender sender = givenACommandResponseSenderForAnyTenant(outcome);
// WHEN a device publishes an command response
final String reqId = Commands.encodeRequestIdParameters("correlation", "replyToId", "device", MessagingType.amqp);
final Buffer payload = Buffer.buffer("some payload");
final OptionSet options = new OptionSet();
options.addUriPath(CommandConstants.COMMAND_RESPONSE_ENDPOINT).addUriPath(reqId);
options.addUriQuery(String.format("%s=%d", Constants.HEADER_COMMAND_RESPONSE_STATUS, 200));
options.setContentFormat(MediaTypeRegistry.TEXT_PLAIN);
final CoapExchange coapExchange = newCoapExchange(payload, Type.CON, options);
final Device authenticatedDevice = new Device("tenant", "device");
final CoapContext context = CoapContext.fromRequest(coapExchange, authenticatedDevice, authenticatedDevice, "device", span);
final Future<Void> result = resource.uploadCommandResponseMessage(context);
outcome.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "malformed message"));
result.onComplete(ctx.failing(t -> {
ctx.verify(() -> {
// THEN the command response is being forwarded downstream
verify(sender).sendCommandResponse(any(TenantObject.class), any(RegistrationAssertion.class), any(CommandResponse.class), any(SpanContext.class));
// and the device gets a 4.00 response
assertThat(t).isInstanceOf(ClientErrorException.class);
assertThat(((ClientErrorException) t).getErrorCode()).isEqualTo(HttpURLConnection.HTTP_BAD_REQUEST);
// and the response has not been reported as forwarded
verify(metrics, never()).reportCommand(eq(Direction.RESPONSE), eq("tenant"), any(), eq(ProcessingOutcome.FORWARDED), anyInt(), any());
});
ctx.completeNow();
}));
}
use of org.eclipse.hono.client.command.CommandResponseSender in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method testMessageLimitExceededForACommandResponseMessage.
/**
* Verifies that a command response message is rejected due to the limit exceeded.
*
* @param ctx The vert.x test context.
*/
@Test
public void testMessageLimitExceededForACommandResponseMessage(final VertxTestContext ctx) {
// GIVEN an adapter
givenAnAdapter(properties);
final CommandResponseSender sender = givenACommandResponseSenderForAnyTenant();
// WHEN the message limit exceeds
when(resourceLimitChecks.isMessageLimitReached(any(TenantObject.class), anyLong(), any(SpanContext.class))).thenReturn(Future.succeededFuture(Boolean.TRUE));
// WHEN a device of "tenant" publishes a command response message
final MqttPublishMessage msg = mock(MqttPublishMessage.class);
when(msg.topicName()).thenReturn("e/tenant/device");
when(msg.qosLevel()).thenReturn(MqttQoS.AT_MOST_ONCE);
when(msg.payload()).thenReturn(Buffer.buffer("test"));
adapter.uploadMessage(newMqttContext(msg, mockEndpoint(), span), ResourceIdentifier.fromString(String.format("%s/tenant/device/res/%s/200", getCommandEndpoint(), Commands.encodeRequestIdParameters("cmd123", "to", "deviceId", MessagingType.amqp))), msg).onComplete(ctx.failing(t -> {
ctx.verify(() -> {
// THEN the request fails with a 429 error
assertThat(((ClientErrorException) t).getErrorCode()).isEqualTo(HttpUtils.HTTP_TOO_MANY_REQUESTS);
// AND the response is not being forwarded
verify(sender, never()).sendCommandResponse(any(TenantObject.class), any(RegistrationAssertion.class), any(CommandResponse.class), (SpanContext) any());
// AND has reported the message as unprocessable
verify(metrics).reportCommand(eq(MetricsTags.Direction.RESPONSE), eq("tenant"), any(), eq(MetricsTags.ProcessingOutcome.UNPROCESSABLE), anyInt(), any());
});
ctx.completeNow();
}));
}
use of org.eclipse.hono.client.command.CommandResponseSender in project hono by eclipse.
the class ProtocolAdapterMockSupport method createCommandResponseSender.
private CommandResponseSender createCommandResponseSender() {
final CommandResponseSender client = mock(CommandResponseSender.class);
when(client.getMessagingType()).thenReturn(MessagingType.amqp);
when(client.start()).thenReturn(Future.succeededFuture());
when(client.stop()).thenReturn(Future.succeededFuture());
return client;
}
use of org.eclipse.hono.client.command.CommandResponseSender in project hono by eclipse.
the class VertxBasedAmqpProtocolAdapterTest method testUploadCommandResponseWithoutPayloadSucceeds.
/**
* Verify that the AMQP adapter forwards command responses that do not contain a payload downstream.
*
* @param ctx The vert.x test context.
*/
@Test
public void testUploadCommandResponseWithoutPayloadSucceeds(final VertxTestContext ctx) {
// GIVEN an AMQP adapter
givenAnAdapter(properties);
final CommandResponseSender responseSender = givenACommandResponseSenderForAnyTenant();
when(responseSender.sendCommandResponse(any(TenantObject.class), any(RegistrationAssertion.class), any(CommandResponse.class), (SpanContext) any())).thenReturn(Future.succeededFuture());
// which is enabled for the test tenant
final TenantObject tenantObject = givenAConfiguredTenant(TEST_TENANT_ID, true);
// WHEN an unauthenticated device publishes a command response
final String replyToAddress = String.format("%s/%s/%s", getCommandResponseEndpoint(), TEST_TENANT_ID, Commands.getDeviceFacingReplyToId("test-reply-id", TEST_DEVICE, MessagingType.amqp));
final Map<String, Object> propertyMap = new HashMap<>();
propertyMap.put(MessageHelper.APP_PROPERTY_STATUS, 200);
final ApplicationProperties props = new ApplicationProperties(propertyMap);
final Message message = getFakeMessage(replyToAddress, null);
message.setCorrelationId("correlation-id");
message.setApplicationProperties(props);
final ProtonDelivery delivery = mock(ProtonDelivery.class);
adapter.onMessageReceived(AmqpContext.fromMessage(delivery, message, span, null)).onComplete(ctx.succeeding(ok -> {
ctx.verify(() -> {
// THEN the adapter forwards the command response message downstream
verify(responseSender).sendCommandResponse(eq(tenantObject), any(RegistrationAssertion.class), any(CommandResponse.class), (SpanContext) any());
// and reports the forwarded message
verify(metrics).reportCommand(eq(Direction.RESPONSE), eq(TEST_TENANT_ID), eq(tenantObject), eq(ProcessingOutcome.FORWARDED), eq(0), any());
});
ctx.completeNow();
}));
}
use of org.eclipse.hono.client.command.CommandResponseSender in project hono by eclipse.
the class AbstractProtocolAdapterBaseTest method testGetCommandResponseSenderConfiguredOnTenant.
/**
* Verifies that when the messaging system to be used, as configured for the command response, is not available,
* then the messaging system type configuration from the tenant is used.
*/
@Test
public void testGetCommandResponseSenderConfiguredOnTenant() {
final var commandResponseSenderProvider = new MessagingClientProvider<CommandResponseSender>().setClient(amqpCommandResponseSender);
messagingClientProviders = new MessagingClientProviders(new MessagingClientProvider<TelemetrySender>().setClient(amqpTelemetrySender), new MessagingClientProvider<EventSender>().setClient(amqpEventSender), commandResponseSenderProvider);
properties = new ProtocolAdapterProperties();
adapter = newProtocolAdapter(properties, ADAPTER_NAME);
setCollaborators(adapter);
final CommandResponse response = CommandResponse.fromRequestId(Commands.encodeRequestIdParameters("", "replyTo", "4711", MessagingType.kafka), Constants.DEFAULT_TENANT, "4711", null, null, HttpURLConnection.HTTP_OK);
final TenantObject tenant = new TenantObject("tenant", true);
final var device = new RegistrationAssertion("4711");
tenant.setProperty(TenantConstants.FIELD_EXT, Map.of(TenantConstants.FIELD_EXT_MESSAGING_TYPE, MessagingType.amqp.name()));
adapter.sendCommandResponse(tenant, device, response, null);
verify(amqpCommandResponseSender).sendCommandResponse(eq(tenant), eq(device), eq(response), any());
}
Aggregations