Search in sources :

Example 1 with QoS

use of org.eclipse.hono.util.QoS in project hono by eclipse.

the class VertxBasedHttpProtocolAdapterTest method testPostTelemetrySucceedsForQoS1.

/**
 * Verifies that a request (with valid credentials) to upload telemetry data with
 * 'QoS-Level: 1' using POST succeeds with a 202.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testPostTelemetrySucceedsForQoS1(final VertxTestContext ctx) {
    givenATelemetrySenderForAnyTenant();
    mockSuccessfulAuthentication("DEFAULT_TENANT", "device_1");
    httpClient.post("/telemetry").putHeader(HttpHeaders.CONTENT_TYPE.toString(), HttpUtils.CONTENT_TYPE_JSON).basicAuthentication("testuser@DEFAULT_TENANT", "password123").putHeader(HttpHeaders.ORIGIN.toString(), ORIGIN_HEADER_VALUE).putHeader(Constants.HEADER_QOS_LEVEL, String.valueOf(1)).expect(ResponsePredicate.status(HttpURLConnection.HTTP_ACCEPTED)).expect(this::assertCorsHeaders).sendJsonObject(new JsonObject(), ctx.succeeding(r -> {
        ctx.verify(() -> assertTelemetryMessageHasBeenSentDownstream(QoS.AT_LEAST_ONCE, "DEFAULT_TENANT", "device_1", "application/json"));
        ctx.completeNow();
    }));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) WebClientOptions(io.vertx.ext.web.client.WebClientOptions) BeforeEach(org.junit.jupiter.api.BeforeEach) ResponsePredicate(io.vertx.ext.web.client.predicate.ResponsePredicate) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) LoggerFactory(org.slf4j.LoggerFactory) MultiMap(io.vertx.core.MultiMap) Timeout(io.vertx.junit5.Timeout) AfterAll(org.junit.jupiter.api.AfterAll) MessagingType(org.eclipse.hono.util.MessagingType) TestInstance(org.junit.jupiter.api.TestInstance) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) BeforeAll(org.junit.jupiter.api.BeforeAll) Mockito.doAnswer(org.mockito.Mockito.doAnswer) JsonObject(io.vertx.core.json.JsonObject) JsonHelper(org.eclipse.hono.util.JsonHelper) CommandContext(org.eclipse.hono.client.command.CommandContext) HttpHeaders(io.vertx.core.http.HttpHeaders) Lifecycle(org.junit.jupiter.api.TestInstance.Lifecycle) VertxExtension(io.vertx.junit5.VertxExtension) Future(io.vertx.core.Future) TestInfo(org.junit.jupiter.api.TestInfo) Test(org.junit.jupiter.api.Test) User(io.vertx.ext.auth.User) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) UsernamePasswordCredentials(org.eclipse.hono.adapter.auth.device.UsernamePasswordCredentials) HttpAdapterMetrics(org.eclipse.hono.adapter.http.HttpAdapterMetrics) QoS(org.eclipse.hono.util.QoS) Mockito.mock(org.mockito.Mockito.mock) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) VertxTestContext(io.vertx.junit5.VertxTestContext) HttpResponse(io.vertx.ext.web.client.HttpResponse) ProtonDelivery(io.vertx.proton.ProtonDelivery) WebClient(io.vertx.ext.web.client.WebClient) ResponsePredicateResult(io.vertx.ext.web.client.predicate.ResponsePredicateResult) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Constants(org.eclipse.hono.util.Constants) DeviceUser(org.eclipse.hono.service.auth.DeviceUser) ProtocolAdapterTestSupport(org.eclipse.hono.adapter.test.ProtocolAdapterTestSupport) Timer(io.micrometer.core.instrument.Timer) HttpUtils(org.eclipse.hono.service.http.HttpUtils) AsyncResult(io.vertx.core.AsyncResult) CommandConstants(org.eclipse.hono.util.CommandConstants) Logger(org.slf4j.Logger) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) Mockito.when(org.mockito.Mockito.when) CredentialsConstants(org.eclipse.hono.util.CredentialsConstants) Mockito.verify(org.mockito.Mockito.verify) TimeUnit(java.util.concurrent.TimeUnit) DeviceCredentialsAuthProvider(org.eclipse.hono.adapter.auth.device.DeviceCredentialsAuthProvider) HttpProtocolAdapterProperties(org.eclipse.hono.adapter.http.HttpProtocolAdapterProperties) Handler(io.vertx.core.Handler) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) JsonObject(io.vertx.core.json.JsonObject) Test(org.junit.jupiter.api.Test)

Example 2 with QoS

use of org.eclipse.hono.util.QoS in project hono by eclipse.

the class DownstreamMessageProperties method applyTelemetryLimits.

private void applyTelemetryLimits() {
    final QoS qos = Optional.ofNullable(props.get(MessageHelper.APP_PROPERTY_QOS)).filter(Integer.class::isInstance).map(Integer.class::cast).map(QoS::from).orElse(QoS.AT_MOST_ONCE);
    // make sure that we always remove the default properties from the map so that
    // they are not being added to the downstream message later on
    final long configuredDefaultTtlQoS0 = getNormalizedTtlPropertyValue(TenantConstants.FIELD_TTL_TELEMETRY_QOS0);
    final long configuredDefaultTtlQoS1 = getNormalizedTtlPropertyValue(TenantConstants.FIELD_TTL_TELEMETRY_QOS1);
    final long configuredMaxTtl;
    final long configuredDefaultTtl;
    switch(qos) {
        case AT_MOST_ONCE:
            configuredDefaultTtl = configuredDefaultTtlQoS0;
            configuredMaxTtl = Optional.ofNullable(resourceLimits).map(ResourceLimits::getMaxTtlTelemetryQoS0).filter(v -> v > TenantConstants.UNLIMITED_TTL).orElse(TenantConstants.UNLIMITED_TTL);
            break;
        case AT_LEAST_ONCE:
        default:
            configuredDefaultTtl = configuredDefaultTtlQoS1;
            configuredMaxTtl = Optional.ofNullable(resourceLimits).map(ResourceLimits::getMaxTtlTelemetryQoS1).filter(v -> v > TenantConstants.UNLIMITED_TTL).orElse(TenantConstants.UNLIMITED_TTL);
    }
    final long deviceProvidedTtl = getNormalizedTtlPropertyValue(MessageHelper.SYS_HEADER_PROPERTY_TTL);
    if (deviceProvidedTtl > TenantConstants.UNLIMITED_TTL) {
        setTtl(deviceProvidedTtl, configuredMaxTtl);
    } else {
        setTtl(configuredDefaultTtl, configuredMaxTtl);
    }
}
Also used : QoS(org.eclipse.hono.util.QoS)

Example 3 with QoS

use of org.eclipse.hono.util.QoS in project hono by eclipse.

the class ProtonBasedDownstreamSenderTest method testDownstreamTelemetryMessageHasCreationTimeAndTtl.

/**
 * Verifies that a downstream telemetry message always contains a creation-time
 * and a time-to-live as defined at the tenant level.
 *
 * @param qosLevel The quality of service used for sending the message.
 * @param expectedTtl The time to live (in millis) expected to be set on the message.
 */
