Search in sources :

Example 1 with MessageContext

use of org.eclipse.hono.application.client.MessageContext in project hono by eclipse.

the class HonoExampleApplicationBase method consumeData.

/**
 * Start the application client and set the message handling method to treat data that is received.
 */
protected void consumeData() {
    final CompletableFuture<ApplicationClient<? extends MessageContext>> startup = new CompletableFuture<>();
    if (client instanceof AmqpApplicationClient) {
        final AmqpApplicationClient ac = (AmqpApplicationClient) client;
        ac.addDisconnectListener(c -> LOG.info("lost connection to Hono, trying to reconnect ..."));
        ac.addReconnectListener(c -> LOG.info("reconnected to Hono"));
    }
    client.start().compose(v -> CompositeFuture.all(createEventConsumer(), createTelemetryConsumer())).onSuccess(ok -> startup.complete(client)).onFailure(startup::completeExceptionally);
    try {
        startup.join();
        LOG.info("Consumer ready for telemetry and event messages");
        System.in.read();
    } catch (final CompletionException e) {
        LOG.error("{} consumer failed to start [{}:{}]", USE_KAFKA ? "Kafka" : "AMQP", HonoExampleConstants.HONO_MESSAGING_HOST, port, e.getCause());
    } catch (final IOException e) {
    // nothing we can do
    }
    final CompletableFuture<ApplicationClient<? extends MessageContext>> shutDown = new CompletableFuture<>();
    @SuppressWarnings("rawtypes") final List<Future> closeFutures = new ArrayList<>();
    Optional.ofNullable(eventConsumer).map(MessageConsumer::close).ifPresent(closeFutures::add);
    Optional.ofNullable(telemetryConsumer).map(MessageConsumer::close).ifPresent(closeFutures::add);
    Optional.ofNullable(client).map(Lifecycle::stop).ifPresent(closeFutures::add);
    CompositeFuture.join(closeFutures).compose(ok -> vertx.close()).recover(t -> vertx.close()).onComplete(ar -> shutDown.complete(client));
    // wait for clients to be closed
    shutDown.join();
    LOG.info("Consumer has been shut down");
}
Also used : ApplicationClient(org.eclipse.hono.application.client.ApplicationClient) MessagingKafkaConsumerConfigProperties(org.eclipse.hono.client.kafka.consumer.MessagingKafkaConsumerConfigProperties) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) MessagingKafkaProducerConfigProperties(org.eclipse.hono.client.kafka.producer.MessagingKafkaProducerConfigProperties) Lifecycle(org.eclipse.hono.util.Lifecycle) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) Random(java.util.Random) CompletableFuture(java.util.concurrent.CompletableFuture) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) TimeUntilDisconnectNotification(org.eclipse.hono.util.TimeUntilDisconnectNotification) ArrayList(java.util.ArrayList) CompositeFuture(io.vertx.core.CompositeFuture) ProtonBasedApplicationClient(org.eclipse.hono.application.client.amqp.ProtonBasedApplicationClient) Map(java.util.Map) JsonObject(io.vertx.core.json.JsonObject) HonoConnection(org.eclipse.hono.client.HonoConnection) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) Logger(org.slf4j.Logger) MessageContext(org.eclipse.hono.application.client.MessageContext) KafkaApplicationClientImpl(org.eclipse.hono.application.client.kafka.impl.KafkaApplicationClientImpl) CachingKafkaProducerFactory(org.eclipse.hono.client.kafka.producer.CachingKafkaProducerFactory) Vertx(io.vertx.core.Vertx) IOException(java.io.IOException) CompletionException(java.util.concurrent.CompletionException) Future(io.vertx.core.Future) List(java.util.List) KafkaProducerFactory(org.eclipse.hono.client.kafka.producer.KafkaProducerFactory) Buffer(io.vertx.core.buffer.Buffer) AmqpApplicationClient(org.eclipse.hono.application.client.amqp.AmqpApplicationClient) Optional(java.util.Optional) MessageConsumer(org.eclipse.hono.application.client.MessageConsumer) CommonKafkaClientConfigProperties(org.eclipse.hono.client.kafka.CommonKafkaClientConfigProperties) Handler(io.vertx.core.Handler) ApplicationClient(org.eclipse.hono.application.client.ApplicationClient) ProtonBasedApplicationClient(org.eclipse.hono.application.client.amqp.ProtonBasedApplicationClient) AmqpApplicationClient(org.eclipse.hono.application.client.amqp.AmqpApplicationClient) ArrayList(java.util.ArrayList) IOException(java.io.IOException) AmqpApplicationClient(org.eclipse.hono.application.client.amqp.AmqpApplicationClient) CompletableFuture(java.util.concurrent.CompletableFuture) CompletionException(java.util.concurrent.CompletionException) CompletableFuture(java.util.concurrent.CompletableFuture) CompositeFuture(io.vertx.core.CompositeFuture) Future(io.vertx.core.Future) MessageContext(org.eclipse.hono.application.client.MessageContext)

