use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method givenAnEventSenderForOutcome.
private void givenAnEventSenderForOutcome(final Future<ProtonDelivery> outcome) {
final MessageSender sender = mock(MessageSender.class);
when(sender.getEndpoint()).thenReturn(EventConstants.EVENT_ENDPOINT);
when(sender.send(any(Message.class))).thenReturn(outcome);
when(messagingClient.getOrCreateEventSender(anyString())).thenReturn(Future.succeededFuture(sender));
}
use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method testUploadTelemetryMessageFailsForUnknownDevice.
/**
* Verifies that the adapter does not forward a message published by a device
* if the device's registration status cannot be asserted.
*
* @param ctx The vert.x test context.
*/
@Test
public void testUploadTelemetryMessageFailsForUnknownDevice(final TestContext ctx) {
// GIVEN an adapter
final MqttServer server = getMqttServer(false);
final AbstractVertxBasedMqttProtocolAdapter<ProtocolAdapterProperties> adapter = getAdapter(server);
givenATelemetrySenderForOutcome(Future.succeededFuture(mock(ProtonDelivery.class)));
// WHEN an unknown device publishes a telemetry message
when(regClient.assertRegistration(eq("unknown"), any())).thenReturn(Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND)));
final MessageSender sender = mock(MessageSender.class);
when(messagingClient.getOrCreateTelemetrySender(anyString())).thenReturn(Future.succeededFuture(sender));
adapter.uploadTelemetryMessage(new MqttContext(mock(MqttPublishMessage.class), mock(MqttEndpoint.class)), "my-tenant", "unknown", Buffer.buffer("test")).setHandler(ctx.asyncAssertFailure(t -> {
// THEN the message has not been sent downstream
verify(sender, never()).send(any(Message.class));
// because the device's registration status could not be asserted
ctx.assertEquals(HttpURLConnection.HTTP_NOT_FOUND, ((ClientErrorException) t).getErrorCode());
}));
}
use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class HonoClientImpl method getOrCreateSender.
Future<MessageSender> getOrCreateSender(final String key, final Supplier<Future<MessageSender>> newSenderSupplier) {
final Future<MessageSender> result = Future.future();
context.runOnContext(get -> {
final MessageSender sender = activeSenders.get(key);
if (sender != null && sender.isOpen()) {
LOG.debug("reusing existing message sender [target: {}, credit: {}]", key, sender.getCredit());
result.complete(sender);
} else if (!creationLocks.computeIfAbsent(key, k -> Boolean.FALSE)) {
// register a handler to be notified if the underlying connection to the server fails
// so that we can fail the result handler passed in
final Handler<Void> connectionFailureHandler = connectionLost -> {
// remove lock so that next attempt to open a sender doesn't fail
creationLocks.remove(key);
result.tryFail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no connection to service"));
};
creationRequests.add(connectionFailureHandler);
creationLocks.put(key, Boolean.TRUE);
LOG.debug("creating new message sender for {}", key);
newSenderSupplier.get().setHandler(creationAttempt -> {
creationLocks.remove(key);
creationRequests.remove(connectionFailureHandler);
if (creationAttempt.succeeded()) {
MessageSender newSender = creationAttempt.result();
LOG.debug("successfully created new message sender for {}", key);
activeSenders.put(key, newSender);
result.tryComplete(newSender);
} else {
LOG.debug("failed to create new message sender for {}", key, creationAttempt.cause());
activeSenders.remove(key);
result.tryFail(creationAttempt.cause());
}
});
} else {
LOG.debug("already trying to create a message sender for {}", key);
result.fail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no connection to service"));
}
});
return result;
}
use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class EventSenderImplTest method testSendMessageWaitsForAcceptedOutcome.
/**
* Verifies that the sender waits for the peer to settle and
* accept a message before succeeding the returned future.
*
* @param ctx The vert.x test context.
*/
@SuppressWarnings({ "unchecked" })
@Test
public void testSendMessageWaitsForAcceptedOutcome(final TestContext ctx) {
// GIVEN a sender that has credit
when(sender.sendQueueFull()).thenReturn(Boolean.FALSE);
MessageSender messageSender = new EventSenderImpl(config, sender, "tenant", "telemetry/tenant", context);
final AtomicReference<Handler<ProtonDelivery>> handlerRef = new AtomicReference<>();
doAnswer(invocation -> {
handlerRef.set(invocation.getArgument(1));
return mock(ProtonDelivery.class);
}).when(sender).send(any(Message.class), any(Handler.class));
// WHEN trying to send a message
final Future<ProtonDelivery> result = messageSender.send("device", "some payload", "application/text", "token");
// THEN the message has been sent
// and the result is not completed yet
verify(sender).send(any(Message.class), eq(handlerRef.get()));
assertFalse(result.isComplete());
// until it gets accepted by the peer
ProtonDelivery accepted = mock(ProtonDelivery.class);
when(accepted.remotelySettled()).thenReturn(Boolean.TRUE);
when(accepted.getRemoteState()).thenReturn(new Accepted());
handlerRef.get().handle(accepted);
assertTrue(result.succeeded());
}
use of org.eclipse.hono.client.MessageSender in project hono by eclipse.
the class EventSenderImplTest method testSendMessageFailsForRejectedOutcome.
/**
* Verifies that the sender fails if the peer does not accept a message.
*
* @param ctx The vert.x test context.
*/
@SuppressWarnings({ "unchecked" })
@Test
public void testSendMessageFailsForRejectedOutcome(final TestContext ctx) {
// GIVEN a sender that has credit
when(sender.sendQueueFull()).thenReturn(Boolean.FALSE);
MessageSender messageSender = new EventSenderImpl(config, sender, "tenant", "telemetry/tenant", context);
final AtomicReference<Handler<ProtonDelivery>> handlerRef = new AtomicReference<>();
doAnswer(invocation -> {
handlerRef.set(invocation.getArgument(1));
return mock(ProtonDelivery.class);
}).when(sender).send(any(Message.class), any(Handler.class));
// WHEN trying to send a message
final Future<ProtonDelivery> result = messageSender.send("device", "some payload", "application/text", "token");
// THEN the message has been sent
// and the result is not completed yet
verify(sender).send(any(Message.class), eq(handlerRef.get()));
assertFalse(result.isComplete());
// and the result fails once the peer rejects the message
ProtonDelivery rejected = mock(ProtonDelivery.class);
when(rejected.remotelySettled()).thenReturn(Boolean.TRUE);
when(rejected.getRemoteState()).thenReturn(new Rejected());
handlerRef.get().handle(rejected);
assertFalse(result.succeeded());
}
Aggregations