@ParameterizedTest
@CsvSource(value = { "AT_MOST_ONCE,10000", "AT_LEAST_ONCE,20000" })
public void testDownstreamTelemetryMessageHasCreationTimeAndTtl(final QoS qosLevel, final long expectedTtl) {
    final TenantObject tenant = TenantObject.from(Constants.DEFAULT_TENANT, true);
    tenant.setResourceLimits(new ResourceLimits().setMaxTtlTelemetryQoS0(10L).setMaxTtlTelemetryQoS1(20L));
    final RegistrationAssertion device = new RegistrationAssertion("4711");
    // WHEN sending a message without specifying any properties
    sender.sendTelemetry(tenant, device, qosLevel, "text/plain", Buffer.buffer("hello"), null, span.context());
    // THEN the message contains a creation-time
    verify(protonSender).send(argThat(message -> message.getCreationTime() > 0 && message.getTtl() == expectedTtl), VertxMockSupport.anyHandler());
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) HttpURLConnection(java.net.HttpURLConnection) VertxTestContext(io.vertx.junit5.VertxTestContext) BeforeEach(org.junit.jupiter.api.BeforeEach) CsvSource(org.junit.jupiter.params.provider.CsvSource) ArgumentMatchers.anyLong(org.mockito.ArgumentMatchers.anyLong) ArgumentMatchers.argThat(org.mockito.ArgumentMatchers.argThat) AmqpClientUnitTestHelper(org.eclipse.hono.client.amqp.test.AmqpClientUnitTestHelper) HashMap(java.util.HashMap) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Supplier(java.util.function.Supplier) Constants(org.eclipse.hono.util.Constants) EventBus(io.vertx.core.eventbus.EventBus) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Map(java.util.Map) Message(org.apache.qpid.proton.message.Message) HonoConnection(org.eclipse.hono.client.HonoConnection) ClientConfigProperties(org.eclipse.hono.config.ClientConfigProperties) ResourceLimits(org.eclipse.hono.util.ResourceLimits) Tracer(io.opentracing.Tracer) NoopTracerFactory(io.opentracing.noop.NoopTracerFactory) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) MessageHelper(org.eclipse.hono.util.MessageHelper) VertxExtension(io.vertx.junit5.VertxExtension) Future(io.vertx.core.Future) Mockito.verify(org.mockito.Mockito.verify) TenantObject(org.eclipse.hono.util.TenantObject) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Buffer(io.vertx.core.buffer.Buffer) VertxMockSupport(org.eclipse.hono.test.VertxMockSupport) Span(io.opentracing.Span) ProtonSender(io.vertx.proton.ProtonSender) SendMessageSampler(org.eclipse.hono.client.SendMessageSampler) NoopSpan(io.opentracing.noop.NoopSpan) QoS(org.eclipse.hono.util.QoS) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Mockito.mock(org.mockito.Mockito.mock) TenantObject(org.eclipse.hono.util.TenantObject) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ResourceLimits(org.eclipse.hono.util.ResourceLimits) CsvSource(org.junit.jupiter.params.provider.CsvSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 4 with QoS

use of org.eclipse.hono.util.QoS in project hono by eclipse.

the class KafkaBasedTelemetrySenderTest method testSendTelemetryCreatesCorrectRecord.

/**
 * Verifies that the Kafka record is created as expected when sending telemetry data.
 *
 * @param qos The quality of service used for sending the message.
 * @param expectedTtl The ttl expected in the message.
 * @param ctx The vert.x test context.
 */
@ParameterizedTest
@CsvSource(value = { "AT_MOST_ONCE,10000", "AT_LEAST_ONCE,60000" })
public void testSendTelemetryCreatesCorrectRecord(final QoS qos, final long expectedTtl, final VertxTestContext ctx) {
    // GIVEN a telemetry sender
    final String payload = "the-payload";
    final String contentType = "text/plain";
    final Map<String, Object> properties = Map.of("foo", "bar");
    final var spanFinished = ctx.checkpoint();
    final var messageHasHeaders = ctx.checkpoint();
    final var span = TracingMockSupport.mockSpan();
    doAnswer(invocation -> {
        spanFinished.flag();
        return null;
    }).when(span).finish();
    final var tracer = TracingMockSupport.mockTracer(span);
    final var mockProducer = KafkaClientUnitTestHelper.newMockProducer(true);
    final var factory = CachingKafkaProducerFactory.testFactory(vertxMock, (n, c) -> KafkaClientUnitTestHelper.newKafkaProducer(mockProducer));
    final var sender = new KafkaBasedTelemetrySender(vertxMock, factory, kafkaProducerConfig, true, tracer);
    tenant.setResourceLimits(new ResourceLimits().setMaxTtlTelemetryQoS0(10L).setMaxTtlTelemetryQoS1(60L));
    // WHEN sending telemetry data
    sender.sendTelemetry(tenant, device, qos, contentType, Buffer.buffer(payload), properties, null).onComplete(ctx.succeeding(t -> {
        ctx.verify(() -> {
            // THEN the producer record is created from the given values...
            final var producerRecord = mockProducer.history().get(0);
            assertThat(producerRecord.key()).isEqualTo(device.getDeviceId());
            assertThat(producerRecord.topic()).isEqualTo(new HonoTopic(HonoTopic.Type.TELEMETRY, tenant.getTenantId()).toString());
            assertThat(producerRecord.value().toString()).isEqualTo(payload);
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(producerRecord.headers(), "foo", "bar");
            KafkaClientUnitTestHelper.assertUniqueHeaderWithExpectedValue(producerRecord.headers(), MessageHelper.SYS_HEADER_PROPERTY_TTL, expectedTtl);
            // ...AND contains the standard headers
            KafkaClientUnitTestHelper.assertStandardHeaders(producerRecord, device.getDeviceId(), contentType, qos.ordinal());
        });
        messageHasHeaders.flag();
    }));
}
Also used : Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) VertxTestContext(io.vertx.junit5.VertxTestContext) BeforeEach(org.junit.jupiter.api.BeforeEach) CsvSource(org.junit.jupiter.params.provider.CsvSource) MessagingKafkaProducerConfigProperties(org.eclipse.hono.client.kafka.producer.MessagingKafkaProducerConfigProperties) HashMap(java.util.HashMap) EventBus(io.vertx.core.eventbus.EventBus) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Mockito.doAnswer(org.mockito.Mockito.doAnswer) Map(java.util.Map) TracingMockSupport(org.eclipse.hono.test.TracingMockSupport) KafkaClientUnitTestHelper(org.eclipse.hono.kafka.test.KafkaClientUnitTestHelper) ResourceLimits(org.eclipse.hono.util.ResourceLimits) Tracer(io.opentracing.Tracer) NoopTracerFactory(io.opentracing.noop.NoopTracerFactory) CachingKafkaProducerFactory(org.eclipse.hono.client.kafka.producer.CachingKafkaProducerFactory) Vertx(io.vertx.core.Vertx) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) Mockito.when(org.mockito.Mockito.when) Truth.assertThat(com.google.common.truth.Truth.assertThat) MessageHelper(org.eclipse.hono.util.MessageHelper) VertxExtension(io.vertx.junit5.VertxExtension) TenantObject(org.eclipse.hono.util.TenantObject) Test(org.junit.jupiter.api.Test) HonoTopic(org.eclipse.hono.client.kafka.HonoTopic) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Buffer(io.vertx.core.buffer.Buffer) QoS(org.eclipse.hono.util.QoS) MockProducer(org.apache.kafka.clients.producer.MockProducer) Mockito.mock(org.mockito.Mockito.mock) ResourceLimits(org.eclipse.hono.util.ResourceLimits) TenantObject(org.eclipse.hono.util.TenantObject) HonoTopic(org.eclipse.hono.client.kafka.HonoTopic) CsvSource(org.junit.jupiter.params.provider.CsvSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 5 with QoS

use of org.eclipse.hono.util.QoS 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();
        });
    }));
}
Also used : HttpURLConnection(java.net.HttpURLConnection) VertxTestContext(io.vertx.junit5.VertxTestContext) ResponsePredicate(io.vertx.ext.web.client.predicate.ResponsePredicate) DownstreamMessage(org.eclipse.hono.application.client.DownstreamMessage) HttpResponse(io.vertx.ext.web.client.HttpResponse) ProtonDelivery(io.vertx.proton.ProtonDelivery) MultiMap(io.vertx.core.MultiMap) RequestOptions(io.vertx.core.http.RequestOptions) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) AtomicReference(java.util.concurrent.atomic.AtomicReference) Constants(org.eclipse.hono.util.Constants) NoConsumerException(org.eclipse.hono.client.NoConsumerException) Tenant(org.eclipse.hono.service.management.tenant.Tenant) TelemetryConstants(org.eclipse.hono.util.TelemetryConstants) MessagingType(org.eclipse.hono.util.MessagingType) IntegrationTestSupport(org.eclipse.hono.tests.IntegrationTestSupport) ExtendWith(org.junit.jupiter.api.extension.ExtendWith) Assumptions.assumeTrue(org.junit.jupiter.api.Assumptions.assumeTrue) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) Tenants(org.eclipse.hono.tests.Tenants) MessageContext(org.eclipse.hono.application.client.MessageContext) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) HttpHeaders(io.vertx.core.http.HttpHeaders) Truth.assertThat(com.google.common.truth.Truth.assertThat) RequestResponseApiConstants(org.eclipse.hono.util.RequestResponseApiConstants) VertxExtension(io.vertx.junit5.VertxExtension) AssumeMessagingSystem(org.eclipse.hono.tests.AssumeMessagingSystem) Future(io.vertx.core.Future) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) Buffer(io.vertx.core.buffer.Buffer) AmqpApplicationClient(org.eclipse.hono.application.client.amqp.AmqpApplicationClient) MessageConsumer(org.eclipse.hono.application.client.MessageConsumer) SendMessageTimeoutException(org.eclipse.hono.client.SendMessageTimeoutException) Checkpoint(io.vertx.junit5.Checkpoint) Handler(io.vertx.core.Handler) QoS(org.eclipse.hono.util.QoS) ProtonDelivery(io.vertx.proton.ProtonDelivery) VertxTestContext(io.vertx.junit5.VertxTestContext) HttpResponse(io.vertx.ext.web.client.HttpResponse) AtomicReference(java.util.concurrent.atomic.AtomicReference) AmqpApplicationClient(org.eclipse.hono.application.client.amqp.AmqpApplicationClient) MultiMap(io.vertx.core.MultiMap) Checkpoint(io.vertx.junit5.Checkpoint) Tenant(org.eclipse.hono.service.management.tenant.Tenant) Test(org.junit.jupiter.api.Test) AssumeMessagingSystem(org.eclipse.hono.tests.AssumeMessagingSystem)

Aggregations

QoS (org.eclipse.hono.util.QoS)10 Test (org.junit.jupiter.api.Test)8 Buffer (io.vertx.core.buffer.Buffer)7 Vertx (io.vertx.core.Vertx)6 VertxTestContext (io.vertx.junit5.VertxTestContext)6 Truth.assertThat (com.google.common.truth.Truth.assertThat)5 Future (io.vertx.core.Future)5 HttpURLConnection (java.net.HttpURLConnection)5 Constants (org.eclipse.hono.util.Constants)5 BeforeEach (org.junit.jupiter.api.BeforeEach)5 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)5 Handler (io.vertx.core.Handler)4 Promise (io.vertx.core.Promise)4 VertxExtension (io.vertx.junit5.VertxExtension)4 TimeUnit (java.util.concurrent.TimeUnit)4 ExtendWith (org.junit.jupiter.api.extension.ExtendWith)4 Mockito.mock (org.mockito.Mockito.mock)3 Mockito.when (org.mockito.Mockito.when)3 Truth.assertWithMessage (com.google.common.truth.Truth.assertWithMessage)2 Tracer (io.opentracing.Tracer)2