Example 2 with MessageContext

use of org.eclipse.hono.application.client.MessageContext in project hono by eclipse.

the class HttpTestBase method testUploadMessages.

/**
 * Uploads messages to the HTTP endpoint.
 *
 * @param ctx The test context to run on.
 * @param tenantId The tenant that the device belongs to.
 * @param messageConsumer Consumer that is invoked when a message was received.
 * @param requestSender The test device that will publish the data.
 * @param numberOfMessages The number of messages that are uploaded.
 * @param expectedQos The expected QoS level, may be {@code null} leading to expecting the default for event or telemetry.
 * @throws InterruptedException if the test is interrupted before it has finished.
 */
protected void testUploadMessages(final VertxTestContext ctx, final String tenantId, final Function<DownstreamMessage<? extends MessageContext>, Future<Void>> messageConsumer, final Function<Integer, Future<HttpResponse<Buffer>>> requestSender, final int numberOfMessages, final QoS expectedQos) throws InterruptedException {
    final VertxTestContext messageSending = new VertxTestContext();
    final Checkpoint messageSent = messageSending.checkpoint(numberOfMessages);
    final Checkpoint messageReceived = messageSending.laxCheckpoint(numberOfMessages);
    final AtomicInteger receivedMessageCount = new AtomicInteger(0);
    final VertxTestContext setup = new VertxTestContext();
    createConsumer(tenantId, msg -> {
        logger.trace("received {}", msg);
        ctx.verify(() -> {
            DownstreamMessageAssertions.assertTelemetryMessageProperties(msg, tenantId);
            assertThat(msg.getQos()).isEqualTo(getExpectedQoS(expectedQos));
            assertAdditionalMessageProperties(msg);
        });
        Optional.ofNullable(messageConsumer).map(consumer -> consumer.apply(msg)).orElseGet(() -> Future.succeededFuture()).onComplete(attempt -> {
            if (attempt.succeeded()) {
                receivedMessageCount.incrementAndGet();
                messageReceived.flag();
            } else {
                logger.error("failed to process message from device", attempt.cause());
                messageSending.failNow(attempt.cause());
            }
        });
        if (receivedMessageCount.get() % 20 == 0) {
            logger.info("messages received: {}", receivedMessageCount.get());
        }
    }).onComplete(setup.succeedingThenComplete());
    assertThat(setup.awaitCompletion(5, TimeUnit.SECONDS)).isTrue();
    if (setup.failed()) {
        ctx.failNow(setup.causeOfFailure());
        return;
    }
    final long start = System.currentTimeMillis();
    int messageCount = 0;
    while (messageCount < numberOfMessages && !messageSending.failed()) {
        messageCount++;
        final int currentMessage = messageCount;
        final CountDownLatch sending = new CountDownLatch(1);
        requestSender.apply(currentMessage).compose(this::assertHttpResponse).onComplete(attempt -> {
            try {
                if (attempt.succeeded()) {
                    logger.debug("sent message {}", currentMessage);
                    messageSent.flag();
                } else {
                    logger.info("failed to send message {}: {}", currentMessage, attempt.cause().getMessage());
                    messageSending.failNow(attempt.cause());
                }
            } finally {
                sending.countDown();
            }
        });
        sending.await();
        if (currentMessage % 20 == 0) {
            logger.info("messages sent: " + currentMessage);
        }
    }
    final long timeToWait = Math.max(TEST_TIMEOUT_MILLIS - 50 - (System.currentTimeMillis() - testStartTimeMillis), 1);
    assertThat(messageSending.awaitCompletion(timeToWait, TimeUnit.MILLISECONDS)).isTrue();
    if (messageSending.failed()) {
        logger.error("test execution failed", messageSending.causeOfFailure());
        ctx.failNow(messageSending.causeOfFailure());
    } else {
        logger.info("successfully sent {} and received {} messages after {} milliseconds", messageCount, receivedMessageCount.get(), System.currentTimeMillis() - start);
        ctx.completeNow();
    }
}
Also used : HttpURLConnection(java.net.HttpURLConnection) KeyPair(java.security.KeyPair) BeforeEach(org.junit.jupiter.api.BeforeEach) Arrays(java.util.Arrays) ResponsePredicate(io.vertx.ext.web.client.predicate.ResponsePredicate) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) LoggerFactory(org.slf4j.LoggerFactory) MultiMap(io.vertx.core.MultiMap) Tenant(org.eclipse.hono.service.management.tenant.Tenant) Timeout(io.vertx.junit5.Timeout) GeneralSecurityException(java.security.GeneralSecurityException) IntegrationTestSupport(org.eclipse.hono.tests.IntegrationTestSupport) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) BeforeAll(org.junit.jupiter.api.BeforeAll) JsonObject(io.vertx.core.json.JsonObject) Tenants(org.eclipse.hono.tests.Tenants) MethodSource(org.junit.jupiter.params.provider.MethodSource) Device(org.eclipse.hono.service.management.device.Device) MessageContext(org.eclipse.hono.application.client.MessageContext) SubscriberRole(org.eclipse.hono.tests.CommandEndpointConfiguration.SubscriberRole) Truth.assertWithMessage(com.google.common.truth.Truth.assertWithMessage) MetricsTags(org.eclipse.hono.service.metric.MetricsTags) Set(java.util.Set) HttpHeaders(io.vertx.core.http.HttpHeaders) DownstreamMessageAssertions(org.eclipse.hono.tests.DownstreamMessageAssertions) UUID(java.util.UUID) Future(io.vertx.core.Future) StandardCharsets(java.nio.charset.StandardCharsets) TestInfo(org.junit.jupiter.api.TestInfo) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) Base64(java.util.Base64) Stream(java.util.stream.Stream) Buffer(io.vertx.core.buffer.Buffer) Optional(java.util.Optional) Checkpoint(io.vertx.junit5.Checkpoint) QoS(org.eclipse.hono.util.QoS) VertxTestContext(io.vertx.junit5.VertxTestContext) X500Principal(javax.security.auth.x500.X500Principal) HttpResponse(io.vertx.ext.web.client.HttpResponse) SelfSignedCertificate(io.vertx.core.net.SelfSignedCertificate) Function(java.util.function.Function) Constants(org.eclipse.hono.util.Constants) CompositeFuture(io.vertx.core.CompositeFuture) HttpClientOptions(io.vertx.core.http.HttpClientOptions) PemTrustOptions(io.vertx.core.net.PemTrustOptions) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) Logger(org.slf4j.Logger) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) Truth.assertThat(com.google.common.truth.Truth.assertThat) TimeUnit(java.util.concurrent.TimeUnit) Adapter(org.eclipse.hono.util.Adapter) AfterEach(org.junit.jupiter.api.AfterEach) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) CrudHttpClient(org.eclipse.hono.tests.CrudHttpClient) MessageConsumer(org.eclipse.hono.application.client.MessageConsumer) Handler(io.vertx.core.Handler) Collections(java.util.Collections) Checkpoint(io.vertx.junit5.Checkpoint) VertxTestContext(io.vertx.junit5.VertxTestContext) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) CountDownLatch(java.util.concurrent.CountDownLatch) Checkpoint(io.vertx.junit5.Checkpoint)

