From e84d7807841927e11379bb3eb0db7c933ebbdd8b Mon Sep 17 00:00:00 2001 From: Kaibo Cai Date: Sun, 19 Feb 2023 20:15:17 -0600 Subject: [PATCH 1/5] init rxjava3 junit test update testing logics for rxjava update test instance level migrate rxjava3 unit tests to java sort traces for test - format code style migrate rest of tests for rxjava3 format code style --- .../reactor/AbstractReactorCoreTest.java | 17 + .../AbstractRxJava3SubscriptionTest.groovy | 59 - .../v3/common/AbstractRxJava3Test.groovy | 491 -------- .../common/AbstractRxJava3WithSpanTest.groovy | 1117 ----------------- .../AbstractRxJava3SubscriptionTest.java | 54 + .../rxjava/v3/common/AbstractRxJava3Test.java | 856 +++++++++++++ .../common/AbstractRxJava3WithSpanTest.java | 995 +++++++++++++++ .../common/RxJava3ConcurrencyTestHelper.java | 2 + .../RxJava3ExtensionWithSpanTest.groovy | 16 - .../RxJava3InstrumentationWithSpanTest.groovy | 16 - .../groovy/RxJava3SubscriptionTest.groovy | 10 - .../src/test/groovy/RxJava3Test.groovy | 10 - .../src/test/java/Rx3SubscriptionTest.java | 19 + .../java/RxJava3ExtensionWithSpanTest.java | 35 + .../RxJava3InstrumentationWithSpanTest.java | 35 + .../javaagent/src/test/java/RxJava3Test.java | 28 + .../groovy/RxJava3SubscriptionTest.groovy | 18 - .../src/test/groovy/RxJava3Test.groovy | 18 - .../src/test/java/Rx3SubscriptionTest.java | 29 + .../library/src/test/java/RxJava3Test.java | 40 + .../RxJava3ExtensionWithSpanTest.groovy | 16 - .../RxJava3InstrumentationWithSpanTest.groovy | 16 - .../groovy/RxJava3SubscriptionTest.groovy | 10 - .../src/test/groovy/RxJava3Test.groovy | 10 - .../src/test/java/Rx3SubscriptionTest.java | 19 + .../java/RxJava3ExtensionWithSpanTest.java | 35 + .../RxJava3InstrumentationWithSpanTest.java | 35 + .../javaagent/src/test/java/RxJava3Test.java | 28 + .../groovy/RxJava3SubscriptionTest.groovy | 18 - .../src/test/groovy/RxJava3Test.groovy | 18 - .../src/test/java/Rx3SubscriptionTest.java | 29 + .../library/src/test/java/RxJava3Test.java | 40 + 32 files changed, 2296 insertions(+), 1843 deletions(-) delete mode 100644 instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.groovy delete mode 100644 instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.groovy delete mode 100644 instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.groovy create mode 100644 instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.java create mode 100644 instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java create mode 100644 instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.java rename instrumentation/rxjava/rxjava-3-common/testing/src/main/{groovy => java}/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java (98%) delete mode 100644 instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3ExtensionWithSpanTest.groovy delete mode 100644 instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3InstrumentationWithSpanTest.groovy delete mode 100644 instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3SubscriptionTest.groovy delete mode 100644 instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3Test.groovy create mode 100644 instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/Rx3SubscriptionTest.java create mode 100644 instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java create mode 100644 instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java create mode 100644 instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3Test.java delete mode 100644 instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3SubscriptionTest.groovy delete mode 100644 instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3Test.groovy create mode 100644 instrumentation/rxjava/rxjava-3.0/library/src/test/java/Rx3SubscriptionTest.java create mode 100644 instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3Test.java delete mode 100644 instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3ExtensionWithSpanTest.groovy delete mode 100644 instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3InstrumentationWithSpanTest.groovy delete mode 100644 instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3SubscriptionTest.groovy delete mode 100644 instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3Test.groovy create mode 100644 instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/Rx3SubscriptionTest.java create mode 100644 instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java create mode 100644 instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java create mode 100644 instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3Test.java delete mode 100644 instrumentation/rxjava/rxjava-3.1.1/library/src/test/groovy/RxJava3SubscriptionTest.groovy delete mode 100644 instrumentation/rxjava/rxjava-3.1.1/library/src/test/groovy/RxJava3Test.groovy create mode 100644 instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/Rx3SubscriptionTest.java create mode 100644 instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3Test.java diff --git a/instrumentation/reactor/reactor-3.1/testing/src/main/java/io/opentelemetry/instrumentation/reactor/AbstractReactorCoreTest.java b/instrumentation/reactor/reactor-3.1/testing/src/main/java/io/opentelemetry/instrumentation/reactor/AbstractReactorCoreTest.java index e1c64f46717a..51601291c268 100644 --- a/instrumentation/reactor/reactor-3.1/testing/src/main/java/io/opentelemetry/instrumentation/reactor/AbstractReactorCoreTest.java +++ b/instrumentation/reactor/reactor-3.1/testing/src/main/java/io/opentelemetry/instrumentation/reactor/AbstractReactorCoreTest.java @@ -9,6 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.google.common.primitives.Ints; import io.opentelemetry.api.trace.Span; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.sdk.testing.assertj.TraceAssert; @@ -115,6 +116,22 @@ void basicFlux() { span -> span.hasName("add one").hasParent(trace.getSpan(0)))); } + @Test + void basicFluxIterable() { + List result = + testing.runWithSpan( + "parent", + () -> Flux.fromIterable(Ints.asList(5, 6)).map(this::addOne).collectList().block()); + assertThat(result).containsExactly(6, 7); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasNoParent(), + span -> span.hasName("add one").hasParent(trace.getSpan(0)), + span -> span.hasName("add one").hasParent(trace.getSpan(0)))); + } + @Test void twoOperationsFlux() { List result = diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.groovy b/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.groovy deleted file mode 100644 index 3acb7761a851..000000000000 --- a/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.groovy +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.rxjava.v3.common - -import io.opentelemetry.api.GlobalOpenTelemetry -import io.opentelemetry.api.trace.SpanKind -import io.opentelemetry.instrumentation.test.InstrumentationSpecification -import io.reactivex.rxjava3.core.Single -import io.reactivex.rxjava3.functions.Consumer - -import java.util.concurrent.CountDownLatch - -abstract class AbstractRxJava3SubscriptionTest extends InstrumentationSpecification { - - def "subscription test"() { - when: - CountDownLatch latch = new CountDownLatch(1) - runWithSpan("parent") { - Single connection = Single.create { - it.onSuccess(new Connection()) - } - connection.subscribe(new Consumer() { - @Override - void accept(Connection t) { - t.query() - latch.countDown() - } - }) - } - latch.await() - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - name "parent" - kind SpanKind.INTERNAL - hasNoParent() - } - span(1) { - name "Connection.query" - kind SpanKind.INTERNAL - childOf span(0) - } - } - } - } - - static class Connection { - static int query() { - def span = GlobalOpenTelemetry.getTracer("test").spanBuilder("Connection.query").startSpan() - span.end() - return new Random().nextInt() - } - } -} diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.groovy b/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.groovy deleted file mode 100644 index 338a6b3587ec..000000000000 --- a/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.groovy +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.rxjava.v3.common - -import com.google.common.collect.Lists -import io.opentelemetry.api.common.AttributeKey -import io.opentelemetry.api.trace.Span -import io.opentelemetry.api.trace.SpanKind -import io.opentelemetry.instrumentation.test.InstrumentationSpecification -import io.reactivex.rxjava3.core.BackpressureStrategy -import io.reactivex.rxjava3.core.Completable -import io.reactivex.rxjava3.core.Flowable -import io.reactivex.rxjava3.core.Maybe -import io.reactivex.rxjava3.core.Observable -import io.reactivex.rxjava3.core.Single -import io.reactivex.rxjava3.internal.operators.flowable.FlowablePublish -import io.reactivex.rxjava3.internal.operators.observable.ObservablePublish -import io.reactivex.rxjava3.schedulers.Schedulers -import org.reactivestreams.Subscriber -import org.reactivestreams.Subscription -import spock.lang.Shared -import spock.lang.Unroll - -import static java.util.concurrent.TimeUnit.MILLISECONDS - -/** - *

Tests in this class may seem not exhaustive due to the fact that some classes are converted - * into others, ie. {@link Completable#toMaybe()}. Fortunately, RxJava3 uses helper classes like - * {@link io.reactivex.rxjava3.internal.operators.maybe.MaybeFromCompletable} and as a result we - * can test subscriptions and cancellations correctly. - */ -@Unroll -abstract class AbstractRxJava3Test extends InstrumentationSpecification { - - public static final String EXCEPTION_MESSAGE = "test exception" - - @Shared - def addOne = { i -> - addOneFunc(i) - } - - @Shared - def addTwo = { i -> - addTwoFunc(i) - } - - @Shared - def throwException = { - throw new IllegalStateException(EXCEPTION_MESSAGE) - } - - def addOneFunc(int i) { - runWithSpan("addOne") { - return i + 1 - } - } - - def addTwoFunc(int i) { - runWithSpan("addTwo") { - return i + 2 - } - } - - def "Publisher '#testName' test"() { - when: - def result = assemblePublisherUnderTrace(publisherSupplier) - - then: - result == expected - and: - assertTraces(1) { - sortSpansByStartTime() - trace(0, workSpans + 1) { - - span(0) { - name "publisher-parent" - kind SpanKind.INTERNAL - hasNoParent() - } - for (int i = 1; i < workSpans + 1; ++i) { - span(i) { - name "addOne" - kind SpanKind.INTERNAL - childOf span(0) - } - } - } - } - - where: - testName | expected | workSpans | publisherSupplier - "basic maybe" | 2 | 1 | { -> Maybe.just(1).map(addOne) } - "two operations maybe" | 4 | 2 | { -> Maybe.just(2).map(addOne).map(addOne) } - "delayed maybe" | 4 | 1 | { -> - Maybe.just(3).delay(100, MILLISECONDS).map(addOne) - } - "delayed twice maybe" | 6 | 2 | { -> - Maybe.just(4).delay(100, MILLISECONDS).map(addOne).delay(100, MILLISECONDS).map(addOne) - } - "basic flowable" | [6, 7] | 2 | { -> - Flowable.fromIterable([5, 6]).map(addOne) - } - "two operations flowable" | [8, 9] | 4 | { -> - Flowable.fromIterable([6, 7]).map(addOne).map(addOne) - } - "delayed flowable" | [8, 9] | 2 | { -> - Flowable.fromIterable([7, 8]).delay(100, MILLISECONDS).map(addOne) - } - "delayed twice flowable" | [10, 11] | 4 | { -> - Flowable.fromIterable([8, 9]).delay(100, MILLISECONDS).map(addOne).delay(100, MILLISECONDS).map(addOne) - } - "maybe from callable" | 12 | 2 | { -> - Maybe.fromCallable({ addOneFunc(10) }).map(addOne) - } - "basic single" | 1 | 1 | { -> Single.just(0).map(addOne) } - "basic observable" | [1] | 1 | { -> Observable.just(0).map(addOne) } - "connectable flowable" | [1] | 1 | { -> - FlowablePublish.just(0).delay(100, MILLISECONDS).map(addOne) - } - "connectable observable" | [1] | 1 | { -> - ObservablePublish.just(0).delay(100, MILLISECONDS).map(addOne) - } - } - - def "Publisher error '#testName' test"() { - when: - assemblePublisherUnderTrace(publisherSupplier) - - then: - def thrownException = thrown RuntimeException - thrownException.message == EXCEPTION_MESSAGE - and: - assertTraces(1) { - sortSpansByStartTime() - trace(0, 1) { - // It's important that we don't attach errors at the Reactor level so that we don't - // impact the spans on reactor integrations such as netty and lettuce, as reactor is - // more of a context propagation mechanism than something we would be tracking for - // errors this is ok. - span(0) { - name "publisher-parent" - kind SpanKind.INTERNAL - hasNoParent() - } - } - } - - where: - testName | publisherSupplier - "maybe" | { -> Maybe.error(new RuntimeException(EXCEPTION_MESSAGE)) } - "flowable" | { -> Flowable.error(new RuntimeException(EXCEPTION_MESSAGE)) } - "single" | { -> Single.error(new RuntimeException(EXCEPTION_MESSAGE)) } - "observable" | { -> Observable.error(new RuntimeException(EXCEPTION_MESSAGE)) } - "completable" | { -> Completable.error(new RuntimeException(EXCEPTION_MESSAGE)) } - } - - def "Publisher step '#testName' test"() { - when: - assemblePublisherUnderTrace(publisherSupplier) - - then: - def exception = thrown RuntimeException - exception.message == EXCEPTION_MESSAGE - and: - assertTraces(1) { - sortSpansByStartTime() - trace(0, workSpans + 1) { - // It's important that we don't attach errors at the Reactor level so that we don't - // impact the spans on reactor integrations such as netty and lettuce, as reactor is - // more of a context propagation mechanism than something we would be tracking for - // errors this is ok. - span(0) { - name "publisher-parent" - kind SpanKind.INTERNAL - hasNoParent() - } - - for (int i = 1; i < workSpans + 1; i++) { - span(i) { - name "addOne" - kind SpanKind.INTERNAL - childOf span(0) - } - } - } - } - - where: - testName | workSpans | publisherSupplier - "basic maybe failure" | 1 | { -> - Maybe.just(1).map(addOne).map({ throwException() }) - } - "basic flowable failure" | 1 | { -> - Flowable.fromIterable([5, 6]).map(addOne).map({ throwException() }) - } - } - - def "Publisher '#testName' cancel"() { - when: - cancelUnderTrace(publisherSupplier) - - then: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "publisher-parent" - kind SpanKind.INTERNAL - hasNoParent() - } - } - } - - where: - testName | publisherSupplier - "basic maybe" | { -> Maybe.just(1) } - "basic flowable" | { -> Flowable.fromIterable([5, 6]) } - "basic single" | { -> Single.just(1) } - "basic completable" | { -> Completable.fromCallable({ -> 1 }) } - "basic observable" | { -> Observable.just(1) } - } - - def "Publisher chain spans have the correct parent for '#testName'"() { - when: - assemblePublisherUnderTrace(publisherSupplier) - - then: - assertTraces(1) { - trace(0, workSpans + 1) { - span(0) { - name "publisher-parent" - kind SpanKind.INTERNAL - hasNoParent() - } - - for (int i = 1; i < workSpans + 1; i++) { - span(i) { - name "addOne" - kind SpanKind.INTERNAL - childOf span(0) - } - } - } - } - - where: - testName | workSpans | publisherSupplier - "basic maybe" | 3 | { -> - Maybe.just(1).map(addOne).map(addOne).concatWith(Maybe.just(1).map(addOne)) - } - "basic flowable" | 5 | { -> - Flowable.fromIterable([5, 6]).map(addOne).map(addOne).concatWith(Maybe.just(1).map(addOne).toFlowable()) - } - } - - def "Publisher chain spans have the correct parents from subscription time"() { - when: - def maybe = Maybe.just(42) - .map(addOne) - .map(addTwo) - - runWithSpan("trace-parent") { - maybe.blockingGet() - } - - then: - assertTraces(1) { - trace(0, 3) { - sortSpansByStartTime() - span(0) { - name "trace-parent" - kind SpanKind.INTERNAL - hasNoParent() - } - span(1) { - name "addOne" - kind SpanKind.INTERNAL - childOf span(0) - } - span(2) { - name "addTwo" - kind SpanKind.INTERNAL - childOf span(0) - } - } - } - } - - def "Publisher chain spans have the correct parents from subscription time '#testName'"() { - when: - assemblePublisherUnderTrace { - // The "add one" operations in the publisher created here should be children of the publisher-parent - def publisher = publisherSupplier() - - runWithSpan("intermediate") { - if (publisher instanceof Maybe) { - return ((Maybe) publisher).map(addTwo) - } else if (publisher instanceof Flowable) { - return ((Flowable) publisher).map(addTwo) - } else if (publisher instanceof Single) { - return ((Single) publisher).map(addTwo) - } else if (publisher instanceof Observable) { - return ((Observable) publisher).map(addTwo) - } else if (publisher instanceof Completable) { - return ((Completable) publisher).toMaybe().map(addTwo) - } - throw new IllegalStateException("Unknown publisher type") - } - } - - then: - assertTraces(1) { - trace(0, 2 + 2 * workItems) { - sortSpansByStartTime() - span(0) { - name "publisher-parent" - kind SpanKind.INTERNAL - hasNoParent() - } - span(1) { - name "intermediate" - kind SpanKind.INTERNAL - childOf span(0) - } - - for (int i = 2; i < 2 + 2 * workItems; i = i + 2) { - span(i) { - name "addOne" - kind SpanKind.INTERNAL - childOf span(0) - } - span(i + 1) { - name "addTwo" - kind SpanKind.INTERNAL - childOf span(0) - } - } - } - } - - where: - testName | workItems | publisherSupplier - "basic maybe" | 1 | { -> Maybe.just(1).map(addOne) } - "basic flowable" | 2 | { -> Flowable.fromIterable([1, 2]).map(addOne) } - "basic single" | 1 | { -> Single.just(1).map(addOne) } - "basic observable" | 1 | { -> Observable.just(1).map(addOne) } - } - - def "Flowables produce the right number of results '#scheduler'"() { - when: - List values = runWithSpan("flowable root") { - Flowable.fromIterable([1, 2, 3, 4]) - .parallel() - .runOn(scheduler) - .flatMap({ num -> - Maybe.just(num).map(addOne).toFlowable() - }) - .sequential() - .toList() - .blockingGet() - } - - then: - values.size() == 4 - assertTraces(1) { - trace(0, 5) { - span(0) { - name "flowable root" - kind SpanKind.INTERNAL - hasNoParent() - } - for (int i = 1; i < values.size() + 1; i++) { - span(i) { - name "addOne" - kind SpanKind.INTERNAL - childOf span(0) - } - } - } - } - - where: - scheduler << [Schedulers.newThread(), Schedulers.computation(), Schedulers.single(), Schedulers.trampoline()] - } - - def "test many ongoing trace chains on '#scheduler'"() { - setup: - int iterations = 100 - Set remainingIterations = new HashSet<>((0L..(iterations - 1)).toList()) - - when: - RxJava3ConcurrencyTestHelper.launchAndWait(scheduler, iterations, 60000, testRunner()) - - then: - assertTraces(iterations) { - for (int i = 0; i < iterations; i++) { - trace(i, 3) { - long iteration = -1 - span(0) { - name("outer") - iteration = span.getAttributes().get(AttributeKey.longKey("iteration")).toLong() - assert remainingIterations.remove(iteration) - } - span(1) { - name("middle") - childOf(span(0)) - assert span.getAttributes().get(AttributeKey.longKey("iteration")) == iteration - } - span(2) { - name("inner") - childOf(span(1)) - assert span.getAttributes().get(AttributeKey.longKey("iteration")) == iteration - } - } - } - } - - assert remainingIterations.isEmpty() - - where: - scheduler << [Schedulers.newThread(), Schedulers.computation(), Schedulers.single(), Schedulers.trampoline()] - } - - def cancelUnderTrace(def publisherSupplier) { - runUnderTraceWithoutExceptionCatch("publisher-parent") { - def publisher = publisherSupplier() - if (publisher instanceof Maybe) { - publisher = publisher.toFlowable() - } else if (publisher instanceof Single) { - publisher = publisher.toFlowable() - } else if (publisher instanceof Completable) { - publisher = publisher.toFlowable() - } else if (publisher instanceof Observable) { - publisher = publisher.toFlowable(BackpressureStrategy.LATEST) - } - - publisher.subscribe(new Subscriber() { - void onSubscribe(Subscription subscription) { - subscription.cancel() - } - - void onNext(Integer t) { - } - - void onError(Throwable error) { - } - - void onComplete() { - } - }) - } - } - - @SuppressWarnings("unchecked") - def assemblePublisherUnderTrace(def publisherSupplier) { - // The "add two" operations below should be children of this span - runUnderTraceWithoutExceptionCatch("publisher-parent") { - def publisher = publisherSupplier() - - // Read all data from publisher - if (publisher instanceof Maybe) { - return ((Maybe) publisher).blockingGet() - } else if (publisher instanceof Flowable) { - return Lists.newArrayList(((Flowable) publisher).blockingIterable()) - } else if (publisher instanceof Single) { - return ((Single) publisher).blockingGet() - } else if (publisher instanceof Observable) { - return Lists.newArrayList(((Observable) publisher).blockingIterable()) - } else if (publisher instanceof Completable) { - return ((Completable) publisher).toMaybe().blockingGet() - } - - throw new IllegalStateException("Unknown publisher: " + publisher) - } - } - - def runUnderTraceWithoutExceptionCatch(String spanName, Closure c) { - Span span = openTelemetry.getTracer("test") - .spanBuilder(spanName) - .startSpan() - try { - return span.makeCurrent().withCloseable { - c.call() - } - } finally { - span.end() - } - } -} diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.groovy b/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.groovy deleted file mode 100644 index 65b41ebbf812..000000000000 --- a/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.groovy +++ /dev/null @@ -1,1117 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.rxjava.v3.common - - -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.semconv.trace.attributes.SemanticAttributes -import io.reactivex.rxjava3.core.Completable -import io.reactivex.rxjava3.core.Flowable -import io.reactivex.rxjava3.core.Maybe -import io.reactivex.rxjava3.core.Observable -import io.reactivex.rxjava3.core.Single -import io.reactivex.rxjava3.observers.TestObserver -import io.reactivex.rxjava3.processors.UnicastProcessor -import io.reactivex.rxjava3.subjects.CompletableSubject -import io.reactivex.rxjava3.subjects.MaybeSubject -import io.reactivex.rxjava3.subjects.SingleSubject -import io.reactivex.rxjava3.subjects.UnicastSubject -import io.reactivex.rxjava3.subscribers.TestSubscriber -import org.reactivestreams.Publisher -import org.reactivestreams.Subscriber -import org.reactivestreams.Subscription - -import static io.opentelemetry.api.trace.SpanKind.INTERNAL -import static io.opentelemetry.api.trace.StatusCode.ERROR - -abstract class AbstractRxJava3WithSpanTest extends AgentInstrumentationSpecification { - - abstract AbstractTracedWithSpan newTraced() - - def "should capture span for already completed Completable"() { - setup: - def observer = new TestObserver() - def source = Completable.complete() - newTraced() - .completable(source) - .subscribe(observer) - observer.assertComplete() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.completable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "completable" - } - } - } - } - } - - def "should capture span for eventually completed Completable"() { - setup: - def source = CompletableSubject.create() - def observer = new TestObserver() - newTraced() - .completable(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onComplete() - observer.assertComplete() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.completable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "completable" - } - } - } - } - } - - def "should capture span for already errored Completable"() { - setup: - def error = new IllegalArgumentException("Boom") - def observer = new TestObserver() - def source = Completable.error(error) - newTraced() - .completable(source) - .subscribe(observer) - observer.assertError(error) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.completable" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "completable" - } - } - } - } - } - - def "should capture span for eventually errored Completable"() { - setup: - def error = new IllegalArgumentException("Boom") - def source = CompletableSubject.create() - def observer = new TestObserver() - newTraced() - .completable(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onError(error) - observer.assertError(error) - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.completable" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "completable" - } - } - } - } - } - - def "should capture span for canceled Completable"() { - setup: - def source = CompletableSubject.create() - def observer = new TestObserver() - newTraced() - .completable(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - observer.dispose() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.completable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "completable" - "rxjava.canceled" true - } - } - } - } - } - - def "should capture span for already completed Maybe"() { - setup: - def observer = new TestObserver() - def source = Maybe.just("Value") - newTraced() - .maybe(source) - .subscribe(observer) - observer.assertValue("Value") - observer.assertComplete() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.maybe" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "maybe" - } - } - } - } - } - - def "should capture span for already empty Maybe"() { - setup: - def observer = new TestObserver() - def source = Maybe. empty() - newTraced() - .maybe(source) - .subscribe(observer) - observer.assertComplete() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.maybe" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "maybe" - } - } - } - } - } - - def "should capture span for eventually completed Maybe"() { - setup: - def source = MaybeSubject. create() - def observer = new TestObserver() - newTraced() - .maybe(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onSuccess("Value") - observer.assertValue("Value") - observer.assertComplete() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.maybe" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "maybe" - } - } - } - } - } - - def "should capture span for already errored Maybe"() { - setup: - def error = new IllegalArgumentException("Boom") - def observer = new TestObserver() - def source = Maybe. error(error) - newTraced() - .maybe(source) - .subscribe(observer) - observer.assertError(error) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.maybe" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "maybe" - } - } - } - } - } - - def "should capture span for eventually errored Maybe"() { - setup: - def error = new IllegalArgumentException("Boom") - def source = MaybeSubject. create() - def observer = new TestObserver() - newTraced() - .maybe(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onError(error) - observer.assertError(error) - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.maybe" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "maybe" - } - } - } - } - } - - def "should capture span for canceled Maybe"() { - setup: - def source = MaybeSubject. create() - def observer = new TestObserver() - newTraced() - .maybe(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - observer.dispose() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.maybe" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "maybe" - "rxjava.canceled" true - } - } - } - } - } - - def "should capture span for already completed Single"() { - setup: - def observer = new TestObserver() - def source = Single.just("Value") - newTraced() - .single(source) - .subscribe(observer) - observer.assertValue("Value") - observer.assertComplete() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.single" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "single" - } - } - } - } - } - - def "should capture span for eventually completed Single"() { - setup: - def source = SingleSubject. create() - def observer = new TestObserver() - newTraced() - .single(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onSuccess("Value") - observer.assertValue("Value") - observer.assertComplete() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.single" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "single" - } - } - } - } - } - - def "should capture span for already errored Single"() { - setup: - def error = new IllegalArgumentException("Boom") - def observer = new TestObserver() - def source = Single. error(error) - newTraced() - .single(source) - .subscribe(observer) - observer.assertError(error) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.single" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "single" - } - } - } - } - } - - def "should capture span for eventually errored Single"() { - setup: - def error = new IllegalArgumentException("Boom") - def source = SingleSubject. create() - def observer = new TestObserver() - newTraced() - .single(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onError(error) - observer.assertError(error) - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.single" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "single" - } - } - } - } - } - - def "should capture span for canceled Single"() { - setup: - def source = SingleSubject. create() - def observer = new TestObserver() - newTraced() - .single(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - observer.dispose() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.single" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "single" - "rxjava.canceled" true - } - } - } - } - } - - def "should capture span for already completed Observable"() { - setup: - def observer = new TestObserver() - def source = Observable. just("Value") - newTraced() - .observable(source) - .subscribe(observer) - observer.assertValue("Value") - observer.assertComplete() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.observable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "observable" - } - } - } - } - } - - def "should capture span for eventually completed Observable"() { - setup: - def source = UnicastSubject. create() - def observer = new TestObserver() - newTraced() - .observable(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onNext("Value") - observer.assertValue("Value") - - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onComplete() - observer.assertComplete() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.observable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "observable" - } - } - } - } - } - - def "should capture span for already errored Observable"() { - setup: - def error = new IllegalArgumentException("Boom") - def observer = new TestObserver() - def source = Observable. error(error) - newTraced() - .observable(source) - .subscribe(observer) - observer.assertError(error) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.observable" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "observable" - } - } - } - } - } - - def "should capture span for eventually errored Observable"() { - setup: - def error = new IllegalArgumentException("Boom") - def source = UnicastSubject. create() - def observer = new TestObserver() - newTraced() - .observable(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onNext("Value") - observer.assertValue("Value") - - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onError(error) - observer.assertError(error) - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.observable" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "observable" - } - } - } - } - } - - def "should capture span for canceled Observable"() { - setup: - def source = UnicastSubject. create() - def observer = new TestObserver() - newTraced() - .observable(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onNext("Value") - observer.assertValue("Value") - - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - observer.dispose() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.observable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "observable" - "rxjava.canceled" true - } - } - } - } - } - - def "should capture span for already completed Flowable"() { - setup: - def observer = new TestSubscriber() - def source = Flowable. just("Value") - newTraced() - .flowable(source) - .subscribe(observer) - observer.assertValue("Value") - observer.assertComplete() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.flowable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "flowable" - } - } - } - } - } - - def "should capture span for eventually completed Flowable"() { - setup: - def source = UnicastProcessor. create() - def observer = new TestSubscriber() - newTraced() - .flowable(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onNext("Value") - observer.assertValue("Value") - - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onComplete() - observer.assertComplete() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.flowable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "flowable" - } - } - } - } - } - - def "should capture span for already errored Flowable"() { - setup: - def error = new IllegalArgumentException("Boom") - def observer = new TestSubscriber() - def source = Flowable. error(error) - newTraced() - .flowable(source) - .subscribe(observer) - observer.assertError(error) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.flowable" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "flowable" - } - } - } - } - } - - def "should capture span for eventually errored Flowable"() { - setup: - def error = new IllegalArgumentException("Boom") - def source = UnicastProcessor. create() - def observer = new TestSubscriber() - newTraced() - .flowable(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onNext("Value") - observer.assertValue("Value") - - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onError(error) - observer.assertError(error) - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.flowable" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "flowable" - } - } - } - } - } - - def "should capture span for canceled Flowable"() { - setup: - def source = UnicastProcessor. create() - def observer = new TestSubscriber() - newTraced() - .flowable(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onNext("Value") - observer.assertValue("Value") - - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - observer.cancel() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.flowable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "flowable" - "rxjava.canceled" true - } - } - } - } - } - - def "should capture span for already completed ParallelFlowable"() { - setup: - def observer = new TestSubscriber() - def source = Flowable. just("Value") - newTraced() - .parallelFlowable(source.parallel()) - .sequential() - .subscribe(observer) - observer.assertValue("Value") - observer.assertComplete() - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.parallelFlowable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "parallelFlowable" - } - } - } - } - } - - def "should capture span for eventually completed ParallelFlowable"() { - setup: - def source = UnicastProcessor. create() - def observer = new TestSubscriber() - newTraced() - .parallelFlowable(source.parallel()) - .sequential() - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onNext("Value") - observer.assertValue("Value") - - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onComplete() - observer.assertComplete() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.parallelFlowable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "parallelFlowable" - } - } - } - } - } - - def "should capture span for already errored ParallelFlowable"() { - setup: - def error = new IllegalArgumentException("Boom") - def observer = new TestSubscriber() - def source = Flowable. error(error) - newTraced() - .parallelFlowable(source.parallel()) - .sequential() - .subscribe(observer) - observer.assertError(error) - - expect: - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.parallelFlowable" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "parallelFlowable" - } - } - } - } - } - - def "should capture span for eventually errored ParallelFlowable"() { - setup: - def error = new IllegalArgumentException("Boom") - def source = UnicastProcessor. create() - def observer = new TestSubscriber() - newTraced() - .parallelFlowable(source.parallel()) - .sequential() - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onNext("Value") - observer.assertValue("Value") - - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onError(error) - observer.assertError(error) - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.parallelFlowable" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "parallelFlowable" - } - } - } - } - } - - def "should capture span for canceled ParallelFlowable"() { - setup: - def source = UnicastProcessor. create() - def observer = new TestSubscriber() - newTraced() - .parallelFlowable(source.parallel()) - .sequential() - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onNext("Value") - observer.assertValue("Value") - - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - observer.cancel() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.parallelFlowable" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "parallelFlowable" - "rxjava.canceled" true - } - } - } - } - } - - def "should capture span for eventually completed Publisher"() { - setup: - def source = new CustomPublisher() - def observer = new TestSubscriber() - newTraced() - .publisher(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onComplete() - observer.assertComplete() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.publisher" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "publisher" - } - } - } - } - } - - def "should capture span for eventually errored Publisher"() { - setup: - def error = new IllegalArgumentException("Boom") - def source = new CustomPublisher() - def observer = new TestSubscriber() - newTraced() - .publisher(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - source.onError(error) - observer.assertError(error) - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.publisher" - kind INTERNAL - hasNoParent() - status ERROR - errorEvent(IllegalArgumentException, "Boom") - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "publisher" - } - } - } - } - } - - def "should capture span for canceled Publisher"() { - setup: - def source = new CustomPublisher() - def observer = new TestSubscriber() - newTraced() - .publisher(source) - .subscribe(observer) - - expect: - Thread.sleep(500) // sleep a bit just to make sure no span is captured - assertTraces(0) {} - - observer.cancel() - - assertTraces(1) { - trace(0, 1) { - span(0) { - name "TracedWithSpan.publisher" - kind INTERNAL - hasNoParent() - attributes { - "$SemanticAttributes.CODE_NAMESPACE" { it.endsWith(".TracedWithSpan") } - "$SemanticAttributes.CODE_FUNCTION" "publisher" - "rxjava.canceled" true - } - } - } - } - } - - static class CustomPublisher implements Publisher, Subscription { - Subscriber subscriber - - @Override - void subscribe(Subscriber subscriber) { - this.subscriber = subscriber - subscriber.onSubscribe(this) - } - - void onComplete() { - this.subscriber.onComplete() - } - - void onError(Throwable exception) { - this.subscriber.onError(exception) - } - - @Override - void request(long l) {} - - @Override - void cancel() {} - } -} diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.java new file mode 100644 index 000000000000..d38ac0058937 --- /dev/null +++ b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.java @@ -0,0 +1,54 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.rxjava.v3.common; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.disposables.Disposable; +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import org.junit.jupiter.api.Test; + +public abstract class AbstractRxJava3SubscriptionTest { + + protected abstract InstrumentationExtension testing(); + + @Test + public void subscriptionTest() throws InterruptedException { + CountDownLatch countDownLatch = new CountDownLatch(1); + testing() + .runWithSpan( + "parent", + () -> { + Single connectionSingle = + Single.create(emitter -> emitter.onSuccess(new Connection())); + Disposable unused = + connectionSingle.subscribe( + connection -> { + connection.query(); + countDownLatch.countDown(); + }); + }); + countDownLatch.await(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> span.hasName("Connection.query").hasKind(SpanKind.INTERNAL))); + } + + static class Connection { + int query() { + Span span = GlobalOpenTelemetry.getTracer("test").spanBuilder("Connection.query").startSpan(); + span.end(); + return new Random().nextInt(); + } + } +} diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java new file mode 100644 index 000000000000..5609183b6242 --- /dev/null +++ b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java @@ -0,0 +1,856 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.rxjava.v3.common; + +import static io.opentelemetry.sdk.testing.assertj.LogAssertions.assertThat; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.google.common.primitives.Ints; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable; +import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier; +import io.opentelemetry.sdk.testing.assertj.TraceAssert; +import io.reactivex.rxjava3.core.BackpressureStrategy; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.Maybe; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.Scheduler; +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.internal.operators.flowable.FlowablePublish; +import io.reactivex.rxjava3.internal.operators.observable.ObservablePublish; +import io.reactivex.rxjava3.schedulers.Schedulers; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public abstract class AbstractRxJava3Test { + protected abstract InstrumentationExtension testing(); + + protected abstract InstrumentationTestRunner testRunner(); + + private static final String EXCEPTION_MESSAGE = "test exception"; + private static final String PARENT = "publisher-parent"; + private static final String ADD_ONE = "addOne"; + private static final String ADD_TWO = "addTwo"; + + private static Stream provideParameters() { + return Stream.of( + Arguments.of(Schedulers.newThread()), + Arguments.of(Schedulers.computation()), + Arguments.of(Schedulers.single()), + Arguments.of(Schedulers.trampoline())); + } + + private int addOne(int i) { + return testing().runWithSpan(ADD_ONE, () -> i + 1); + } + + private int addTwo(int i) { + return testing().runWithSpan(ADD_TWO, () -> i + 2); + } + + private T createParentSpan(ThrowingSupplier test) { + return testing().runWithSpan(PARENT, test); + } + + private void createParentSpan(ThrowingRunnable test) { + testing().runWithSpan(PARENT, test); + } + // private T createParentSpan(ThrowingSupplier test) { + // OpenTelemetry. + // } + + private enum CancellingSubscriber implements Subscriber { + INSTANCE; + + @Override + public void onSubscribe(Subscription subscription) {} + + @Override + public void onNext(Object o) {} + + @Override + public void onError(Throwable throwable) {} + + @Override + public void onComplete() {} + } + + @Test + public void basicMaybe() { + int result = createParentSpan(() -> Maybe.just(1).map(this::addOne).blockingGet()); + assertThat(result).isEqualTo(2); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void twoOperationsMaybe() { + int result = + createParentSpan(() -> Maybe.just(2).map(this::addOne).map(this::addOne).blockingGet()); + assertThat(result).isEqualTo(4); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void delayedMaybe() { + int result = + createParentSpan( + () -> Maybe.just(3).delay(100, TimeUnit.MILLISECONDS).map(this::addOne).blockingGet()); + assertThat(result).isEqualTo(4); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void delayedTwiceMaybe() { + int result = + createParentSpan( + () -> + Maybe.just(4) + .delay(100, TimeUnit.MILLISECONDS) + .map(this::addOne) + .delay(100, TimeUnit.MILLISECONDS) + .map(this::addOne) + .blockingGet()); + assertThat(result).isEqualTo(6); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void basicFlowable() { + Iterable result = + createParentSpan( + () -> + Flowable.fromIterable(Ints.asList(5, 6)).map(this::addOne).toList().blockingGet()); + assertThat(result).contains(6, 7); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void twoOperationsFlowable() { + List result = + createParentSpan( + () -> + Flowable.fromIterable(Ints.asList(6, 7)) + .map(this::addOne) + .map(this::addOne) + .toList() + .blockingGet()); + assertThat(result).contains(8, 9); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void delayedFlowable() { + List result = + createParentSpan( + () -> + Flowable.fromIterable(Ints.asList(7, 8)) + .delay(100, TimeUnit.MILLISECONDS) + .map(this::addOne) + .toList() + .blockingGet()); + assertThat(result).contains(8, 9); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void delayedTwiceFlowable() { + List result = + createParentSpan( + () -> + Flowable.fromIterable(Ints.asList(8, 9)) + .delay(100, TimeUnit.MILLISECONDS) + .map(this::addOne) + .delay(100, TimeUnit.MILLISECONDS) + .map(this::addOne) + .toList() + .blockingGet()); + assertThat(result).contains(10, 11); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void maybeFromCallable() { + Integer result = + createParentSpan( + () -> Maybe.fromCallable(() -> addOne(10)).map(this::addOne).blockingGet()); + assertThat(result).isEqualTo(12); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void basicSingle() { + Integer result = createParentSpan(() -> Single.just(0).map(this::addOne).blockingGet()); + assertThat(result).isEqualTo(1); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void basicObservable() { + List result = + createParentSpan(() -> Observable.just(0).map(this::addOne).toList().blockingGet()); + assertThat(result).contains(1); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void connectableFlowable() { + List result = + createParentSpan( + () -> + FlowablePublish.just(0) + .delay(100, TimeUnit.MILLISECONDS) + .map(this::addOne) + .toList() + .blockingGet()); + assertThat(result).contains(1); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void connectableObservable() { + List result = + createParentSpan( + () -> + ObservablePublish.just(0) + .delay(100, TimeUnit.MILLISECONDS) + .map(this::addOne) + .toList() + .blockingGet()); + assertThat(result).contains(1); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void maybeError() { + IllegalStateException error = new IllegalStateException(EXCEPTION_MESSAGE); + assertThatThrownBy(() -> createParentSpan(() -> Maybe.error(error).blockingGet())) + .isEqualTo(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void flowableError() { + IllegalStateException error = new IllegalStateException(EXCEPTION_MESSAGE); + assertThatThrownBy(() -> createParentSpan(() -> Flowable.error(error)).toList().blockingGet()) + .isEqualTo(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void singleError() { + IllegalStateException error = new IllegalStateException(EXCEPTION_MESSAGE); + assertThatThrownBy(() -> createParentSpan(() -> Single.error(error)).blockingGet()) + .isEqualTo(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void observableError() { + IllegalStateException error = new IllegalStateException(EXCEPTION_MESSAGE); + assertThatThrownBy(() -> createParentSpan(() -> Observable.error(error).toList().blockingGet())) + .isEqualTo(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void completableError() { + IllegalStateException error = new IllegalStateException(EXCEPTION_MESSAGE); + assertThatThrownBy( + () -> createParentSpan(() -> Completable.error(error).toMaybe().blockingGet())) + .isEqualTo(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void basicMaybeFailure() { + IllegalStateException error = new IllegalStateException(EXCEPTION_MESSAGE); + assertThatThrownBy( + () -> + createParentSpan( + () -> + Maybe.just(1) + .map(this::addOne) + .map( + i -> { + throw error; + }) + .blockingGet())) + .isEqualTo(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void basicFlowableFailure() { + IllegalStateException error = new IllegalStateException(EXCEPTION_MESSAGE); + assertThatThrownBy( + () -> + createParentSpan( + () -> + Flowable.fromIterable(Ints.asList(5, 6)) + .map(this::addOne) + .map( + i -> { + throw error; + }) + .toList() + .blockingGet())) + .isEqualTo(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void basicMaybeCancel() { + createParentSpan(() -> Maybe.just(1).toFlowable().subscribe(CancellingSubscriber.INSTANCE)); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void basicFlowableCancel() { + createParentSpan( + () -> + Flowable.fromIterable(Ints.asList(5, 6)) + .map(this::addOne) + .subscribe(CancellingSubscriber.INSTANCE)); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void basicSingleCancel() { + createParentSpan(() -> Single.just(1).toFlowable().subscribe(CancellingSubscriber.INSTANCE)); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void basicCompletableCancel() { + createParentSpan( + () -> + Completable.fromCallable(() -> 1) + .toFlowable() + .subscribe(CancellingSubscriber.INSTANCE)); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void basicObservableCancel() { + createParentSpan( + () -> + Observable.just(1) + .toFlowable(BackpressureStrategy.LATEST) + .subscribe(CancellingSubscriber.INSTANCE)); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent())); + } + + @Test + public void basicMaybeChain() { + createParentSpan( + () -> + Maybe.just(1) + .map(this::addOne) + .map(this::addOne) + .concatWith(Maybe.just(1).map(this::addOne)) + .toList() + .blockingGet()); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void basicFlowableChain() { + createParentSpan( + () -> + Flowable.fromIterable(Ints.asList(5, 6)) + .map(this::addOne) + .map(this::addOne) + .concatWith(Maybe.just(1).map(this::addOne)) + .toList() + .blockingGet()); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + // Publisher chain spans have the correct parents from subscription time + @Test + public void maybeChainParentSpan() { + testing() + .runWithSpan( + "trace-parent", () -> Maybe.just(42).map(this::addOne).map(this::addTwo).blockingGet()); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("trace-parent").hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_TWO) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void maybeChainHasAssemblyContext() { + Integer result = + createParentSpan( + () -> { + Maybe maybe = Maybe.just(1).map(this::addOne); + return testing() + .runWithSpan("intermediate", () -> maybe.map(this::addTwo)) + .blockingGet(); + }); + assertThat(result).isEqualTo(4); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName("intermediate") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_TWO) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void flowableChainHasAssemblyContext() { + List result = + createParentSpan( + () -> { + Flowable flowable = + Flowable.fromIterable(Ints.asList(1, 2)).map(this::addOne); + return testing() + .runWithSpan("intermediate", () -> flowable.map(this::addTwo)) + .toList() + .blockingGet(); + }); + assertThat(result).contains(4, 5); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName("intermediate") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_TWO) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_TWO) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void singleChainHasAssemblyContext() { + Integer result = + createParentSpan( + () -> { + Single single = Single.just(1).map(this::addOne); + return testing() + .runWithSpan("intermediate", () -> single.map(this::addTwo)) + .blockingGet(); + }); + assertThat(result).isEqualTo(4); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName("intermediate") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_TWO) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + public void observableChainHasAssemblyContext() { + List result = + createParentSpan( + () -> { + Observable observable = Observable.just(1).map(this::addOne); + return testing() + .runWithSpan("intermediate", () -> observable.map(this::addTwo)) + .toList() + .blockingGet(); + }); + assertThat(result).contains(4); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName(PARENT).hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName("intermediate") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_TWO) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @ParameterizedTest + @MethodSource("provideParameters") + public void flowableMultiResults(Scheduler scheduler) { + List result = + testing() + .runWithSpan( + "flowable root", + () -> { + return Flowable.fromIterable(Ints.asList(1, 2, 3, 4)) + .parallel() + .runOn(scheduler) + .flatMap(num -> Maybe.just(num).map(this::addOne).toFlowable()) + .sequential() + .toList() + .blockingGet(); + }); + assertThat(result.size()).isEqualTo(4); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("flowable root").hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)), + span -> + span.hasName(ADD_ONE) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @ParameterizedTest + @MethodSource("provideParameters") + public void maybeMultipleTraceChains(Scheduler scheduler) { + int iterations = 100; + RxJava3ConcurrencyTestHelper.launchAndWait(scheduler, iterations, 60000, testRunner()); + @SuppressWarnings("unchecked") + Consumer[] assertions = (Consumer[]) new Consumer[iterations]; + for (int i = 0; i < iterations; i++) { + int iteration = i; + assertions[i] = + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("outer") + .hasNoParent() + .hasAttributes(attributeEntry("iteration", iteration)), + span -> + span.hasName("middle") + .hasParent(trace.getSpan(0)) + .hasAttributes(attributeEntry("iteration", iteration)), + span -> + span.hasName("inner") + .hasParent(trace.getSpan(1)) + .hasAttributes(attributeEntry("iteration", iteration))); + } + testing() + .waitAndAssertSortedTraces( + Comparator.comparing( + span -> span.get(0).getAttributes().get(AttributeKey.longKey("iteration"))), + assertions); + testing().clearData(); + } +} diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.java b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.java new file mode 100644 index 000000000000..2b4d2490e5ad --- /dev/null +++ b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.java @@ -0,0 +1,995 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.rxjava.v3.common; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.CODE_FUNCTION; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.CODE_NAMESPACE; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.Maybe; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.processors.UnicastProcessor; +import io.reactivex.rxjava3.subjects.CompletableSubject; +import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.subjects.SingleSubject; +import io.reactivex.rxjava3.subjects.UnicastSubject; +import io.reactivex.rxjava3.subscribers.TestSubscriber; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; + +public abstract class AbstractRxJava3WithSpanTest { + private static final AttributeKey RXJAVA_CANCELED = + AttributeKey.booleanKey("rxjava.canceled"); + + protected abstract AbstractTracedWithSpan newTraced(); + + protected abstract InstrumentationExtension testing(); + + protected abstract InstrumentationTestRunner testRunner(); + + @Test + public void captureSpanForCompletedCompletable() { + TestObserver observer = new TestObserver<>(); + Completable source = Completable.complete(); + newTraced().completable(source).subscribe(observer); + observer.assertComplete(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.completable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "completable")))); + } + + @Test + public void captureSpanForEventuallyCompletedCompletable() throws InterruptedException { + CompletableSubject source = CompletableSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().completable(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onComplete(); + observer.assertComplete(); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.completable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "completable")))); + } + + @Test + public void captureSpanForErrorCompletable() { + IllegalStateException error = new IllegalStateException("Boom"); + TestObserver observer = new TestObserver<>(); + Completable source = Completable.error(error); + newTraced().completable(source).subscribe(observer); + observer.assertError(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.completable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "completable")))); + } + + @Test + public void captureSpanForEventuallyErrorCompletable() throws InterruptedException { + IllegalStateException error = new IllegalStateException("Boom"); + CompletableSubject source = CompletableSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().completable(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onError(error); + observer.assertError(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.completable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "completable")))); + } + + @Test + public void captureSpanForCanceledCompletable() throws InterruptedException { + CompletableSubject source = CompletableSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().completable(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + observer.dispose(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.completable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "completable"), + equalTo(RXJAVA_CANCELED, true)))); + } + + @Test + public void captureSpanForCompletedMaybe() { + Maybe source = Maybe.just("Value"); + TestObserver observer = new TestObserver<>(); + newTraced().maybe(source).subscribe(observer); + observer.assertValue("Value"); + observer.assertComplete(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.maybe") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "maybe")))); + } + + @Test + public void captureSpanForEmptyMaybe() { + Maybe source = Maybe.empty(); + TestObserver observer = new TestObserver<>(); + newTraced().maybe(source).subscribe(observer); + observer.assertComplete(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.maybe") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "maybe")))); + } + + @Test + public void captureSpanForEventuallyCompletedMaybe() throws InterruptedException { + MaybeSubject source = MaybeSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().maybe(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onSuccess("Value"); + observer.assertValue("Value"); + observer.assertComplete(); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.maybe") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "maybe")))); + } + + @Test + public void captureSpanForErrorMaybe() { + IllegalStateException error = new IllegalStateException("Boom"); + TestObserver observer = new TestObserver<>(); + Maybe source = Maybe.error(error); + newTraced().maybe(source).subscribe(observer); + observer.assertError(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.maybe") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "maybe")))); + } + + @Test + public void captureSpanForEventuallyErrorMaybe() throws InterruptedException { + IllegalStateException error = new IllegalStateException("Boom"); + MaybeSubject source = MaybeSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().maybe(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onError(error); + observer.assertError(error); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.maybe") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "maybe")))); + } + + @Test + public void captureSpanForCanceledMaybe() throws InterruptedException { + MaybeSubject source = MaybeSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().maybe(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + observer.dispose(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.maybe") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "maybe"), + equalTo(RXJAVA_CANCELED, true)))); + } + + @Test + public void captureSpanForCompletedSingle() { + Single source = Single.just("Value"); + TestObserver observer = new TestObserver<>(); + newTraced().single(source).subscribe(observer); + observer.assertValue("Value"); + observer.assertComplete(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.single") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "single")))); + } + + @Test + public void captureSpanForEventuallyCompletedSingle() throws InterruptedException { + SingleSubject source = SingleSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().single(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onSuccess("Value"); + observer.assertValue("Value"); + observer.assertComplete(); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.single") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "single")))); + } + + @Test + public void captureSpanForErrorSingle() { + IllegalStateException error = new IllegalStateException("Boom"); + TestObserver observer = new TestObserver<>(); + Single source = Single.error(error); + newTraced().single(source).subscribe(observer); + observer.assertError(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.single") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "single")))); + } + + @Test + public void captureSpanForEventuallyErrorSingle() throws InterruptedException { + IllegalStateException error = new IllegalStateException("Boom"); + SingleSubject source = SingleSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().single(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onError(error); + observer.assertError(error); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.single") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "single")))); + } + + @Test + public void captureSpanForCanceledSingle() throws InterruptedException { + SingleSubject source = SingleSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().single(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + observer.dispose(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.single") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "single"), + equalTo(RXJAVA_CANCELED, true)))); + } + + @Test + public void captureSpanForCompletedObservable() { + TestObserver observer = new TestObserver<>(); + Observable source = Observable.just("Value"); + newTraced().observable(source).subscribe(observer); + observer.assertValue("Value"); + observer.assertComplete(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.observable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "observable")))); + } + + @Test + public void captureSpanForEventuallyCompletedObservable() throws InterruptedException { + TestObserver observer = new TestObserver<>(); + UnicastSubject source = UnicastSubject.create(); + newTraced().observable(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onNext("Value"); + observer.assertValue("Value"); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onComplete(); + observer.assertComplete(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.observable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "observable")))); + } + + @Test + public void captureSpanForErrorObservable() { + IllegalStateException error = new IllegalStateException("Boom"); + Observable source = Observable.error(error); + TestObserver observer = new TestObserver<>(); + newTraced().observable(source).subscribe(observer); + observer.assertError(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.observable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "observable")))); + } + + @Test + public void captureSpanForEventuallyErrorObservable() throws InterruptedException { + IllegalStateException error = new IllegalStateException("Boom"); + UnicastSubject source = UnicastSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().observable(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onNext("Value"); + observer.assertValue("Value"); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onError(error); + observer.assertError(error); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.observable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "observable")))); + } + + @Test + public void captureSpanForCanceledObservable() throws InterruptedException { + UnicastSubject source = UnicastSubject.create(); + TestObserver observer = new TestObserver<>(); + newTraced().observable(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onNext("Value"); + observer.assertValue("Value"); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + observer.dispose(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.observable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "observable"), + equalTo(RXJAVA_CANCELED, true)))); + } + + @Test + public void captureSpanForCompletedFlowable() { + TestSubscriber observe = new TestSubscriber<>(); + Flowable source = Flowable.just("Value"); + newTraced().flowable(source).subscribe(observe); + observe.assertValue("Value"); + observe.assertComplete(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.flowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "flowable")))); + } + + @Test + public void captureForEventuallyCompletedFlowable() throws InterruptedException { + UnicastProcessor source = UnicastProcessor.create(); + TestSubscriber observer = new TestSubscriber<>(); + newTraced().flowable(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onNext("Value"); + observer.assertValue("Value"); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onComplete(); + observer.assertComplete(); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.flowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "flowable")))); + } + + @Test + public void captureSpanForErrorFlowable() { + IllegalStateException error = new IllegalStateException("Boom"); + TestSubscriber observer = new TestSubscriber<>(); + Flowable source = Flowable.error(error); + newTraced().flowable(source).subscribe(observer); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.flowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "flowable")))); + } + + @Test + public void captureSpanForEventuallyErrorFlowable() throws InterruptedException { + IllegalStateException error = new IllegalStateException("Boom"); + UnicastProcessor source = UnicastProcessor.create(); + TestSubscriber observer = new TestSubscriber<>(); + newTraced().flowable(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onNext("Value"); + observer.assertValue("Value"); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onError(error); + observer.assertError(error); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.flowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "flowable")))); + } + + @Test + public void captureSpanForCanceledFlowable() throws InterruptedException { + UnicastProcessor source = UnicastProcessor.create(); + TestSubscriber observer = new TestSubscriber<>(); + newTraced().flowable(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onNext("Value"); + observer.assertValue("Value"); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + observer.cancel(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.flowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "flowable"), + equalTo(RXJAVA_CANCELED, true)))); + } + + @Test + public void captureSpanForCompletedParallelFlowable() { + Flowable source = Flowable.just("Value"); + TestSubscriber observer = new TestSubscriber<>(); + newTraced().parallelFlowable(source.parallel()).sequential().subscribe(observer); + observer.assertValue("Value"); + observer.assertComplete(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.parallelFlowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "parallelFlowable")))); + } + + @Test + public void captureSpanForEventuallyCompletedParallelFlowable() throws InterruptedException { + UnicastProcessor source = UnicastProcessor.create(); + TestSubscriber observer = new TestSubscriber<>(); + newTraced().parallelFlowable(source.parallel()).sequential().subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onNext("Value"); + observer.assertValue("Value"); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onComplete(); + observer.assertComplete(); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.parallelFlowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "parallelFlowable")))); + } + + @Test + public void captureSpanForErrorParallelFlowable() { + IllegalStateException error = new IllegalStateException("Boom"); + TestSubscriber observer = new TestSubscriber<>(); + Flowable source = Flowable.error(error); + newTraced().parallelFlowable(source.parallel()).sequential().subscribe(observer); + observer.assertError(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.parallelFlowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "parallelFlowable")))); + } + + @Test + public void captureSpanForEventuallyErrorParallelFlowable() throws InterruptedException { + IllegalStateException error = new IllegalStateException("Boom"); + TestSubscriber observer = new TestSubscriber<>(); + UnicastProcessor source = UnicastProcessor.create(); + newTraced().parallelFlowable(source.parallel()).sequential().subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onNext("Value"); + observer.assertValue("Value"); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onError(error); + observer.assertError(error); + + observer.assertError(error); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.parallelFlowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "parallelFlowable")))); + } + + @Test + public void captureSpanForCanceledParallelFlowable() throws InterruptedException { + TestSubscriber observer = new TestSubscriber<>(); + UnicastProcessor source = UnicastProcessor.create(); + newTraced().parallelFlowable(source.parallel()).sequential().subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onNext("Value"); + observer.assertValue("Value"); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + observer.cancel(); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.parallelFlowable") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "parallelFlowable"), + equalTo(RXJAVA_CANCELED, true)))); + } + + @Test + public void captureSpanForEventuallyCompletedPublisher() throws InterruptedException { + CustomPublisher source = new CustomPublisher(); + TestSubscriber observer = new TestSubscriber<>(); + newTraced().publisher(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onComplete(); + observer.assertComplete(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.publisher") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "publisher")))); + } + + @Test + public void captureSpanForEventuallyErrorPublisher() throws InterruptedException { + IllegalStateException error = new IllegalStateException("Boom"); + CustomPublisher source = new CustomPublisher(); + TestSubscriber observer = new TestSubscriber<>(); + newTraced().publisher(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + source.onError(error); + observer.assertError(error); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.publisher") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(error) + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "publisher")))); + } + + @Test + public void captureSpanForCanceledPublisher() throws InterruptedException { + CustomPublisher source = new CustomPublisher(); + TestSubscriber observer = new TestSubscriber<>(); + newTraced().publisher(source).subscribe(observer); + + // sleep a bit just to make sure no span is captured + Thread.sleep(500); + List> traces = testRunner().traces(); + assertThat(traces).isEmpty(); + + observer.cancel(); + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("TracedWithSpan.publisher") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributesSatisfyingExactly( + satisfies(CODE_NAMESPACE, val -> val.endsWith(".TracedWithSpan")), + equalTo(CODE_FUNCTION, "publisher"), + equalTo(RXJAVA_CANCELED, true)))); + } + + static class CustomPublisher implements Publisher, Subscription { + + Subscriber subscriber; + + @Override + public void subscribe(Subscriber subscriber) { + this.subscriber = subscriber; + subscriber.onSubscribe(this); + } + + void onComplete() { + this.subscriber.onComplete(); + } + + void onError(Throwable exception) { + this.subscriber.onError(exception); + } + + @Override + public void request(long l) {} + + @Override + public void cancel() {} + } +} diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java similarity index 98% rename from instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java rename to instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java index 5625c98ae6f2..ba00e212fb60 100644 --- a/instrumentation/rxjava/rxjava-3-common/testing/src/main/groovy/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java +++ b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java @@ -23,6 +23,8 @@ * from different traces. */ public class RxJava3ConcurrencyTestHelper { + private RxJava3ConcurrencyTestHelper() {} + public static void launchAndWait( Scheduler scheduler, int iterations, long timeoutMillis, InstrumentationTestRunner runner) { CountDownLatch latch = new CountDownLatch(iterations); diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3ExtensionWithSpanTest.groovy b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3ExtensionWithSpanTest.groovy deleted file mode 100644 index e910848831e3..000000000000 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3ExtensionWithSpanTest.groovy +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan -import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan - -class RxJava3ExtensionWithSpanTest extends AbstractRxJava3WithSpanTest { - - @Override - AbstractTracedWithSpan newTraced() { - return new TracedWithSpan() - } -} diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3InstrumentationWithSpanTest.groovy b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3InstrumentationWithSpanTest.groovy deleted file mode 100644 index 68938741d3b9..000000000000 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3InstrumentationWithSpanTest.groovy +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan -import io.opentelemetry.instrumentation.rxjava.v3.common.instrumentationannotation.TracedWithSpan - -class RxJava3InstrumentationWithSpanTest extends AbstractRxJava3WithSpanTest { - - @Override - AbstractTracedWithSpan newTraced() { - return new TracedWithSpan() - } -} diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3SubscriptionTest.groovy b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3SubscriptionTest.groovy deleted file mode 100644 index b46f33bcc050..000000000000 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3SubscriptionTest.groovy +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3SubscriptionTest -import io.opentelemetry.instrumentation.test.AgentTestTrait - -class RxJava3SubscriptionTest extends AbstractRxJava3SubscriptionTest implements AgentTestTrait { -} diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3Test.groovy b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3Test.groovy deleted file mode 100644 index 706aae82a6f9..000000000000 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/groovy/RxJava3Test.groovy +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test -import io.opentelemetry.instrumentation.test.AgentTestTrait - -class RxJava3Test extends AbstractRxJava3Test implements AgentTestTrait { -} diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/Rx3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/Rx3SubscriptionTest.java new file mode 100644 index 000000000000..49b86d517e87 --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/Rx3SubscriptionTest.java @@ -0,0 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3SubscriptionTest; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class Rx3SubscriptionTest extends AbstractRxJava3SubscriptionTest { + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } +} diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java new file mode 100644 index 000000000000..99135062ce4e --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest; +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan; +import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan; +import io.opentelemetry.instrumentation.testing.AgentTestRunner; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class RxJava3ExtensionWithSpanTest extends AbstractRxJava3WithSpanTest { + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); + + @Override + protected AbstractTracedWithSpan newTraced() { + return new TracedWithSpan(); + } + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + protected InstrumentationTestRunner testRunner() { + return RUNNER; + } +} diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java new file mode 100644 index 000000000000..680bfabfcfb3 --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest; +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan; +import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan; +import io.opentelemetry.instrumentation.testing.AgentTestRunner; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class RxJava3InstrumentationWithSpanTest extends AbstractRxJava3WithSpanTest { + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); + + @Override + protected AbstractTracedWithSpan newTraced() { + return new TracedWithSpan(); + } + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + protected InstrumentationTestRunner testRunner() { + return RUNNER; + } +} diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3Test.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3Test.java new file mode 100644 index 000000000000..e49a6acf55cc --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3Test.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test; +import io.opentelemetry.instrumentation.testing.AgentTestRunner; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class RxJava3Test extends AbstractRxJava3Test { + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + protected InstrumentationTestRunner testRunner() { + return RUNNER; + } +} diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3SubscriptionTest.groovy b/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3SubscriptionTest.groovy deleted file mode 100644 index e855b04f4e16..000000000000 --- a/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3SubscriptionTest.groovy +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3SubscriptionTest -import io.opentelemetry.instrumentation.rxjava.v3_0.TracingAssembly -import io.opentelemetry.instrumentation.test.LibraryTestTrait -import spock.lang.Shared - -class RxJava3SubscriptionTest extends AbstractRxJava3SubscriptionTest implements LibraryTestTrait { - @Shared - TracingAssembly tracingAssembly = TracingAssembly.create() - - def setupSpec() { - tracingAssembly.enable() - } -} diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3Test.groovy b/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3Test.groovy deleted file mode 100644 index 9bfdf0fd2195..000000000000 --- a/instrumentation/rxjava/rxjava-3.0/library/src/test/groovy/RxJava3Test.groovy +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test -import io.opentelemetry.instrumentation.rxjava.v3_0.TracingAssembly -import io.opentelemetry.instrumentation.test.LibraryTestTrait -import spock.lang.Shared - -class RxJava3Test extends AbstractRxJava3Test implements LibraryTestTrait { - @Shared - TracingAssembly tracingAssembly = TracingAssembly.create() - - def setupSpec() { - tracingAssembly.enable() - } -} diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/test/java/Rx3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3.0/library/src/test/java/Rx3SubscriptionTest.java new file mode 100644 index 000000000000..a2d34deebbe2 --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.0/library/src/test/java/Rx3SubscriptionTest.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3SubscriptionTest; +import io.opentelemetry.instrumentation.rxjava.v3_0.TracingAssembly; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class Rx3SubscriptionTest extends AbstractRxJava3SubscriptionTest { + + @RegisterExtension + static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + static TracingAssembly tracingAssembly = TracingAssembly.create(); + + @BeforeAll + public static void setupSpec() { + tracingAssembly.enable(); + } +} diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3Test.java b/instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3Test.java new file mode 100644 index 000000000000..7b96033313aa --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3Test.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test; +import io.opentelemetry.instrumentation.rxjava.v3_0.TracingAssembly; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.LibraryTestRunner; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class RxJava3Test extends AbstractRxJava3Test { + @RegisterExtension + static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + static TracingAssembly tracingAssembly = TracingAssembly.create(); + private static final InstrumentationTestRunner RUNNER = LibraryTestRunner.instance(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + public InstrumentationTestRunner testRunner() { + return RUNNER; + } + + @BeforeAll + public void setupSpec() { + tracingAssembly.enable(); + } + + public InstrumentationTestRunner getTestRunner() { + return RUNNER; + } +} diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3ExtensionWithSpanTest.groovy b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3ExtensionWithSpanTest.groovy deleted file mode 100644 index e910848831e3..000000000000 --- a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3ExtensionWithSpanTest.groovy +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan -import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan - -class RxJava3ExtensionWithSpanTest extends AbstractRxJava3WithSpanTest { - - @Override - AbstractTracedWithSpan newTraced() { - return new TracedWithSpan() - } -} diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3InstrumentationWithSpanTest.groovy b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3InstrumentationWithSpanTest.groovy deleted file mode 100644 index 68938741d3b9..000000000000 --- a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3InstrumentationWithSpanTest.groovy +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan -import io.opentelemetry.instrumentation.rxjava.v3.common.instrumentationannotation.TracedWithSpan - -class RxJava3InstrumentationWithSpanTest extends AbstractRxJava3WithSpanTest { - - @Override - AbstractTracedWithSpan newTraced() { - return new TracedWithSpan() - } -} diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3SubscriptionTest.groovy b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3SubscriptionTest.groovy deleted file mode 100644 index b46f33bcc050..000000000000 --- a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3SubscriptionTest.groovy +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3SubscriptionTest -import io.opentelemetry.instrumentation.test.AgentTestTrait - -class RxJava3SubscriptionTest extends AbstractRxJava3SubscriptionTest implements AgentTestTrait { -} diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3Test.groovy b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3Test.groovy deleted file mode 100644 index 706aae82a6f9..000000000000 --- a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/groovy/RxJava3Test.groovy +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test -import io.opentelemetry.instrumentation.test.AgentTestTrait - -class RxJava3Test extends AbstractRxJava3Test implements AgentTestTrait { -} diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/Rx3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/Rx3SubscriptionTest.java new file mode 100644 index 000000000000..49b86d517e87 --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/Rx3SubscriptionTest.java @@ -0,0 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3SubscriptionTest; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class Rx3SubscriptionTest extends AbstractRxJava3SubscriptionTest { + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } +} diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java new file mode 100644 index 000000000000..99135062ce4e --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest; +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan; +import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan; +import io.opentelemetry.instrumentation.testing.AgentTestRunner; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class RxJava3ExtensionWithSpanTest extends AbstractRxJava3WithSpanTest { + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); + + @Override + protected AbstractTracedWithSpan newTraced() { + return new TracedWithSpan(); + } + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + protected InstrumentationTestRunner testRunner() { + return RUNNER; + } +} diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java new file mode 100644 index 000000000000..680bfabfcfb3 --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest; +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan; +import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan; +import io.opentelemetry.instrumentation.testing.AgentTestRunner; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class RxJava3InstrumentationWithSpanTest extends AbstractRxJava3WithSpanTest { + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); + + @Override + protected AbstractTracedWithSpan newTraced() { + return new TracedWithSpan(); + } + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + protected InstrumentationTestRunner testRunner() { + return RUNNER; + } +} diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3Test.java b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3Test.java new file mode 100644 index 000000000000..e49a6acf55cc --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3Test.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test; +import io.opentelemetry.instrumentation.testing.AgentTestRunner; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class RxJava3Test extends AbstractRxJava3Test { + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + protected InstrumentationTestRunner testRunner() { + return RUNNER; + } +} diff --git a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/groovy/RxJava3SubscriptionTest.groovy b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/groovy/RxJava3SubscriptionTest.groovy deleted file mode 100644 index aa0117118c15..000000000000 --- a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/groovy/RxJava3SubscriptionTest.groovy +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3SubscriptionTest -import io.opentelemetry.instrumentation.rxjava.v3_1_1.TracingAssembly -import io.opentelemetry.instrumentation.test.LibraryTestTrait -import spock.lang.Shared - -class RxJava3SubscriptionTest extends AbstractRxJava3SubscriptionTest implements LibraryTestTrait { - @Shared - TracingAssembly tracingAssembly = TracingAssembly.create() - - def setupSpec() { - tracingAssembly.enable() - } -} diff --git a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/groovy/RxJava3Test.groovy b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/groovy/RxJava3Test.groovy deleted file mode 100644 index a479bec24fd4..000000000000 --- a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/groovy/RxJava3Test.groovy +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test -import io.opentelemetry.instrumentation.rxjava.v3_1_1.TracingAssembly -import io.opentelemetry.instrumentation.test.LibraryTestTrait -import spock.lang.Shared - -class RxJava3Test extends AbstractRxJava3Test implements LibraryTestTrait { - @Shared - TracingAssembly tracingAssembly = TracingAssembly.create() - - def setupSpec() { - tracingAssembly.enable() - } -} diff --git a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/Rx3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/Rx3SubscriptionTest.java new file mode 100644 index 000000000000..42ea148c6354 --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/Rx3SubscriptionTest.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3SubscriptionTest; +import io.opentelemetry.instrumentation.rxjava.v3_1_1.TracingAssembly; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class Rx3SubscriptionTest extends AbstractRxJava3SubscriptionTest { + + @RegisterExtension + static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + static TracingAssembly tracingAssembly = TracingAssembly.create(); + + @BeforeAll + public static void setupSpec() { + tracingAssembly.enable(); + } +} diff --git a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3Test.java b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3Test.java new file mode 100644 index 000000000000..43343a9b569c --- /dev/null +++ b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3Test.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test; +import io.opentelemetry.instrumentation.rxjava.v3_1_1.TracingAssembly; +import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.LibraryTestRunner; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class RxJava3Test extends AbstractRxJava3Test { + @RegisterExtension + static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); + + static TracingAssembly tracingAssembly = TracingAssembly.create(); + private static final InstrumentationTestRunner RUNNER = LibraryTestRunner.instance(); + + @Override + protected InstrumentationExtension testing() { + return testing; + } + + @Override + public InstrumentationTestRunner testRunner() { + return RUNNER; + } + + @BeforeAll + public void setupSpec() { + tracingAssembly.enable(); + } + + public InstrumentationTestRunner getTestRunner() { + return RUNNER; + } +} From da171e6be03a0e0cedd301d34ae8a01e1aa666f2 Mon Sep 17 00:00:00 2001 From: Kaibo Cai Date: Sun, 2 Apr 2023 13:09:55 -0500 Subject: [PATCH 2/5] fix test fix more tests fix comments - convert missed groovy tests --- .../reactor/AbstractReactorCoreTest.java | 17 - ...xJava3AsyncOperationEndStrategyTest.groovy | 1045 ----------------- .../RxJava3AsyncOperationEndStrategyTest.java | 954 +++++++++++++++ .../AbstractRxJava3SubscriptionTest.java | 5 +- .../rxjava/v3/common/AbstractRxJava3Test.java | 44 +- .../common/AbstractRxJava3WithSpanTest.java | 63 +- .../common/RxJava3ConcurrencyTestHelper.java | 8 +- .../java/RxJava3ExtensionWithSpanTest.java | 9 - .../RxJava3InstrumentationWithSpanTest.java | 9 - .../javaagent/src/test/java/RxJava3Test.java | 9 - .../library/src/test/java/RxJava3Test.java | 12 - .../java/RxJava3ExtensionWithSpanTest.java | 9 - .../RxJava3InstrumentationWithSpanTest.java | 9 - .../javaagent/src/test/java/RxJava3Test.java | 9 - .../library/src/test/java/RxJava3Test.java | 12 - 15 files changed, 1014 insertions(+), 1200 deletions(-) delete mode 100644 instrumentation/rxjava/rxjava-3-common/library/src/test/groovy/RxJava3AsyncOperationEndStrategyTest.groovy create mode 100644 instrumentation/rxjava/rxjava-3-common/library/src/test/java/RxJava3AsyncOperationEndStrategyTest.java diff --git a/instrumentation/reactor/reactor-3.1/testing/src/main/java/io/opentelemetry/instrumentation/reactor/AbstractReactorCoreTest.java b/instrumentation/reactor/reactor-3.1/testing/src/main/java/io/opentelemetry/instrumentation/reactor/AbstractReactorCoreTest.java index 51601291c268..e1c64f46717a 100644 --- a/instrumentation/reactor/reactor-3.1/testing/src/main/java/io/opentelemetry/instrumentation/reactor/AbstractReactorCoreTest.java +++ b/instrumentation/reactor/reactor-3.1/testing/src/main/java/io/opentelemetry/instrumentation/reactor/AbstractReactorCoreTest.java @@ -9,7 +9,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.google.common.primitives.Ints; import io.opentelemetry.api.trace.Span; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.sdk.testing.assertj.TraceAssert; @@ -116,22 +115,6 @@ void basicFlux() { span -> span.hasName("add one").hasParent(trace.getSpan(0)))); } - @Test - void basicFluxIterable() { - List result = - testing.runWithSpan( - "parent", - () -> Flux.fromIterable(Ints.asList(5, 6)).map(this::addOne).collectList().block()); - assertThat(result).containsExactly(6, 7); - - testing.waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> span.hasName("parent").hasNoParent(), - span -> span.hasName("add one").hasParent(trace.getSpan(0)), - span -> span.hasName("add one").hasParent(trace.getSpan(0)))); - } - @Test void twoOperationsFlux() { List result = diff --git a/instrumentation/rxjava/rxjava-3-common/library/src/test/groovy/RxJava3AsyncOperationEndStrategyTest.groovy b/instrumentation/rxjava/rxjava-3-common/library/src/test/groovy/RxJava3AsyncOperationEndStrategyTest.groovy deleted file mode 100644 index c3c174396b8e..000000000000 --- a/instrumentation/rxjava/rxjava-3-common/library/src/test/groovy/RxJava3AsyncOperationEndStrategyTest.groovy +++ /dev/null @@ -1,1045 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.api.trace.Span -import io.opentelemetry.context.Context -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter -import io.opentelemetry.instrumentation.rxjava.v3.common.RxJava3AsyncOperationEndStrategy -import io.reactivex.rxjava3.core.Completable -import io.reactivex.rxjava3.core.Flowable -import io.reactivex.rxjava3.core.Maybe -import io.reactivex.rxjava3.core.Observable -import io.reactivex.rxjava3.core.Single -import io.reactivex.rxjava3.observers.TestObserver -import io.reactivex.rxjava3.parallel.ParallelFlowable -import io.reactivex.rxjava3.processors.ReplayProcessor -import io.reactivex.rxjava3.processors.UnicastProcessor -import io.reactivex.rxjava3.subjects.CompletableSubject -import io.reactivex.rxjava3.subjects.MaybeSubject -import io.reactivex.rxjava3.subjects.ReplaySubject -import io.reactivex.rxjava3.subjects.SingleSubject -import io.reactivex.rxjava3.subjects.UnicastSubject -import io.reactivex.rxjava3.subscribers.TestSubscriber -import org.reactivestreams.Publisher -import org.reactivestreams.Subscriber -import org.reactivestreams.Subscription -import spock.lang.Specification - -class RxJava3AsyncOperationEndStrategyTest extends Specification { - String request = "request" - String response = "response" - - Instrumenter instrumenter - - Context context - - Span span - - def underTest = RxJava3AsyncOperationEndStrategy.create() - - def underTestWithExperimentalAttributes = RxJava3AsyncOperationEndStrategy.builder() - .setCaptureExperimentalSpanAttributes(true) - .build() - - void setup() { - instrumenter = Mock() - context = Mock() - span = Mock() - span.storeInContext(_) >> { callRealMethod() } - } - - static class CompletableTest extends RxJava3AsyncOperationEndStrategyTest { - def "is supported"() { - expect: - underTest.supports(Completable) - } - - def "ends span on already completed"() { - given: - def observer = new TestObserver() - - when: - def result = (Completable) underTest.end(instrumenter, context, request, Completable.complete(), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, null, null) - observer.assertComplete() - } - - def "ends span on already errored"() { - given: - def exception = new IllegalStateException() - def observer = new TestObserver() - - when: - def result = (Completable) underTest.end(instrumenter, context, request, Completable.error(exception), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when completed"() { - given: - def source = CompletableSubject.create() - def observer = new TestObserver() - - when: - def result = (Completable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onComplete() - - then: - 1 * instrumenter.end(context, request, null, null) - observer.assertComplete() - } - - def "ends span when errored"() { - given: - def exception = new IllegalStateException() - def source = CompletableSubject.create() - def observer = new TestObserver() - - when: - def result = (Completable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onError(exception) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when cancelled"() { - given: - def source = CompletableSubject.create() - def observer = new TestObserver() - def context = span.storeInContext(Context.root()) - - when: - def result = (Completable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - 0 * span._ - - when: - observer.dispose() - - then: - 1 * instrumenter.end(context, request, null, null) - 0 * span.setAttribute(_) - } - - def "ends span when cancelled and capturing experimental span attributes"() { - given: - def source = CompletableSubject.create() - def observer = new TestObserver() - def context = span.storeInContext(Context.root()) - - when: - def result = (Completable) underTestWithExperimentalAttributes.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - 0 * span._ - - when: - observer.dispose() - - then: - 1 * instrumenter.end(context, request, null, null) - 1 * span.setAttribute({ it.getKey() == "rxjava.canceled" }, true) - } - - def "ends span once for multiple subscribers"() { - given: - def source = CompletableSubject.create() - def observer1 = new TestObserver() - def observer2 = new TestObserver() - def observer3 = new TestObserver() - - when: - def result = (Completable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer1) - result.subscribe(observer2) - result.subscribe(observer3) - - then: - 0 * instrumenter._ - - when: - source.onComplete() - - then: - 1 * instrumenter.end(context, request, null, null) - observer1.assertComplete() - observer2.assertComplete() - observer3.assertComplete() - } - } - - static class MaybeTest extends RxJava3AsyncOperationEndStrategyTest { - def "is supported"() { - expect: - underTest.supports(Maybe) - } - - def "ends span on already completed"() { - given: - def observer = new TestObserver() - - when: - def result = (Maybe) underTest.end(instrumenter, context, request, Maybe.just(response), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, response, null) - observer.assertComplete() - } - - def "ends span on already empty"() { - given: - def observer = new TestObserver() - - when: - def result = (Maybe) underTest.end(instrumenter, context, request, Maybe.empty(), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, null, null) - observer.assertComplete() - } - - def "ends span on already errored"() { - given: - def exception = new IllegalStateException() - def observer = new TestObserver() - - when: - def result = (Maybe) underTest.end(instrumenter, context, request, Maybe.error(exception), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when completed"() { - given: - def source = MaybeSubject.create() - def observer = new TestObserver() - - when: - def result = (Maybe) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onSuccess(response) - - then: - 1 * instrumenter.end(context, request, response, null) - observer.assertComplete() - } - - def "ends span when empty"() { - given: - def source = MaybeSubject.create() - def observer = new TestObserver() - - when: - def result = (Maybe) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onComplete() - - then: - 1 * instrumenter.end(context, request, null, null) - observer.assertComplete() - } - - def "ends span when errored"() { - given: - def exception = new IllegalStateException() - def source = MaybeSubject.create() - def observer = new TestObserver() - - when: - def result = (Maybe) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onError(exception) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when cancelled"() { - given: - def source = MaybeSubject.create() - def observer = new TestObserver() - def context = span.storeInContext(Context.root()) - - when: - def result = (Maybe) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - observer.dispose() - - then: - 1 * instrumenter.end(context, request, null, null) - 0 * span.setAttribute(_) - } - - def "ends span when cancelled and capturing experimental span attributes"() { - given: - def source = MaybeSubject.create() - def observer = new TestObserver() - def context = span.storeInContext(Context.root()) - - when: - def result = (Maybe) underTestWithExperimentalAttributes.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - 0 * span._ - - when: - observer.dispose() - - then: - 1 * instrumenter.end(context, request, null, null) - 1 * span.setAttribute({ it.getKey() == "rxjava.canceled" }, true) - } - - def "ends span once for multiple subscribers"() { - given: - def source = MaybeSubject.create() - def observer1 = new TestObserver() - def observer2 = new TestObserver() - def observer3 = new TestObserver() - - when: - def result = (Maybe) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer1) - result.subscribe(observer2) - result.subscribe(observer3) - - then: - 0 * instrumenter._ - - when: - source.onSuccess(response) - - then: - 1 * instrumenter.end(context, request, response, null) - observer1.assertValue(response) - observer1.assertComplete() - observer2.assertValue(response) - observer2.assertComplete() - observer3.assertValue(response) - observer3.assertComplete() - } - } - - static class SingleTest extends RxJava3AsyncOperationEndStrategyTest { - def "is supported"() { - expect: - underTest.supports(Single) - } - - def "ends span on already completed"() { - given: - def observer = new TestObserver() - - when: - def result = (Single) underTest.end(instrumenter, context, request, Single.just(response), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, response, null) - observer.assertComplete() - } - - def "ends span on already errored"() { - given: - def exception = new IllegalStateException() - def observer = new TestObserver() - - when: - def result = (Single) underTest.end(instrumenter, context, request, Single.error(exception), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when completed"() { - given: - def source = SingleSubject.create() - def observer = new TestObserver() - - when: - def result = (Single) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onSuccess(response) - - then: - 1 * instrumenter.end(context, request, response, null) - observer.assertComplete() - } - - def "ends span when errored"() { - given: - def exception = new IllegalStateException() - def source = SingleSubject.create() - def observer = new TestObserver() - - when: - def result = (Single) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onError(exception) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when cancelled"() { - given: - def source = SingleSubject.create() - def observer = new TestObserver() - def context = span.storeInContext(Context.root()) - - when: - def result = (Single) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - observer.dispose() - - then: - 1 * instrumenter.end(context, request, null, null) - 0 * span.setAttribute(_) - } - - def "ends span when cancelled and capturing experimental span attributes"() { - given: - def source = SingleSubject.create() - def observer = new TestObserver() - def context = span.storeInContext(Context.root()) - - when: - def result = (Single) underTestWithExperimentalAttributes.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - 0 * span._ - - when: - observer.dispose() - - then: - 1 * instrumenter.end(context, request, null, null) - 1 * span.setAttribute({ it.getKey() == "rxjava.canceled" }, true) - } - - def "ends span once for multiple subscribers"() { - given: - def source = SingleSubject.create() - def observer1 = new TestObserver() - def observer2 = new TestObserver() - def observer3 = new TestObserver() - - when: - def result = (Single) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer1) - result.subscribe(observer2) - result.subscribe(observer3) - - then: - 0 * instrumenter._ - - when: - source.onSuccess(response) - - then: - 1 * instrumenter.end(context, request, response, null) - observer1.assertValue(response) - observer1.assertComplete() - observer2.assertValue(response) - observer2.assertComplete() - observer3.assertValue(response) - observer3.assertComplete() - } - } - - static class ObservableTest extends RxJava3AsyncOperationEndStrategyTest { - def "is supported"() { - expect: - underTest.supports(Observable) - } - - def "ends span on already completed"() { - given: - def observer = new TestObserver() - - when: - def result = (Observable) underTest.end(instrumenter, context, request, Observable.just(response), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, null, null) - observer.assertComplete() - } - - def "ends span on already errored"() { - given: - def exception = new IllegalStateException() - def observer = new TestObserver() - - when: - def result = (Observable) underTest.end(instrumenter, context, request, Observable.error(exception), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when completed"() { - given: - def source = UnicastSubject.create() - def observer = new TestObserver() - - when: - def result = (Observable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onComplete() - - then: - 1 * instrumenter.end(context, request, null, null) - observer.assertComplete() - } - - def "ends span when errored"() { - given: - def exception = new IllegalStateException() - def source = UnicastSubject.create() - def observer = new TestObserver() - - when: - def result = (Observable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onError(exception) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when cancelled"() { - given: - def source = UnicastSubject.create() - def observer = new TestObserver() - def context = span.storeInContext(Context.root()) - - when: - def result = (Observable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - observer.dispose() - - then: - 1 * instrumenter.end(context, request, null, null) - 0 * span.setAttribute(_) - } - - def "ends span when cancelled and capturing experimental span attributes"() { - given: - def source = UnicastSubject.create() - def observer = new TestObserver() - def context = span.storeInContext(Context.root()) - - when: - def result = (Observable) underTestWithExperimentalAttributes.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - 0 * span._ - - when: - observer.dispose() - - then: - 1 * instrumenter.end(context, request, null, null) - 1 * span.setAttribute({ it.getKey() == "rxjava.canceled" }, true) - } - - def "ends span once for multiple subscribers"() { - given: - def source = ReplaySubject.create() - def observer1 = new TestObserver() - def observer2 = new TestObserver() - def observer3 = new TestObserver() - - when: - def result = (Observable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer1) - result.subscribe(observer2) - result.subscribe(observer3) - - then: - 0 * instrumenter._ - - when: - source.onComplete() - - then: - 1 * instrumenter.end(context, request, null, null) - observer1.assertComplete() - observer2.assertComplete() - observer3.assertComplete() - } - } - - static class FlowableTest extends RxJava3AsyncOperationEndStrategyTest { - def "is supported"() { - expect: - underTest.supports(Flowable) - } - - def "ends span on already completed"() { - given: - def observer = new TestSubscriber() - - when: - def result = (Flowable) underTest.end(instrumenter, context, request, Flowable.just(response), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, null, null) - observer.assertComplete() - } - - def "ends span on already errored"() { - given: - def exception = new IllegalStateException() - def observer = new TestSubscriber() - - when: - def result = (Flowable) underTest.end(instrumenter, context, request, Flowable.error(exception), String) - result.subscribe(observer) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when completed"() { - given: - def source = UnicastProcessor.create() - def observer = new TestSubscriber() - - when: - def result = (Flowable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onComplete() - - then: - 1 * instrumenter.end(context, request, null, null) - observer.assertComplete() - } - - def "ends span when errored"() { - given: - def exception = new IllegalStateException() - def source = UnicastProcessor.create() - def observer = new TestSubscriber() - - when: - def result = (Flowable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onError(exception) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when cancelled"() { - given: - def source = UnicastProcessor.create() - def observer = new TestSubscriber() - def context = span.storeInContext(Context.root()) - - when: - def result = (Flowable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - observer.cancel() - - then: - 1 * instrumenter.end(context, request, null, null) - 0 * span.setAttribute(_) - } - - def "ends span when cancelled and capturing experimental span attributes"() { - given: - def source = UnicastProcessor.create() - def observer = new TestSubscriber() - def context = span.storeInContext(Context.root()) - - when: - def result = (Flowable) underTestWithExperimentalAttributes.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - 0 * span._ - - when: - observer.cancel() - - then: - 1 * instrumenter.end(context, request, null, null) - 1 * span.setAttribute({ it.getKey() == "rxjava.canceled" }, true) - } - - def "ends span once for multiple subscribers"() { - given: - def source = ReplayProcessor.create() - def observer1 = new TestSubscriber() - def observer2 = new TestSubscriber() - def observer3 = new TestSubscriber() - - when: - def result = (Flowable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer1) - result.subscribe(observer2) - result.subscribe(observer3) - - then: - 0 * instrumenter._ - - when: - source.onComplete() - - then: - 1 * instrumenter.end(context, request, null, null) - observer1.assertComplete() - observer2.assertComplete() - observer3.assertComplete() - } - } - - static class ParallelFlowableTest extends RxJava3AsyncOperationEndStrategyTest { - def "is supported"() { - expect: - underTest.supports(ParallelFlowable) - } - - def "ends span on already completed"() { - given: - def observer = new TestSubscriber() - - when: - def result = (ParallelFlowable) underTest.end(instrumenter, context, request, Flowable.just(response).parallel(), String) - result.sequential().subscribe(observer) - - then: - observer.assertComplete() - 1 * instrumenter.end(context, request, null, null) - } - - def "ends span on already errored"() { - given: - def exception = new IllegalStateException() - def observer = new TestSubscriber() - - when: - def result = (ParallelFlowable) underTest.end(instrumenter, context, request, Flowable.error(exception).parallel(), String) - result.sequential().subscribe(observer) - - then: - observer.assertError(exception) - 1 * instrumenter.end(context, request, null, exception) - } - - def "ends span when completed"() { - given: - def source = UnicastProcessor.create() - def observer = new TestSubscriber() - - when: - def result = (ParallelFlowable) underTest.end(instrumenter, context, request, source.parallel(), String) - result.sequential().subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onComplete() - - then: - observer.assertComplete() - 1 * instrumenter.end(context, request, null, null) - } - - def "ends span when errored"() { - given: - def exception = new IllegalStateException() - def source = UnicastProcessor.create() - def observer = new TestSubscriber() - - when: - def result = (ParallelFlowable) underTest.end(instrumenter, context, request, source.parallel(), String) - result.sequential().subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onError(exception) - - then: - observer.assertError(exception) - 1 * instrumenter.end(context, request, null, exception) - } - - def "ends span when cancelled"() { - given: - def source = UnicastProcessor.create() - def observer = new TestSubscriber() - def context = span.storeInContext(Context.root()) - - when: - def result = (ParallelFlowable) underTest.end(instrumenter, context, request, source.parallel(), String) - result.sequential().subscribe(observer) - - then: - 0 * instrumenter._ - - when: - observer.cancel() - - then: - 1 * instrumenter.end(context, request, null, null) - 0 * span.setAttribute(_) - } - - def "ends span when cancelled and capturing experimental span attributes"() { - given: - def source = UnicastProcessor.create() - def observer = new TestSubscriber() - def context = span.storeInContext(Context.root()) - - when: - def result = (ParallelFlowable) underTestWithExperimentalAttributes.end(instrumenter, context, request, source.parallel(), String) - result.sequential().subscribe(observer) - - then: - 0 * instrumenter._ - 0 * span._ - - when: - observer.cancel() - - then: - 1 * instrumenter.end(context, request, null, null) - 1 * span.setAttribute({ it.getKey() == "rxjava.canceled" }, true) - } - } - - static class PublisherTest extends RxJava3AsyncOperationEndStrategyTest { - def "is supported"() { - expect: - underTest.supports(Publisher) - } - - def "ends span when completed"() { - given: - def source = new CustomPublisher() - def observer = new TestSubscriber() - - when: - def result = (Flowable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onComplete() - - then: - 1 * instrumenter.end(context, request, null, null) - observer.assertComplete() - } - - def "ends span when errored"() { - given: - def exception = new IllegalStateException() - def source = new CustomPublisher() - def observer = new TestSubscriber() - - when: - def result = (Flowable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - source.onError(exception) - - then: - 1 * instrumenter.end(context, request, null, exception) - observer.assertError(exception) - } - - def "ends span when cancelled"() { - given: - def source = new CustomPublisher() - def observer = new TestSubscriber() - def context = span.storeInContext(Context.root()) - - when: - def result = (Flowable) underTest.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - - when: - observer.cancel() - - then: - 1 * instrumenter.end(context, request, null, null) - 0 * span.setAttribute(_) - } - - def "ends span when cancelled and capturing experimental span attributes"() { - given: - def source = new CustomPublisher() - def observer = new TestSubscriber() - def context = span.storeInContext(Context.root()) - - when: - def result = (Flowable) underTestWithExperimentalAttributes.end(instrumenter, context, request, source, String) - result.subscribe(observer) - - then: - 0 * instrumenter._ - 0 * span._ - - when: - observer.cancel() - - then: - 1 * instrumenter.end(context, request, null, null) - 1 * span.setAttribute({ it.getKey() == "rxjava.canceled" }, true) - } - } - - static class CustomPublisher implements Publisher, Subscription { - Subscriber subscriber - - @Override - void subscribe(Subscriber subscriber) { - this.subscriber = subscriber - subscriber.onSubscribe(this) - } - - def onComplete() { - this.subscriber.onComplete() - } - - def onError(Throwable exception) { - this.subscriber.onError(exception) - } - - @Override - void request(long l) {} - - @Override - void cancel() {} - } -} diff --git a/instrumentation/rxjava/rxjava-3-common/library/src/test/java/RxJava3AsyncOperationEndStrategyTest.java b/instrumentation/rxjava/rxjava-3-common/library/src/test/java/RxJava3AsyncOperationEndStrategyTest.java new file mode 100644 index 000000000000..5e235e2cc34c --- /dev/null +++ b/instrumentation/rxjava/rxjava-3-common/library/src/test/java/RxJava3AsyncOperationEndStrategyTest.java @@ -0,0 +1,954 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.annotation.support.async.AsyncOperationEndStrategy; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.rxjava.v3.common.RxJava3AsyncOperationEndStrategy; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.Maybe; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.observers.TestObserver; +import io.reactivex.rxjava3.parallel.ParallelFlowable; +import io.reactivex.rxjava3.processors.ReplayProcessor; +import io.reactivex.rxjava3.processors.UnicastProcessor; +import io.reactivex.rxjava3.subjects.CompletableSubject; +import io.reactivex.rxjava3.subjects.MaybeSubject; +import io.reactivex.rxjava3.subjects.ReplaySubject; +import io.reactivex.rxjava3.subjects.SingleSubject; +import io.reactivex.rxjava3.subjects.UnicastSubject; +import io.reactivex.rxjava3.subscribers.TestSubscriber; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; + +@ExtendWith(MockitoExtension.class) +public class RxJava3AsyncOperationEndStrategyTest { + private static final AttributeKey CANCELED_ATTRIBUTE_KEY = + AttributeKey.booleanKey("rxjava.canceled"); + @Mock Instrumenter instrumenter; + @Mock Span span; + private final AsyncOperationEndStrategy underTest = RxJava3AsyncOperationEndStrategy.create(); + private final RxJava3AsyncOperationEndStrategy underTestWithExperimentalAttributes = + RxJava3AsyncOperationEndStrategy.builder().setCaptureExperimentalSpanAttributes(true).build(); + + @Nested + class CompletableTest { + @Test + void supported() { + assertThat(underTest.supports(Completable.class)).isTrue(); + } + + @Test + void endsSpanOnAlreadyCompleted() { + Completable result = + (Completable) + underTest.end( + instrumenter, Context.root(), "request", Completable.complete(), String.class); + TestObserver observer = result.test(); + + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + + @Test + void endsSpanOnAlreadyErrored() { + IllegalStateException exception = new IllegalStateException(); + + Completable result = + (Completable) + underTest.end( + instrumenter, + Context.root(), + "request", + Completable.error(exception), + String.class); + TestObserver observer = result.test(); + + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsSpanWhenCompleted() { + CompletableSubject source = CompletableSubject.create(); + + Completable result = + (Completable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onComplete(); + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + + @Test + void endsSpanWhenErrored() { + IllegalStateException exception = new IllegalStateException(); + CompletableSubject source = CompletableSubject.create(); + + Completable result = + (Completable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onError(exception); + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsWhenCancelled() { + when(span.storeInContext(any())).thenCallRealMethod(); + CompletableSubject source = CompletableSubject.create(); + Context context = Context.root().with(span); + + Completable result = + (Completable) underTest.end(instrumenter, context, "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + observer.dispose(); + verify(instrumenter).end(context, "request", null, null); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + } + + @Test + void endsSpanWhenCancelledExperimentalAttribute() { + when(span.storeInContext(any())).thenCallRealMethod(); + CompletableSubject source = CompletableSubject.create(); + Context context = Context.root().with(span); + + Completable result = + (Completable) + underTestWithExperimentalAttributes.end( + instrumenter, context, "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + + observer.dispose(); + + verify(instrumenter).end(context, "request", null, null); + verify(span).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + } + + @Test + void endsSpanOnceForMultipleSubscribers() { + CompletableSubject source = CompletableSubject.create(); + TestObserver observer1 = new TestObserver<>(); + TestObserver observer2 = new TestObserver<>(); + TestObserver observer3 = new TestObserver<>(); + + Completable result = + (Completable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + result.subscribe(observer1); + result.subscribe(observer2); + result.subscribe(observer3); + + verifyNoInteractions(instrumenter); + + source.onComplete(); + observer1.assertComplete(); + observer2.assertComplete(); + observer3.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + } + + @Nested + class MaybeTest { + @Test + void supported() { + assertThat(underTest.supports(Maybe.class)).isTrue(); + } + + @Test + void endsSpanOnAlreadyCompleted() { + UnicastProcessor source = UnicastProcessor.create(); + Maybe maybe = source.firstElement(); + + Maybe result = + (Maybe) underTest.end(instrumenter, Context.root(), "request", maybe, String.class); + TestObserver observer = result.test(); + + source.onNext("response"); + source.onComplete(); + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", "response", null); + } + + @Test + void endsSpanOnAlreadyEmpty() { + Maybe result = + (Maybe) + underTest.end(instrumenter, Context.root(), "request", Maybe.empty(), String.class); + TestObserver observer = result.test(); + + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + + @Test + void endsSpanOnAlreadyErrored() { + IllegalStateException exception = new IllegalStateException(); + + Maybe result = + (Maybe) + underTest.end( + instrumenter, Context.root(), "request", Maybe.error(exception), String.class); + TestObserver observer = result.test(); + + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsSpanWhenCompleted() { + MaybeSubject source = MaybeSubject.create(); + + Maybe result = + (Maybe) underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onSuccess("response"); + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", "response", null); + } + + @Test + void endsSpanWhenEmpty() { + MaybeSubject source = MaybeSubject.create(); + + Maybe result = + (Maybe) underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onComplete(); + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + + @Test + void endsSpanWhenErrored() { + IllegalStateException exception = new IllegalStateException(); + MaybeSubject source = MaybeSubject.create(); + + Maybe result = + (Maybe) underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer = result.test(); + + source.onError(exception); + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsSpanWhenCancelled() { + when(span.storeInContext(any())).thenCallRealMethod(); + MaybeSubject source = MaybeSubject.create(); + Context context = Context.root().with(span); + + Maybe result = + (Maybe) underTest.end(instrumenter, context, "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + observer.dispose(); + + verify(instrumenter).end(context, "request", null, null); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + } + + @Test + void endsSpanWhenCancelledExperimentalAttributes() { + when(span.storeInContext(any())).thenCallRealMethod(); + MaybeSubject source = MaybeSubject.create(); + Context context = Context.root().with(span); + + Maybe result = + (Maybe) + underTestWithExperimentalAttributes.end( + instrumenter, context, "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + + observer.dispose(); + + verify(instrumenter).end(context, "request", null, null); + verify(span).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + } + + @Test + void endsSpanOnceForMultipleSubscribers() { + MaybeSubject source = MaybeSubject.create(); + + Maybe result = + (Maybe) underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer1 = result.test(); + TestObserver observer2 = result.test(); + TestObserver observer3 = result.test(); + + verifyNoInteractions(instrumenter); + + source.onSuccess("response"); + + observer1.assertComplete(); + observer1.assertValue(value -> value.equals("response")); + observer2.assertComplete(); + observer2.assertValue(value -> value.equals("response")); + observer3.assertComplete(); + observer3.assertValue(value -> value.equals("response")); + verify(instrumenter).end(Context.root(), "request", "response", null); + } + } + + @Nested + class SingleTest { + @Test + void supported() { + assertThat(underTest.supports(Single.class)).isTrue(); + } + + @Test + void endsSpanOnAlreadyCompleted() { + Single result = + (Single) + underTest.end( + instrumenter, Context.root(), "request", Single.just("response"), String.class); + TestObserver observer = result.test(); + + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", "response", null); + } + + @Test + void endsSpanOnAlreadyErrored() { + IllegalStateException exception = new IllegalStateException(); + + Single result = + (Single) + underTest.end( + instrumenter, Context.root(), "request", Single.error(exception), String.class); + TestObserver observer = result.test(); + + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsSpanWhenCompleted() { + SingleSubject source = SingleSubject.create(); + + Single result = + (Single) underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onSuccess("response"); + + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", "response", null); + } + + @Test + void endsSpanWhenErrored() { + IllegalStateException exception = new IllegalStateException(); + SingleSubject source = SingleSubject.create(); + + Single result = + (Single) underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onError(exception); + + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsSpanWhenCancelled() { + when(span.storeInContext(any())).thenCallRealMethod(); + SingleSubject source = SingleSubject.create(); + Context context = Context.root().with(span); + + Single result = + (Single) underTest.end(instrumenter, context, "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + observer.dispose(); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(instrumenter).end(context, "request", null, null); + } + + @Test + void endsSpanWhenCancelledExperimentalAttributes() { + when(span.storeInContext(any())).thenCallRealMethod(); + SingleSubject source = SingleSubject.create(); + Context context = Context.root().with(span); + + Single result = + (Single) + underTestWithExperimentalAttributes.end( + instrumenter, context, "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + + observer.dispose(); + + verify(instrumenter).end(context, "request", null, null); + verify(span).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + } + + @Test + void endsSpanOnceForMultipleSubscribers() { + SingleSubject source = SingleSubject.create(); + + Single result = + (Single) underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer1 = result.test(); + TestObserver observer2 = result.test(); + TestObserver observer3 = result.test(); + + verifyNoInteractions(instrumenter); + + source.onSuccess("response"); + + observer1.assertValue(value -> value.equals("response")); + observer1.assertComplete(); + observer2.assertValue(value -> value.equals("response")); + observer2.assertComplete(); + observer3.assertValue(value -> value.equals("response")); + observer3.assertComplete(); + verify(instrumenter).end(Context.root(), "request", "response", null); + } + } + + @Nested + class ObservableTest { + @Test + void supported() { + assertThat(underTest.supports(Observable.class)).isTrue(); + } + + @Test + void endsSpanOnAlreadyCompleted() { + Observable result = + (Observable) + underTest.end( + instrumenter, + Context.root(), + "request", + Observable.just("response"), + String.class); + TestObserver observer = result.test(); + + verify(instrumenter).end(Context.root(), "request", null, null); + observer.assertComplete(); + } + + @Test + void endsSpanOnAlreadyErrored() { + IllegalStateException exception = new IllegalStateException(); + + Observable result = + (Observable) + underTest.end( + instrumenter, + Context.root(), + "request", + Observable.error(exception), + String.class); + TestObserver observer = result.test(); + + verify(instrumenter).end(Context.root(), "request", null, exception); + observer.assertError(exception); + } + + @Test + void endsSpanWhenCompleted() { + UnicastSubject source = UnicastSubject.create(); + + Observable result = + (Observable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onComplete(); + + verify(instrumenter).end(Context.root(), "request", null, null); + observer.assertComplete(); + } + + @Test + void endsSpanWhenErrored() { + IllegalStateException exception = new IllegalStateException(); + UnicastSubject source = UnicastSubject.create(); + + Observable result = + (Observable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onError(exception); + + verify(instrumenter).end(Context.root(), "request", null, exception); + observer.assertError(exception); + } + + @Test + void endsOnWhenCancelled() { + when(span.storeInContext(any())).thenCallRealMethod(); + UnicastSubject source = UnicastSubject.create(); + Context context = Context.root().with(span); + + Observable result = + (Observable) underTest.end(instrumenter, context, "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + + observer.dispose(); + + verify(instrumenter).end(context, "request", null, null); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + } + + @Test + void endsSpanWhenCancelledExperimentalAttributes() { + when(span.storeInContext(any())).thenCallRealMethod(); + UnicastSubject source = UnicastSubject.create(); + Context context = Context.root().with(span); + + Observable result = + (Observable) + underTestWithExperimentalAttributes.end( + instrumenter, context, "request", source, String.class); + TestObserver observer = result.test(); + + verifyNoInteractions(instrumenter); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + + observer.dispose(); + + verify(instrumenter).end(context, "request", null, null); + verify(span).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + } + + @Test + void endsSpanOnceForMultipleSubscribers() { + ReplaySubject source = ReplaySubject.create(); + + Observable result = + (Observable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestObserver observer1 = result.test(); + TestObserver observer2 = result.test(); + TestObserver observer3 = result.test(); + + verifyNoInteractions(instrumenter); + + source.onComplete(); + + observer1.assertComplete(); + observer2.assertComplete(); + observer3.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + } + + @Nested + class FlowableTest { + @Test + void supported() { + assertThat(underTest.supports(Flowable.class)).isTrue(); + } + + @Test + void endsSpanOnAlreadyCompleted() { + Flowable result = + (Flowable) + underTest.end( + instrumenter, Context.root(), "request", Flowable.just("response"), String.class); + TestSubscriber observer = result.test(); + + verify(instrumenter).end(Context.root(), "request", null, null); + observer.assertComplete(); + } + + @Test + void endsOnAlreadyErrored() { + IllegalStateException exception = new IllegalStateException(); + + Flowable result = + (Flowable) + underTest.end( + instrumenter, Context.root(), "request", Flowable.error(exception), String.class); + TestSubscriber observer = result.test(); + + verify(instrumenter).end(Context.root(), "request", null, exception); + observer.assertError(exception); + } + + @Test + void endsSpanWhenCompleted() { + UnicastProcessor source = UnicastProcessor.create(); + + Flowable result = + (Flowable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestSubscriber observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onComplete(); + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + + @Test + void endsOnWhenErrored() { + IllegalStateException exception = new IllegalStateException(); + UnicastProcessor source = UnicastProcessor.create(); + + Flowable result = + (Flowable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestSubscriber observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onError(exception); + + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsSpanWhenCancelled() { + when(span.storeInContext(any())).thenCallRealMethod(); + UnicastProcessor source = UnicastProcessor.create(); + Context context = Context.root().with(span); + + Flowable result = + (Flowable) underTest.end(instrumenter, context, "request", source, String.class); + TestSubscriber observer = result.test(); + + verifyNoInteractions(instrumenter); + + observer.cancel(); + + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(instrumenter).end(context, "request", null, null); + } + + @Test + void endsSpanWhenCancelledExperimentalAttributes() { + when(span.storeInContext(any())).thenCallRealMethod(); + UnicastProcessor source = UnicastProcessor.create(); + Context context = Context.root().with(span); + + Flowable result = + (Flowable) + underTestWithExperimentalAttributes.end( + instrumenter, context, "request", source, String.class); + TestSubscriber observer = result.test(); + + verifyNoInteractions(instrumenter); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + + observer.cancel(); + + verify(span).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(instrumenter).end(context, "request", null, null); + } + + @Test + void endsSpanOnceForMultipleSubscribers() { + ReplayProcessor source = ReplayProcessor.create(); + + Flowable result = + (Flowable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestSubscriber observer1 = result.test(); + TestSubscriber observer2 = result.test(); + TestSubscriber observer3 = result.test(); + + verifyNoInteractions(instrumenter); + + source.onComplete(); + observer1.assertComplete(); + observer2.assertComplete(); + observer3.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + } + + @Nested + class ParallelFlowableTest { + @Test + void supported() { + assertThat(underTest.supports(ParallelFlowable.class)).isTrue(); + } + + @Test + void endsSpanOnAlreadyCompleted() { + ParallelFlowable result = + (ParallelFlowable) + underTest.end( + instrumenter, + Context.root(), + "request", + Flowable.just("response").parallel(), + String.class); + TestSubscriber observer = result.sequential().test(); + + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + + @Test + void endsSpanOnAlreadyErrored() { + IllegalStateException exception = new IllegalStateException(); + + ParallelFlowable result = + (ParallelFlowable) + underTest.end( + instrumenter, + Context.root(), + "request", + Flowable.error(exception).parallel(), + String.class); + TestSubscriber observer = result.sequential().test(); + + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsSpanWhenCompleted() { + UnicastProcessor source = UnicastProcessor.create(); + + ParallelFlowable result = + (ParallelFlowable) + underTest.end( + instrumenter, Context.root(), "request", source.parallel(), String.class); + TestSubscriber observer = result.sequential().test(); + + verifyNoInteractions(instrumenter); + + source.onComplete(); + + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + + @Test + void endsSpanWhenErrored() { + IllegalStateException exception = new IllegalStateException(); + UnicastProcessor source = UnicastProcessor.create(); + + ParallelFlowable result = + (ParallelFlowable) + underTest.end( + instrumenter, Context.root(), "request", source.parallel(), String.class); + TestSubscriber observer = result.sequential().test(); + + verifyNoInteractions(instrumenter); + + source.onError(exception); + + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsSpanWhenCancelled() { + when(span.storeInContext(any())).thenCallRealMethod(); + UnicastProcessor source = UnicastProcessor.create(); + Context context = Context.root().with(span); + + ParallelFlowable result = + (ParallelFlowable) + underTest.end(instrumenter, context, "request", source.parallel(), String.class); + TestSubscriber observer = result.sequential().test(); + + verifyNoInteractions(instrumenter); + + observer.cancel(); + + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(instrumenter).end(context, "request", null, null); + } + + @Test + void endsSpanWhenCancelledExperimentalAttributes() { + when(span.storeInContext(any())).thenCallRealMethod(); + UnicastProcessor source = UnicastProcessor.create(); + Context context = Context.root().with(span); + + ParallelFlowable result = + (ParallelFlowable) + underTestWithExperimentalAttributes.end( + instrumenter, context, "request", source.parallel(), String.class); + TestSubscriber observer = result.sequential().test(); + + verifyNoInteractions(instrumenter); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + + observer.cancel(); + verify(span).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(instrumenter).end(context, "request", null, null); + } + } + + @Nested + class PublisherTest { + @Test + void supported() { + assertThat(underTest.supports(Publisher.class)).isTrue(); + } + + @Test + void endsSpanWhenCompleted() { + CustomPublisher source = new CustomPublisher(); + + Flowable result = + (Flowable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestSubscriber observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onComplete(); + + observer.assertComplete(); + verify(instrumenter).end(Context.root(), "request", null, null); + } + + @Test + void endsSpanWhenErrored() { + IllegalStateException exception = new IllegalStateException(); + CustomPublisher source = new CustomPublisher(); + + Flowable result = + (Flowable) + underTest.end(instrumenter, Context.root(), "request", source, String.class); + TestSubscriber observer = result.test(); + + verifyNoInteractions(instrumenter); + + source.onError(exception); + + observer.assertError(exception); + verify(instrumenter).end(Context.root(), "request", null, exception); + } + + @Test + void endsSpanWhenCancelled() { + when(span.storeInContext(any())).thenCallRealMethod(); + CustomPublisher source = new CustomPublisher(); + Context context = Context.root().with(span); + + Flowable result = + (Flowable) underTest.end(instrumenter, context, "request", source, String.class); + TestSubscriber observer = result.test(); + + verifyNoInteractions(instrumenter); + + observer.cancel(); + + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(instrumenter).end(context, "request", null, null); + } + + @Test + void endsSpanWhenCancelledExperimentalAttributes() { + when(span.storeInContext(any())).thenCallRealMethod(); + CustomPublisher source = new CustomPublisher(); + Context context = Context.root().with(span); + + Flowable result = + (Flowable) + underTestWithExperimentalAttributes.end( + instrumenter, context, "request", source, String.class); + TestSubscriber observer = result.test(); + + verifyNoInteractions(instrumenter); + verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + + observer.cancel(); + + verify(span).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(instrumenter).end(context, "request", null, null); + } + + class CustomPublisher implements Publisher, Subscription { + Subscriber subscriber; + + @Override + public void subscribe(Subscriber subscriber) { + this.subscriber = subscriber; + subscriber.onSubscribe(this); + } + + public void onComplete() { + this.subscriber.onComplete(); + } + + public void onError(Throwable exception) { + this.subscriber.onError(exception); + } + + @Override + public void request(long l) {} + + @Override + public void cancel() {} + } + } +} diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.java index d38ac0058937..c1962937a9b2 100644 --- a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.java +++ b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3SubscriptionTest.java @@ -41,7 +41,10 @@ public void subscriptionTest() throws InterruptedException { trace -> trace.hasSpansSatisfyingExactly( span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(), - span -> span.hasName("Connection.query").hasKind(SpanKind.INTERNAL))); + span -> + span.hasName("Connection.query") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); } static class Connection { diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java index 5609183b6242..e0742c1f17bd 100644 --- a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java +++ b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java @@ -12,7 +12,6 @@ import com.google.common.primitives.Ints; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable; import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier; @@ -42,16 +41,14 @@ @TestInstance(TestInstance.Lifecycle.PER_CLASS) public abstract class AbstractRxJava3Test { - protected abstract InstrumentationExtension testing(); - - protected abstract InstrumentationTestRunner testRunner(); - private static final String EXCEPTION_MESSAGE = "test exception"; private static final String PARENT = "publisher-parent"; private static final String ADD_ONE = "addOne"; private static final String ADD_TWO = "addTwo"; - private static Stream provideParameters() { + protected abstract InstrumentationExtension testing(); + + private static Stream schedulers() { return Stream.of( Arguments.of(Schedulers.newThread()), Arguments.of(Schedulers.computation()), @@ -74,15 +71,14 @@ private T createParentSpan(ThrowingSupplier test) { private void createParentSpan(ThrowingRunnable test) { testing().runWithSpan(PARENT, test); } - // private T createParentSpan(ThrowingSupplier test) { - // OpenTelemetry. - // } private enum CancellingSubscriber implements Subscriber { INSTANCE; @Override - public void onSubscribe(Subscription subscription) {} + public void onSubscribe(Subscription subscription) { + subscription.cancel(); + } @Override public void onNext(Object o) {} @@ -503,7 +499,9 @@ public void basicFlowableFailure() { @Test public void basicMaybeCancel() { - createParentSpan(() -> Maybe.just(1).toFlowable().subscribe(CancellingSubscriber.INSTANCE)); + createParentSpan( + () -> + Maybe.just(1).map(this::addOne).toFlowable().subscribe(CancellingSubscriber.INSTANCE)); testing() .waitAndAssertTraces( trace -> @@ -527,7 +525,9 @@ public void basicFlowableCancel() { @Test public void basicSingleCancel() { - createParentSpan(() -> Single.just(1).toFlowable().subscribe(CancellingSubscriber.INSTANCE)); + createParentSpan( + () -> + Single.just(1).map(this::addOne).toFlowable().subscribe(CancellingSubscriber.INSTANCE)); testing() .waitAndAssertTraces( trace -> @@ -554,6 +554,7 @@ public void basicObservableCancel() { createParentSpan( () -> Observable.just(1) + .map(this::addOne) .toFlowable(BackpressureStrategy.LATEST) .subscribe(CancellingSubscriber.INSTANCE)); testing() @@ -632,9 +633,8 @@ public void basicFlowableChain() { // Publisher chain spans have the correct parents from subscription time @Test public void maybeChainParentSpan() { - testing() - .runWithSpan( - "trace-parent", () -> Maybe.just(42).map(this::addOne).map(this::addTwo).blockingGet()); + Maybe maybe = Maybe.just(42).map(this::addOne).map(this::addTwo); + testing().runWithSpan("trace-parent", () -> maybe.blockingGet()); testing() .waitAndAssertTraces( trace -> @@ -651,7 +651,7 @@ public void maybeChainParentSpan() { } @Test - public void maybeChainHasAssemblyContext() { + public void maybeChainHasSubscriptionContext() { Integer result = createParentSpan( () -> { @@ -681,7 +681,7 @@ public void maybeChainHasAssemblyContext() { } @Test - public void flowableChainHasAssemblyContext() { + public void flowableChainHasSubscriptionContext() { List result = createParentSpan( () -> { @@ -721,7 +721,7 @@ public void flowableChainHasAssemblyContext() { } @Test - public void singleChainHasAssemblyContext() { + public void singleChainHasSubscriptionContext() { Integer result = createParentSpan( () -> { @@ -751,7 +751,7 @@ public void singleChainHasAssemblyContext() { } @Test - public void observableChainHasAssemblyContext() { + public void observableChainHasSubscriptionContext() { List result = createParentSpan( () -> { @@ -782,7 +782,7 @@ public void observableChainHasAssemblyContext() { } @ParameterizedTest - @MethodSource("provideParameters") + @MethodSource("schedulers") public void flowableMultiResults(Scheduler scheduler) { List result = testing() @@ -822,10 +822,10 @@ public void flowableMultiResults(Scheduler scheduler) { } @ParameterizedTest - @MethodSource("provideParameters") + @MethodSource("schedulers") public void maybeMultipleTraceChains(Scheduler scheduler) { int iterations = 100; - RxJava3ConcurrencyTestHelper.launchAndWait(scheduler, iterations, 60000, testRunner()); + RxJava3ConcurrencyTestHelper.launchAndWait(scheduler, iterations, 60000, testing()); @SuppressWarnings("unchecked") Consumer[] assertions = (Consumer[]) new Consumer[iterations]; for (int i = 0; i < iterations; i++) { diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.java b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.java index 2b4d2490e5ad..1c0d50bd2dab 100644 --- a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.java +++ b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3WithSpanTest.java @@ -13,7 +13,6 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.sdk.trace.data.SpanData; import io.opentelemetry.sdk.trace.data.StatusData; @@ -43,8 +42,6 @@ public abstract class AbstractRxJava3WithSpanTest { protected abstract InstrumentationExtension testing(); - protected abstract InstrumentationTestRunner testRunner(); - @Test public void captureSpanForCompletedCompletable() { TestObserver observer = new TestObserver<>(); @@ -72,7 +69,7 @@ public void captureSpanForEventuallyCompletedCompletable() throws InterruptedExc // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onComplete(); @@ -122,7 +119,7 @@ public void captureSpanForEventuallyErrorCompletable() throws InterruptedExcepti // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onError(error); @@ -150,7 +147,7 @@ public void captureSpanForCanceledCompletable() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); observer.dispose(); @@ -215,7 +212,7 @@ public void captureSpanForEventuallyCompletedMaybe() throws InterruptedException // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onSuccess("Value"); @@ -266,7 +263,7 @@ public void captureSpanForEventuallyErrorMaybe() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onError(error); @@ -295,7 +292,7 @@ public void captureSpanForCanceledMaybe() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); observer.dispose(); @@ -341,7 +338,7 @@ public void captureSpanForEventuallyCompletedSingle() throws InterruptedExceptio // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onSuccess("Value"); @@ -392,7 +389,7 @@ public void captureSpanForEventuallyErrorSingle() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onError(error); @@ -421,7 +418,7 @@ public void captureSpanForCanceledSingle() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); observer.dispose(); @@ -467,7 +464,7 @@ public void captureSpanForEventuallyCompletedObservable() throws InterruptedExce // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onNext("Value"); @@ -475,7 +472,7 @@ public void captureSpanForEventuallyCompletedObservable() throws InterruptedExce // sleep a bit just to make sure no span is captured Thread.sleep(500); - traces = testRunner().traces(); + traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onComplete(); @@ -524,7 +521,7 @@ public void captureSpanForEventuallyErrorObservable() throws InterruptedExceptio // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onNext("Value"); @@ -532,7 +529,7 @@ public void captureSpanForEventuallyErrorObservable() throws InterruptedExceptio // sleep a bit just to make sure no span is captured Thread.sleep(500); - traces = testRunner().traces(); + traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onError(error); @@ -561,7 +558,7 @@ public void captureSpanForCanceledObservable() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onNext("Value"); @@ -569,7 +566,7 @@ public void captureSpanForCanceledObservable() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - traces = testRunner().traces(); + traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); observer.dispose(); @@ -615,7 +612,7 @@ public void captureForEventuallyCompletedFlowable() throws InterruptedException // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onNext("Value"); @@ -623,7 +620,7 @@ public void captureForEventuallyCompletedFlowable() throws InterruptedException // sleep a bit just to make sure no span is captured Thread.sleep(500); - traces = testRunner().traces(); + traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onComplete(); @@ -672,7 +669,7 @@ public void captureSpanForEventuallyErrorFlowable() throws InterruptedException // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onNext("Value"); @@ -680,7 +677,7 @@ public void captureSpanForEventuallyErrorFlowable() throws InterruptedException // sleep a bit just to make sure no span is captured Thread.sleep(500); - traces = testRunner().traces(); + traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onError(error); @@ -709,7 +706,7 @@ public void captureSpanForCanceledFlowable() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onNext("Value"); @@ -717,7 +714,7 @@ public void captureSpanForCanceledFlowable() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - traces = testRunner().traces(); + traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); observer.cancel(); @@ -763,7 +760,7 @@ public void captureSpanForEventuallyCompletedParallelFlowable() throws Interrupt // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onNext("Value"); @@ -771,7 +768,7 @@ public void captureSpanForEventuallyCompletedParallelFlowable() throws Interrupt // sleep a bit just to make sure no span is captured Thread.sleep(500); - traces = testRunner().traces(); + traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onComplete(); @@ -821,7 +818,7 @@ public void captureSpanForEventuallyErrorParallelFlowable() throws InterruptedEx // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onNext("Value"); @@ -829,7 +826,7 @@ public void captureSpanForEventuallyErrorParallelFlowable() throws InterruptedEx // sleep a bit just to make sure no span is captured Thread.sleep(500); - traces = testRunner().traces(); + traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onError(error); @@ -859,7 +856,7 @@ public void captureSpanForCanceledParallelFlowable() throws InterruptedException // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onNext("Value"); @@ -867,7 +864,7 @@ public void captureSpanForCanceledParallelFlowable() throws InterruptedException // sleep a bit just to make sure no span is captured Thread.sleep(500); - traces = testRunner().traces(); + traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); observer.cancel(); @@ -894,7 +891,7 @@ public void captureSpanForEventuallyCompletedPublisher() throws InterruptedExcep // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onComplete(); @@ -921,7 +918,7 @@ public void captureSpanForEventuallyErrorPublisher() throws InterruptedException // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); source.onError(error); @@ -950,7 +947,7 @@ public void captureSpanForCanceledPublisher() throws InterruptedException { // sleep a bit just to make sure no span is captured Thread.sleep(500); - List> traces = testRunner().traces(); + List> traces = testing().waitForTraces(0); assertThat(traces).isEmpty(); observer.cancel(); diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java index ba00e212fb60..9d1ddb055d9c 100644 --- a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java +++ b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/RxJava3ConcurrencyTestHelper.java @@ -6,7 +6,7 @@ package io.opentelemetry.instrumentation.rxjava.v3.common; import io.opentelemetry.api.trace.Span; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.reactivex.rxjava3.core.Scheduler; import io.reactivex.rxjava3.core.Single; import java.util.concurrent.CountDownLatch; @@ -26,7 +26,7 @@ public class RxJava3ConcurrencyTestHelper { private RxJava3ConcurrencyTestHelper() {} public static void launchAndWait( - Scheduler scheduler, int iterations, long timeoutMillis, InstrumentationTestRunner runner) { + Scheduler scheduler, int iterations, long timeoutMillis, InstrumentationExtension runner) { CountDownLatch latch = new CountDownLatch(iterations); for (int i = 0; i < iterations; i++) { @@ -42,7 +42,7 @@ public static void launchAndWait( } } - private static void launchOuter(Iteration iteration, InstrumentationTestRunner runner) { + private static void launchOuter(Iteration iteration, InstrumentationExtension runner) { runner.runWithSpan( "outer", () -> { @@ -60,7 +60,7 @@ private static void launchOuter(Iteration iteration, InstrumentationTestRunner r }); } - private static void launchInner(Iteration iteration, InstrumentationTestRunner runner) { + private static void launchInner(Iteration iteration, InstrumentationExtension runner) { runner.runWithSpan( "middle", () -> { diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java index 99135062ce4e..47deb1fd7cef 100644 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java @@ -6,8 +6,6 @@ import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest; import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan; import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan; -import io.opentelemetry.instrumentation.testing.AgentTestRunner; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.extension.RegisterExtension; @@ -16,8 +14,6 @@ public class RxJava3ExtensionWithSpanTest extends AbstractRxJava3WithSpanTest { @RegisterExtension static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); - private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); - @Override protected AbstractTracedWithSpan newTraced() { return new TracedWithSpan(); @@ -27,9 +23,4 @@ protected AbstractTracedWithSpan newTraced() { protected InstrumentationExtension testing() { return testing; } - - @Override - protected InstrumentationTestRunner testRunner() { - return RUNNER; - } } diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java index 680bfabfcfb3..3e55565a3632 100644 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java @@ -6,8 +6,6 @@ import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest; import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan; import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan; -import io.opentelemetry.instrumentation.testing.AgentTestRunner; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.extension.RegisterExtension; @@ -16,8 +14,6 @@ public class RxJava3InstrumentationWithSpanTest extends AbstractRxJava3WithSpanT @RegisterExtension static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); - private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); - @Override protected AbstractTracedWithSpan newTraced() { return new TracedWithSpan(); @@ -27,9 +23,4 @@ protected AbstractTracedWithSpan newTraced() { protected InstrumentationExtension testing() { return testing; } - - @Override - protected InstrumentationTestRunner testRunner() { - return RUNNER; - } } diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3Test.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3Test.java index e49a6acf55cc..9eb2fdfadb51 100644 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3Test.java +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3Test.java @@ -4,8 +4,6 @@ */ import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test; -import io.opentelemetry.instrumentation.testing.AgentTestRunner; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.extension.RegisterExtension; @@ -14,15 +12,8 @@ public class RxJava3Test extends AbstractRxJava3Test { @RegisterExtension static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); - private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); - @Override protected InstrumentationExtension testing() { return testing; } - - @Override - protected InstrumentationTestRunner testRunner() { - return RUNNER; - } } diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3Test.java b/instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3Test.java index 7b96033313aa..68cd95fb1f66 100644 --- a/instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3Test.java +++ b/instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3Test.java @@ -5,8 +5,6 @@ import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test; import io.opentelemetry.instrumentation.rxjava.v3_0.TracingAssembly; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; -import io.opentelemetry.instrumentation.testing.LibraryTestRunner; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; import org.junit.jupiter.api.BeforeAll; @@ -17,24 +15,14 @@ public class RxJava3Test extends AbstractRxJava3Test { static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); static TracingAssembly tracingAssembly = TracingAssembly.create(); - private static final InstrumentationTestRunner RUNNER = LibraryTestRunner.instance(); @Override protected InstrumentationExtension testing() { return testing; } - @Override - public InstrumentationTestRunner testRunner() { - return RUNNER; - } - @BeforeAll public void setupSpec() { tracingAssembly.enable(); } - - public InstrumentationTestRunner getTestRunner() { - return RUNNER; - } } diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java index 99135062ce4e..47deb1fd7cef 100644 --- a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java +++ b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3ExtensionWithSpanTest.java @@ -6,8 +6,6 @@ import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest; import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan; import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan; -import io.opentelemetry.instrumentation.testing.AgentTestRunner; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.extension.RegisterExtension; @@ -16,8 +14,6 @@ public class RxJava3ExtensionWithSpanTest extends AbstractRxJava3WithSpanTest { @RegisterExtension static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); - private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); - @Override protected AbstractTracedWithSpan newTraced() { return new TracedWithSpan(); @@ -27,9 +23,4 @@ protected AbstractTracedWithSpan newTraced() { protected InstrumentationExtension testing() { return testing; } - - @Override - protected InstrumentationTestRunner testRunner() { - return RUNNER; - } } diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java index 680bfabfcfb3..3e55565a3632 100644 --- a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java +++ b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3InstrumentationWithSpanTest.java @@ -6,8 +6,6 @@ import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3WithSpanTest; import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractTracedWithSpan; import io.opentelemetry.instrumentation.rxjava.v3.common.extensionannotation.TracedWithSpan; -import io.opentelemetry.instrumentation.testing.AgentTestRunner; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.extension.RegisterExtension; @@ -16,8 +14,6 @@ public class RxJava3InstrumentationWithSpanTest extends AbstractRxJava3WithSpanT @RegisterExtension static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); - private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); - @Override protected AbstractTracedWithSpan newTraced() { return new TracedWithSpan(); @@ -27,9 +23,4 @@ protected AbstractTracedWithSpan newTraced() { protected InstrumentationExtension testing() { return testing; } - - @Override - protected InstrumentationTestRunner testRunner() { - return RUNNER; - } } diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3Test.java b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3Test.java index e49a6acf55cc..9eb2fdfadb51 100644 --- a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3Test.java +++ b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3Test.java @@ -4,8 +4,6 @@ */ import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test; -import io.opentelemetry.instrumentation.testing.AgentTestRunner; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.extension.RegisterExtension; @@ -14,15 +12,8 @@ public class RxJava3Test extends AbstractRxJava3Test { @RegisterExtension static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); - private static final InstrumentationTestRunner RUNNER = AgentTestRunner.instance(); - @Override protected InstrumentationExtension testing() { return testing; } - - @Override - protected InstrumentationTestRunner testRunner() { - return RUNNER; - } } diff --git a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3Test.java b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3Test.java index 43343a9b569c..efb2f9f960a1 100644 --- a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3Test.java +++ b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3Test.java @@ -5,8 +5,6 @@ import io.opentelemetry.instrumentation.rxjava.v3.common.AbstractRxJava3Test; import io.opentelemetry.instrumentation.rxjava.v3_1_1.TracingAssembly; -import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; -import io.opentelemetry.instrumentation.testing.LibraryTestRunner; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; import org.junit.jupiter.api.BeforeAll; @@ -17,24 +15,14 @@ public class RxJava3Test extends AbstractRxJava3Test { static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); static TracingAssembly tracingAssembly = TracingAssembly.create(); - private static final InstrumentationTestRunner RUNNER = LibraryTestRunner.instance(); @Override protected InstrumentationExtension testing() { return testing; } - @Override - public InstrumentationTestRunner testRunner() { - return RUNNER; - } - @BeforeAll public void setupSpec() { tracingAssembly.enable(); } - - public InstrumentationTestRunner getTestRunner() { - return RUNNER; - } } From c806de84a4937e367d579c6bad52c4270ee04b38 Mon Sep 17 00:00:00 2001 From: Kaibo Cai Date: Mon, 10 Apr 2023 21:49:09 -0500 Subject: [PATCH 3/5] fix cancel test cases --- .../rxjava/v3/common/AbstractRxJava3Test.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java index e0742c1f17bd..d5471f952477 100644 --- a/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java +++ b/instrumentation/rxjava/rxjava-3-common/testing/src/main/java/io/opentelemetry/instrumentation/rxjava/v3/common/AbstractRxJava3Test.java @@ -501,7 +501,7 @@ public void basicFlowableFailure() { public void basicMaybeCancel() { createParentSpan( () -> - Maybe.just(1).map(this::addOne).toFlowable().subscribe(CancellingSubscriber.INSTANCE)); + Maybe.just(1).toFlowable().map(this::addOne).subscribe(CancellingSubscriber.INSTANCE)); testing() .waitAndAssertTraces( trace -> @@ -527,7 +527,7 @@ public void basicFlowableCancel() { public void basicSingleCancel() { createParentSpan( () -> - Single.just(1).map(this::addOne).toFlowable().subscribe(CancellingSubscriber.INSTANCE)); + Single.just(1).toFlowable().map(this::addOne).subscribe(CancellingSubscriber.INSTANCE)); testing() .waitAndAssertTraces( trace -> @@ -554,8 +554,8 @@ public void basicObservableCancel() { createParentSpan( () -> Observable.just(1) - .map(this::addOne) .toFlowable(BackpressureStrategy.LATEST) + .map(this::addOne) .subscribe(CancellingSubscriber.INSTANCE)); testing() .waitAndAssertTraces( From c42e1d157485628349a075d2f676cdd449f67d53 Mon Sep 17 00:00:00 2001 From: Kaibo Cai Date: Tue, 11 Apr 2023 20:48:02 -0500 Subject: [PATCH 4/5] fix tests in RxJava3AsyncOperationEndStrategyTest --- .../RxJava3AsyncOperationEndStrategyTest.java | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/instrumentation/rxjava/rxjava-3-common/library/src/test/java/RxJava3AsyncOperationEndStrategyTest.java b/instrumentation/rxjava/rxjava-3-common/library/src/test/java/RxJava3AsyncOperationEndStrategyTest.java index 5e235e2cc34c..f3fbd8144e23 100644 --- a/instrumentation/rxjava/rxjava-3-common/library/src/test/java/RxJava3AsyncOperationEndStrategyTest.java +++ b/instrumentation/rxjava/rxjava-3-common/library/src/test/java/RxJava3AsyncOperationEndStrategyTest.java @@ -5,7 +5,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.times; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @@ -134,7 +134,7 @@ void endsWhenCancelled() { observer.dispose(); verify(instrumenter).end(context, "request", null, null); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); } @Test @@ -150,7 +150,7 @@ void endsSpanWhenCancelledExperimentalAttribute() { TestObserver observer = result.test(); verifyNoInteractions(instrumenter); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); observer.dispose(); @@ -191,15 +191,12 @@ void supported() { @Test void endsSpanOnAlreadyCompleted() { - UnicastProcessor source = UnicastProcessor.create(); - Maybe maybe = source.firstElement(); - Maybe result = - (Maybe) underTest.end(instrumenter, Context.root(), "request", maybe, String.class); + (Maybe) + underTest.end( + instrumenter, Context.root(), "request", Maybe.just("response"), String.class); TestObserver observer = result.test(); - source.onNext("response"); - source.onComplete(); observer.assertComplete(); verify(instrumenter).end(Context.root(), "request", "response", null); } @@ -288,7 +285,7 @@ void endsSpanWhenCancelled() { observer.dispose(); verify(instrumenter).end(context, "request", null, null); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); } @Test @@ -304,7 +301,7 @@ void endsSpanWhenCancelledExperimentalAttributes() { TestObserver observer = result.test(); verifyNoInteractions(instrumenter); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); observer.dispose(); @@ -415,7 +412,7 @@ void endsSpanWhenCancelled() { verifyNoInteractions(instrumenter); observer.dispose(); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); verify(instrumenter).end(context, "request", null, null); } @@ -432,7 +429,7 @@ void endsSpanWhenCancelledExperimentalAttributes() { TestObserver observer = result.test(); verifyNoInteractions(instrumenter); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); observer.dispose(); @@ -555,7 +552,7 @@ void endsOnWhenCancelled() { observer.dispose(); verify(instrumenter).end(context, "request", null, null); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); } @Test @@ -571,7 +568,7 @@ void endsSpanWhenCancelledExperimentalAttributes() { TestObserver observer = result.test(); verifyNoInteractions(instrumenter); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); observer.dispose(); @@ -682,7 +679,7 @@ void endsSpanWhenCancelled() { observer.cancel(); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); verify(instrumenter).end(context, "request", null, null); } @@ -699,7 +696,7 @@ void endsSpanWhenCancelledExperimentalAttributes() { TestSubscriber observer = result.test(); verifyNoInteractions(instrumenter); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); observer.cancel(); @@ -821,7 +818,7 @@ void endsSpanWhenCancelled() { observer.cancel(); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); verify(instrumenter).end(context, "request", null, null); } @@ -838,7 +835,7 @@ void endsSpanWhenCancelledExperimentalAttributes() { TestSubscriber observer = result.sequential().test(); verifyNoInteractions(instrumenter); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); observer.cancel(); verify(span).setAttribute(CANCELED_ATTRIBUTE_KEY, true); @@ -902,7 +899,7 @@ void endsSpanWhenCancelled() { observer.cancel(); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); verify(instrumenter).end(context, "request", null, null); } @@ -919,7 +916,7 @@ void endsSpanWhenCancelledExperimentalAttributes() { TestSubscriber observer = result.test(); verifyNoInteractions(instrumenter); - verify(span, times(0)).setAttribute(CANCELED_ATTRIBUTE_KEY, true); + verify(span, never()).setAttribute(CANCELED_ATTRIBUTE_KEY, true); observer.cancel(); From d524f7a28fabcac81d0b3c5f8dbb9123e5787e1c Mon Sep 17 00:00:00 2001 From: Kaibo Cai Date: Wed, 12 Apr 2023 14:19:37 -0500 Subject: [PATCH 5/5] fix tests name --- .../{Rx3SubscriptionTest.java => RxJava3SubscriptionTest.java} | 2 +- .../{Rx3SubscriptionTest.java => RxJava3SubscriptionTest.java} | 2 +- .../{Rx3SubscriptionTest.java => RxJava3SubscriptionTest.java} | 2 +- .../{Rx3SubscriptionTest.java => RxJava3SubscriptionTest.java} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/{Rx3SubscriptionTest.java => RxJava3SubscriptionTest.java} (88%) rename instrumentation/rxjava/rxjava-3.0/library/src/test/java/{Rx3SubscriptionTest.java => RxJava3SubscriptionTest.java} (91%) rename instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/{Rx3SubscriptionTest.java => RxJava3SubscriptionTest.java} (88%) rename instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/{Rx3SubscriptionTest.java => RxJava3SubscriptionTest.java} (91%) diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/Rx3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3SubscriptionTest.java similarity index 88% rename from instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/Rx3SubscriptionTest.java rename to instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3SubscriptionTest.java index 49b86d517e87..95ce51a2b612 100644 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/Rx3SubscriptionTest.java +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/test/java/RxJava3SubscriptionTest.java @@ -8,7 +8,7 @@ import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.extension.RegisterExtension; -public class Rx3SubscriptionTest extends AbstractRxJava3SubscriptionTest { +public class RxJava3SubscriptionTest extends AbstractRxJava3SubscriptionTest { @RegisterExtension static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); diff --git a/instrumentation/rxjava/rxjava-3.0/library/src/test/java/Rx3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3SubscriptionTest.java similarity index 91% rename from instrumentation/rxjava/rxjava-3.0/library/src/test/java/Rx3SubscriptionTest.java rename to instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3SubscriptionTest.java index a2d34deebbe2..7e2479a7aa60 100644 --- a/instrumentation/rxjava/rxjava-3.0/library/src/test/java/Rx3SubscriptionTest.java +++ b/instrumentation/rxjava/rxjava-3.0/library/src/test/java/RxJava3SubscriptionTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.RegisterExtension; -public class Rx3SubscriptionTest extends AbstractRxJava3SubscriptionTest { +public class RxJava3SubscriptionTest extends AbstractRxJava3SubscriptionTest { @RegisterExtension static final InstrumentationExtension testing = LibraryInstrumentationExtension.create(); diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/Rx3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3SubscriptionTest.java similarity index 88% rename from instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/Rx3SubscriptionTest.java rename to instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3SubscriptionTest.java index 49b86d517e87..95ce51a2b612 100644 --- a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/Rx3SubscriptionTest.java +++ b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/test/java/RxJava3SubscriptionTest.java @@ -8,7 +8,7 @@ import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.extension.RegisterExtension; -public class Rx3SubscriptionTest extends AbstractRxJava3SubscriptionTest { +public class RxJava3SubscriptionTest extends AbstractRxJava3SubscriptionTest { @RegisterExtension static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); diff --git a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/Rx3SubscriptionTest.java b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3SubscriptionTest.java similarity index 91% rename from instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/Rx3SubscriptionTest.java rename to instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3SubscriptionTest.java index 42ea148c6354..43f6e3988d4a 100644 --- a/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/Rx3SubscriptionTest.java +++ b/instrumentation/rxjava/rxjava-3.1.1/library/src/test/java/RxJava3SubscriptionTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.extension.RegisterExtension; -public class Rx3SubscriptionTest extends AbstractRxJava3SubscriptionTest { +public class RxJava3SubscriptionTest extends AbstractRxJava3SubscriptionTest { @RegisterExtension static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();