use of org.eclipse.hono.commandrouter.CommandTargetMapper in project hono by eclipse.
the class KafkaBasedMappingAndDelegatingCommandHandlerTest method testIncomingCommandOrderIsPreservedWhenDelegating.
/**
* Verifies the behaviour of the
* {@link KafkaBasedMappingAndDelegatingCommandHandler#mapAndDelegateIncomingCommandMessage(KafkaConsumerRecord)}
* method in a scenario where the mapping operation for one command completes earlier than for a previously received
* command. The order in which commands are then delegated to the target adapter instance has to be the same
* as the order in which commands were received.
*
* @param ctx The vert.x test context
*/
@Test
public void testIncomingCommandOrderIsPreservedWhenDelegating(final VertxTestContext ctx) {
final String deviceId1 = "device1";
final String deviceId2 = "device2";
final String deviceId3 = "device3";
final String deviceId4 = "device4";
// GIVEN valid command records
final KafkaConsumerRecord<String, Buffer> commandRecord1 = getCommandRecord(tenantId, deviceId1, "subject1", 0, 1);
final KafkaConsumerRecord<String, Buffer> commandRecord2 = getCommandRecord(tenantId, deviceId2, "subject2", 0, 2);
final KafkaConsumerRecord<String, Buffer> commandRecord3 = getCommandRecord(tenantId, deviceId3, "subject3", 0, 3);
final KafkaConsumerRecord<String, Buffer> commandRecord4 = getCommandRecord(tenantId, deviceId4, "subject4", 0, 4);
// WHEN getting the target adapter instances for the commands results in different delays for each command
// so that the invocations are completed with the order: commandRecord3, commandRecord2, commandRecord1, commandRecord4
final Promise<JsonObject> resultForCommand1 = Promise.promise();
when(commandTargetMapper.getTargetGatewayAndAdapterInstance(eq(tenantId), eq(deviceId1), any())).thenReturn(resultForCommand1.future());
final Promise<JsonObject> resultForCommand2 = Promise.promise();
when(commandTargetMapper.getTargetGatewayAndAdapterInstance(eq(tenantId), eq(deviceId2), any())).thenReturn(resultForCommand2.future());
final Promise<JsonObject> resultForCommand3 = Promise.promise();
when(commandTargetMapper.getTargetGatewayAndAdapterInstance(eq(tenantId), eq(deviceId3), any())).thenReturn(resultForCommand3.future());
doAnswer(invocation -> {
resultForCommand3.complete(createTargetAdapterInstanceJson(deviceId3, adapterInstanceId));
resultForCommand2.complete(createTargetAdapterInstanceJson(deviceId2, adapterInstanceId));
resultForCommand1.complete(createTargetAdapterInstanceJson(deviceId1, adapterInstanceId));
return Future.succeededFuture(createTargetAdapterInstanceJson(deviceId4, adapterInstanceId));
}).when(commandTargetMapper).getTargetGatewayAndAdapterInstance(eq(tenantId), eq(deviceId4), any());
// WHEN mapping and delegating the commands
final Future<Void> cmd1Future = cmdHandler.mapAndDelegateIncomingCommandMessage(commandRecord1);
final Future<Void> cmd2Future = cmdHandler.mapAndDelegateIncomingCommandMessage(commandRecord2);
final Future<Void> cmd3Future = cmdHandler.mapAndDelegateIncomingCommandMessage(commandRecord3);
final Future<Void> cmd4Future = cmdHandler.mapAndDelegateIncomingCommandMessage(commandRecord4);
// THEN the messages are delegated in the original order
CompositeFuture.all(cmd1Future, cmd2Future, cmd3Future, cmd4Future).onComplete(ctx.succeeding(r -> {
ctx.verify(() -> {
final ArgumentCaptor<CommandContext> commandContextCaptor = ArgumentCaptor.forClass(CommandContext.class);
verify(internalCommandSender, times(4)).sendCommand(commandContextCaptor.capture(), anyString());
final List<CommandContext> capturedCommandContexts = commandContextCaptor.getAllValues();
assertThat(capturedCommandContexts.get(0).getCommand().getDeviceId()).isEqualTo(deviceId1);
assertThat(capturedCommandContexts.get(1).getCommand().getDeviceId()).isEqualTo(deviceId2);
assertThat(capturedCommandContexts.get(2).getCommand().getDeviceId()).isEqualTo(deviceId3);
assertThat(capturedCommandContexts.get(3).getCommand().getDeviceId()).isEqualTo(deviceId4);
});
ctx.completeNow();
}));
}
Aggregations