Example 3 with MessageContext

use of org.eclipse.hono.application.client.MessageContext in project hono by eclipse.

the class CoapTestBase method testUploadMessages.

/**
 * Uploads messages to the CoAP endpoint.
 *
 * @param ctx The test context to run on.
 * @param tenantId The tenant that the device belongs to.
 * @param warmUp A sender of messages used to warm up the adapter before running the test itself or {@code null} if
 *            no warm up should be performed.
 * @param messageConsumer Consumer that is invoked when a message was received.
 * @param requestSender The test device that will publish the data.
 * @param numberOfMessages The number of messages that are uploaded.
 * @param expectedQos The expected QoS level, may be {@code null} leading to expecting the default for event or telemetry.
 * @throws InterruptedException if the test is interrupted before it has finished.
 */
protected void testUploadMessages(final VertxTestContext ctx, final String tenantId, final Supplier<Future<Void>> warmUp, final Consumer<DownstreamMessage<? extends MessageContext>> messageConsumer, final Function<Integer, Future<OptionSet>> requestSender, final int numberOfMessages, final QoS expectedQos) throws InterruptedException {
    final CountDownLatch received = new CountDownLatch(numberOfMessages);
    final VertxTestContext setup = new VertxTestContext();
    createConsumer(tenantId, msg -> {
        ctx.verify(() -> {
            logger.trace("received {}", msg);
            DownstreamMessageAssertions.assertTelemetryMessageProperties(msg, tenantId);
            assertThat(msg.getQos()).isEqualTo(getExpectedQoS(expectedQos));
            assertAdditionalMessageProperties(msg);
            if (messageConsumer != null) {
                messageConsumer.accept(msg);
            }
        });
        received.countDown();
        if (received.getCount() % 20 == 0) {
            logger.info("messages received: {}", numberOfMessages - received.getCount());
        }
    }).compose(ok -> Optional.ofNullable(warmUp).map(w -> w.get()).orElseGet(() -> Future.succeededFuture())).onComplete(setup.succeedingThenComplete());
    ctx.verify(() -> assertThat(setup.awaitCompletion(5, TimeUnit.SECONDS)).isTrue());
    final long start = System.currentTimeMillis();
    final AtomicInteger messageCount = new AtomicInteger(0);
    while (messageCount.get() < numberOfMessages && !ctx.failed()) {
        final CountDownLatch sending = new CountDownLatch(1);
        requestSender.apply(messageCount.getAndIncrement()).compose(this::assertCoapResponse).onComplete(attempt -> {
            if (attempt.succeeded()) {
                logger.debug("sent message {}", messageCount.get());
            } else {
                logger.info("failed to send message {}: {}", messageCount.get(), attempt.cause().getMessage());
                ctx.failNow(attempt.cause());
            }
            sending.countDown();
        });
        if (messageCount.get() % 20 == 0) {
            logger.info("messages sent: {}", messageCount.get());
        }
        sending.await();
    }
    if (ctx.failed()) {
        return;
    }
    final long timeToWait = Math.max(TEST_TIMEOUT_MILLIS - 1000, Math.round(numberOfMessages * 20));
    if (received.await(timeToWait, TimeUnit.MILLISECONDS)) {
        logger.info("sent {} and received {} messages after {} milliseconds", messageCount, numberOfMessages - received.getCount(), System.currentTimeMillis() - start);
        ctx.completeNow();
    } else {
        logger.info("sent {} and received {} messages after {} milliseconds", messageCount, numberOfMessages - received.getCount(), System.currentTimeMillis() - start);
        ctx.failNow(new AssertionError("did not receive all messages sent"));
    }
}
Also used : HttpURLConnection(java.net.HttpURLConnection) X509Certificate(java.security.cert.X509Certificate) ResponseCode(org.eclipse.californium.core.coap.CoAP.ResponseCode) KeyPair(java.security.KeyPair) BeforeEach(org.junit.jupiter.api.BeforeEach) Arrays(java.util.Arrays) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) AdvancedPskStore(org.eclipse.californium.scandium.dtls.pskstore.AdvancedPskStore) URISyntaxException(java.net.URISyntaxException) LoggerFactory(org.slf4j.LoggerFactory) CertificateType(org.eclipse.californium.scandium.dtls.CertificateType) Tenant(org.eclipse.hono.service.management.tenant.Tenant) Timeout(io.vertx.junit5.Timeout) CoapResponse(org.eclipse.californium.core.CoapResponse) NetworkConfig(org.eclipse.californium.core.network.config.NetworkConfig) GeneralSecurityException(java.security.GeneralSecurityException) DTLSConnector(org.eclipse.californium.scandium.DTLSConnector) IntegrationTestSupport(org.eclipse.hono.tests.IntegrationTestSupport) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Utils(org.eclipse.californium.core.Utils) JsonObject(io.vertx.core.json.JsonObject) URI(java.net.URI) Tenants(org.eclipse.hono.tests.Tenants) MethodSource(org.junit.jupiter.params.provider.MethodSource) Device(org.eclipse.hono.service.management.device.Device) DtlsConnectorConfig(org.eclipse.californium.scandium.config.DtlsConnectorConfig) MessageContext(org.eclipse.hono.application.client.MessageContext) SubscriberRole(org.eclipse.hono.tests.CommandEndpointConfiguration.SubscriberRole) Truth.assertWithMessage(com.google.common.truth.Truth.assertWithMessage) DownstreamMessageAssertions(org.eclipse.hono.tests.DownstreamMessageAssertions) InetSocketAddress(java.net.InetSocketAddress) Future(io.vertx.core.Future) StandardCharsets(java.nio.charset.StandardCharsets) TestInfo(org.junit.jupiter.api.TestInfo) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Stream(java.util.stream.Stream) Request(org.eclipse.californium.core.coap.Request) Buffer(io.vertx.core.buffer.Buffer) Optional(java.util.Optional) QoS(org.eclipse.hono.util.QoS) VertxTestContext(io.vertx.junit5.VertxTestContext) CoapClient(org.eclipse.californium.core.CoapClient) X500Principal(javax.security.auth.x500.X500Principal) KeyLoader(org.eclipse.hono.config.KeyLoader) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) Function(java.util.function.Function) Supplier(java.util.function.Supplier) Constants(org.eclipse.hono.util.Constants) CoapEndpoint(org.eclipse.californium.core.network.CoapEndpoint) MediaTypeRegistry(org.eclipse.californium.core.coap.MediaTypeRegistry) StaticNewAdvancedCertificateVerifier(org.eclipse.californium.scandium.dtls.x509.StaticNewAdvancedCertificateVerifier) AsyncResult(io.vertx.core.AsyncResult) CommandConstants(org.eclipse.hono.util.CommandConstants) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) Type(org.eclipse.californium.core.coap.CoAP.Type) Logger(org.slf4j.Logger) AdvancedSinglePskStore(org.eclipse.californium.scandium.dtls.pskstore.AdvancedSinglePskStore) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) Truth.assertThat(com.google.common.truth.Truth.assertThat) Inet4Address(java.net.Inet4Address) UnknownHostException(java.net.UnknownHostException) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) Code(org.eclipse.californium.core.coap.CoAP.Code) Adapter(org.eclipse.hono.util.Adapter) AfterEach(org.junit.jupiter.api.AfterEach) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) CoapHandler(org.eclipse.californium.core.CoapHandler) MessageConsumer(org.eclipse.hono.application.client.MessageConsumer) OptionSet(org.eclipse.californium.core.coap.OptionSet) Handler(io.vertx.core.Handler) Collections(java.util.Collections) VertxTestContext(io.vertx.junit5.VertxTestContext) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 4 with MessageContext

use of org.eclipse.hono.application.client.MessageContext in project hono by eclipse.

the class MqttPublishTestBase method doTestUploadMessages.

/**
 * Uploads a number of messages and verifies that they are either received via the northbound consumer or that
 * corresponding error messages are published to the client on the error topic.
 *
 * @param ctx The test context.
 * @param tenantId The tenant identifier.
 * @param connection The MQTT connection future.
 * @param sender The message sender. The Future result is the correlation/message id of the sent message.
 * @param consumerSupplier The message consumer. The result may be succeeded with a {@code null} value in case
 *                         error message handling for a non-existing consumer shall get tested.
 * @param errorMsgHandler The handler to invoke with received error messages or {@code null} if no error messages
 *            are expected. The future result is the error message correlation id.
 * @param errorTopic The errorTopic to subscribe to. Will be ignored of errorMsgHandler is {@code null}.
 * @throws InterruptedException if the test fails.
 */
protected void doTestUploadMessages(final VertxTestContext ctx, final String tenantId, final Future<MqttConnAckMessage> connection, final Function<Buffer, Future<String>> sender, final Function<Handler<DownstreamMessage<? extends MessageContext>>, Future<MessageConsumer>> consumerSupplier, final Function<MqttPublishMessage, Future<String>> errorMsgHandler, final String errorTopic) throws InterruptedException {
    final boolean errorMessagesExpected = errorMsgHandler != null;
    final CountDownLatch received = new CountDownLatch(MESSAGES_TO_SEND);
    final AtomicInteger messageCount = new AtomicInteger(0);
    final AtomicLong lastReceivedTimestamp = new AtomicLong(0);
    // <correlation id of the sent telemetry/event message, errorMessageReceived promise>
    final Map<String, Promise<Void>> pendingErrorMessages = new HashMap<>();
    final AtomicBoolean consumerIsSet = new AtomicBoolean();
    final VertxTestContext setup = new VertxTestContext();
    connection.compose(ok -> consumerSupplier.apply(msg -> {
        if (errorMessagesExpected) {
            ctx.failNow(new IllegalStateException("consumer received message although sending was supposed to fail"));
            return;
        }
        LOGGER.trace("received {}", msg);
        ctx.verify(() -> {
            DownstreamMessageAssertions.assertTelemetryMessageProperties(msg, tenantId);
            assertThat(msg.getQos().ordinal()).isEqualTo(getQos().ordinal());
            assertAdditionalMessageProperties(msg);
        });
        received.countDown();
        lastReceivedTimestamp.set(System.currentTimeMillis());
        if (received.getCount() % 50 == 0) {
            LOGGER.info("messages received: {}", MESSAGES_TO_SEND - received.getCount());
        }
    })).compose(msgConsumer -> {
        consumerIsSet.set(msgConsumer != null);
        if (errorMsgHandler == null) {
            return Future.succeededFuture();
        }
        mqttClient.publishHandler(msg -> {
            LOGGER.trace("received error message [topic: {}]", msg.topicName());
            errorMsgHandler.apply(msg).onSuccess(correlationId -> {
                // correlate the error message with the corresponding publish operation and complete the publish operation promise here
                pendingErrorMessages.compute(correlationId, (key, oldValue) -> {
                    final Promise<Void> promise = Optional.ofNullable(oldValue).orElseGet(Promise::promise);
                    promise.tryComplete();
                    // remove mapping if oldValue is set
                    return oldValue != null ? null : promise;
                });
            }).onFailure(ctx::failNow);
        });
        return subscribeToErrorTopic(errorTopic);
    }).onComplete(setup.succeedingThenComplete());
    assertThat(setup.awaitCompletion(5, TimeUnit.SECONDS)).isTrue();
    if (setup.failed()) {
        ctx.failNow(setup.causeOfFailure());
        return;
    }
    customizeConnectedClient();
    final long start = System.currentTimeMillis();
    while (messageCount.get() < MESSAGES_TO_SEND) {
        final CountDownLatch messageHandlingCompleted = new CountDownLatch(errorMessagesExpected ? 2 : 1);
        context.runOnContext(go -> {
            final Buffer msg = Buffer.buffer("hello " + messageCount.getAndIncrement());
            sender.apply(msg).onComplete(sendAttempt -> {
                if (sendAttempt.failed()) {
                    LOGGER.error("error sending message {}", messageCount.get(), sendAttempt.cause());
                }
                if (messageCount.get() % 50 == 0) {
                    LOGGER.info("messages sent: " + messageCount.get());
                }
                messageHandlingCompleted.countDown();
                if (errorMessagesExpected) {
                    if (sendAttempt.failed()) {
                        messageHandlingCompleted.countDown();
                    } else {
                        // wait til error message has been received
                        final String correlationId = sendAttempt.result();
                        final long timerId = vertx.setTimer(1000, tid -> {
                            Optional.ofNullable(pendingErrorMessages.remove(correlationId)).ifPresent(promise -> promise.tryFail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "timeout waiting for error response")));
                        });
                        final Handler<AsyncResult<Void>> errorMessageReceivedOrTimeoutHandler = ar -> {
                            vertx.cancelTimer(timerId);
                            if (ar.succeeded()) {
                                received.countDown();
                                lastReceivedTimestamp.set(System.currentTimeMillis());
                                if (received.getCount() % 50 == 0) {
                                    LOGGER.info("error messages received: {}", MESSAGES_TO_SEND - received.getCount());
                                }
                            } else {
                                LOGGER.warn("failed to handle error message with correlation id [{}]", correlationId, ar.cause());
                            }
                            messageHandlingCompleted.countDown();
                        };
                        pendingErrorMessages.compute(correlationId, (key, oldValue) -> {
                            final Promise<Void> promise = Optional.ofNullable(oldValue).orElseGet(Promise::promise);
                            promise.future().onComplete(errorMessageReceivedOrTimeoutHandler);
                            // remove mapping if oldValue is set
                            return oldValue != null ? null : promise;
                        });
                    }
                }
            });
        });
        messageHandlingCompleted.await();
    }
    // in case no consumer is set, waiting time needs to be longer (adapter will wait for credit when creating the first downstream sender)
    final long timeToWait = getTimeToWait() + (!consumerIsSet.get() ? 2000 : 0);
    if (!received.await(timeToWait, TimeUnit.MILLISECONDS)) {
        LOGGER.info("Timeout of {} milliseconds reached, stop waiting to receive messages.", timeToWait);
    }
    if (lastReceivedTimestamp.get() == 0L) {
        // no message has been received at all
        lastReceivedTimestamp.set(System.currentTimeMillis());
    }
    final long messagesReceived = MESSAGES_TO_SEND - received.getCount();
    LOGGER.info("sent {} and received {} messages in {} milliseconds", messageCount.get(), messagesReceived, lastReceivedTimestamp.get() - start);
    assertMessageReceivedRatio(messagesReceived, messageCount.get(), ctx);
}
Also used : HttpURLConnection(java.net.HttpURLConnection) VertxTestContext(io.vertx.junit5.VertxTestContext) MqttQoS(io.netty.handler.codec.mqtt.MqttQoS) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MqttPublishMessage(io.vertx.mqtt.messages.MqttPublishMessage) HashMap(java.util.HashMap) SelfSignedCertificate(io.vertx.core.net.SelfSignedCertificate) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) ServiceConfigProperties(org.eclipse.hono.config.ServiceConfigProperties) Tenant(org.eclipse.hono.service.management.tenant.Tenant) CompositeFuture(io.vertx.core.CompositeFuture) IntegrationTestSupport(org.eclipse.hono.tests.IntegrationTestSupport) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) JsonObject(io.vertx.core.json.JsonObject) AsyncResult(io.vertx.core.AsyncResult) Tenants(org.eclipse.hono.tests.Tenants) RegistryManagementConstants(org.eclipse.hono.util.RegistryManagementConstants) MqttConnAckMessage(io.vertx.mqtt.messages.MqttConnAckMessage) Device(org.eclipse.hono.service.management.device.Device) QueryStringEncoder(io.netty.handler.codec.http.QueryStringEncoder) MessageContext(org.eclipse.hono.application.client.MessageContext) Promise(io.vertx.core.Promise) Set(java.util.Set) ServerErrorException(org.eclipse.hono.client.ServerErrorException) DownstreamMessageAssertions(org.eclipse.hono.tests.DownstreamMessageAssertions) UUID(java.util.UUID) Truth.assertThat(com.google.common.truth.Truth.assertThat) MessageHelper(org.eclipse.hono.util.MessageHelper) EventConstants(org.eclipse.hono.util.EventConstants) Future(io.vertx.core.Future) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) Buffer(io.vertx.core.buffer.Buffer) Optional(java.util.Optional) MessageConsumer(org.eclipse.hono.application.client.MessageConsumer) Handler(io.vertx.core.Handler) Buffer(io.vertx.core.buffer.Buffer) HashMap(java.util.HashMap) VertxTestContext(io.vertx.junit5.VertxTestContext) CountDownLatch(java.util.concurrent.CountDownLatch) Promise(io.vertx.core.Promise) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicLong(java.util.concurrent.atomic.AtomicLong) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ServerErrorException(org.eclipse.hono.client.ServerErrorException) AsyncResult(io.vertx.core.AsyncResult)

Aggregations

Future (io.vertx.core.Future)4 Handler (io.vertx.core.Handler)4 Buffer (io.vertx.core.buffer.Buffer)4 JsonObject (io.vertx.core.json.JsonObject)4 Optional (java.util.Optional)4 DownstreamMessage (org.eclipse.hono.application.client.DownstreamMessage)4 MessageConsumer (org.eclipse.hono.application.client.MessageConsumer)4 MessageContext (org.eclipse.hono.application.client.MessageContext)4 Truth.assertThat (com.google.common.truth.Truth.assertThat)3 CompositeFuture (io.vertx.core.CompositeFuture)3 Promise (io.vertx.core.Promise)3 Vertx (io.vertx.core.Vertx)3 VertxTestContext (io.vertx.junit5.VertxTestContext)3 HttpURLConnection (java.net.HttpURLConnection)3 List (java.util.List)3 CountDownLatch (java.util.concurrent.CountDownLatch)3 TimeUnit (java.util.concurrent.TimeUnit)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3 Function (java.util.function.Function)3 ServiceInvocationException (org.eclipse.hono.client.ServiceInvocationException)3