Browse Source

Migrate Guava tests to Java (#5668)

* Migrate Guava tests to Java

* Update instrumentation/guava-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/guava/ListenableFutureTest.java

Co-authored-by: Lauri Tulmin <tulmin@gmail.com>

* Workaround inline mock issue

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
Co-authored-by: Lauri Tulmin <tulmin@gmail.com>
Anuraag Agrawal 3 years ago
parent
commit
14372adb68
32 changed files with 461 additions and 559 deletions
  1. 7 0
      conventions/src/main/kotlin/otel.java-conventions.gradle.kts
  2. 0 4
      instrumentation-api-annotation-support/build.gradle.kts
  3. 0 4
      instrumentation-api/build.gradle.kts
  4. 0 3
      instrumentation-appender-api-internal/build.gradle.kts
  5. 0 1
      instrumentation/apache-camel-2.20/javaagent-unit-tests/build.gradle.kts
  6. 0 2
      instrumentation/aws-lambda/aws-lambda-core-1.0/library/build.gradle.kts
  7. 0 2
      instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts
  8. 0 2
      instrumentation/aws-sdk/aws-sdk-1.11/javaagent-unit-tests/build.gradle.kts
  9. 0 3
      instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts
  10. 0 1
      instrumentation/grpc-1.6/library/build.gradle.kts
  11. 0 129
      instrumentation/guava-10.0/javaagent/src/test/groovy/GuavaWithSpanInstrumentationTest.groovy
  12. 0 43
      instrumentation/guava-10.0/javaagent/src/test/groovy/ListenableFutureTest.groovy
  13. 106 0
      instrumentation/guava-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaWithSpanInstrumentationTest.java
  14. 197 0
      instrumentation/guava-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/guava/ListenableFutureTest.java
  15. 3 3
      instrumentation/guava-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/guava/TracedWithSpan.java
  16. 0 6
      instrumentation/guava-10.0/library/build.gradle.kts
  17. 2 1
      instrumentation/guava-10.0/library/src/main/java/io/opentelemetry/instrumentation/guava/GuavaAsyncOperationEndStrategy.java
  18. 0 139
      instrumentation/guava-10.0/library/src/test/groovy/GuavaAsyncOperationEndStrategyTest.groovy
  19. 135 0
      instrumentation/guava-10.0/library/src/test/java/io/opentelemetry/instrumentation/guava/GuavaAsyncOperationEndStrategyTest.java
  20. 0 3
      instrumentation/jms-1.1/javaagent-unit-tests/build.gradle.kts
  21. 0 2
      instrumentation/log4j/log4j-appender-2.16/library/build.gradle.kts
  22. 0 2
      instrumentation/logback/logback-appender-1.0/library/build.gradle.kts
  23. 0 1
      instrumentation/runtime-metrics/library/build.gradle.kts
  24. 0 4
      instrumentation/servlet/servlet-common/bootstrap/build.gradle.kts
  25. 0 1
      instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts
  26. 0 3
      instrumentation/spring/spring-web-3.1/library/build.gradle.kts
  27. 0 2
      javaagent-bootstrap/build.gradle.kts
  28. 0 3
      javaagent-instrumentation-api/build.gradle.kts
  29. 11 3
      javaagent-tooling/build.gradle.kts
  30. 0 1
      javaagent/build.gradle.kts
  31. 0 6
      muzzle/build.gradle.kts
  32. 0 185
      testing-common/src/main/groovy/io/opentelemetry/instrumentation/test/base/AbstractPromiseTest.groovy

+ 7 - 0
conventions/src/main/kotlin/otel.java-conventions.gradle.kts

@@ -137,6 +137,13 @@ testing {
       runtimeOnly("org.junit.jupiter:junit-jupiter-engine")
       runtimeOnly("org.junit.vintage:junit-vintage-engine")
 
+
+      implementation("org.assertj:assertj-core")
+      implementation("org.awaitility:awaitility")
+      implementation("org.mockito:mockito-core")
+      implementation("org.mockito:mockito-inline")
+      implementation("org.mockito:mockito-junit-jupiter")
+
       implementation("org.objenesis:objenesis")
       implementation("org.spockframework:spock-core") {
         with (this as ExternalDependency) {

+ 0 - 4
instrumentation-api-annotation-support/build.gradle.kts

@@ -17,10 +17,6 @@ dependencies {
   annotationProcessor("com.google.auto.value:auto-value")
 
   testImplementation(project(":testing-common"))
-  testImplementation("org.mockito:mockito-core")
-  testImplementation("org.mockito:mockito-junit-jupiter")
-  testImplementation("org.assertj:assertj-core")
-  testImplementation("org.awaitility:awaitility")
   testImplementation("io.opentelemetry:opentelemetry-sdk-metrics")
   testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
 }

+ 0 - 4
instrumentation-api/build.gradle.kts

@@ -21,10 +21,6 @@ dependencies {
   annotationProcessor("com.google.auto.value:auto-value")
 
   testImplementation(project(":testing-common"))
-  testImplementation("org.mockito:mockito-core")
-  testImplementation("org.mockito:mockito-junit-jupiter")
-  testImplementation("org.assertj:assertj-core")
-  testImplementation("org.awaitility:awaitility")
   testImplementation("io.opentelemetry:opentelemetry-sdk-metrics")
   testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
 }

+ 0 - 3
instrumentation-appender-api-internal/build.gradle.kts

@@ -10,7 +10,4 @@ group = "io.opentelemetry.instrumentation"
 
 dependencies {
   api("io.opentelemetry:opentelemetry-api")
-
-  testImplementation("org.assertj:assertj-core")
-  testImplementation("org.mockito:mockito-core")
 }

+ 0 - 1
instrumentation/apache-camel-2.20/javaagent-unit-tests/build.gradle.kts

@@ -12,5 +12,4 @@ dependencies {
 
   testImplementation("io.opentelemetry:opentelemetry-extension-trace-propagators")
   testImplementation("io.opentelemetry:opentelemetry-extension-aws")
-  testImplementation("org.assertj:assertj-core")
 }

+ 0 - 2
instrumentation/aws-lambda/aws-lambda-core-1.0/library/build.gradle.kts

@@ -27,7 +27,5 @@ dependencies {
   testImplementation("com.google.guava:guava")
 
   testImplementation(project(":instrumentation:aws-lambda:aws-lambda-core-1.0:testing"))
-  testImplementation("org.mockito:mockito-core")
-  testImplementation("org.assertj:assertj-core")
   testImplementation("uk.org.webcompere:system-stubs-jupiter")
 }

+ 0 - 2
instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts

@@ -35,7 +35,5 @@ dependencies {
   testImplementation("com.google.guava:guava")
 
   testImplementation(project(":instrumentation:aws-lambda:aws-lambda-events-2.2:testing"))
-  testImplementation("org.mockito:mockito-core")
-  testImplementation("org.assertj:assertj-core")
   testImplementation("uk.org.webcompere:system-stubs-jupiter")
 }

+ 0 - 2
instrumentation/aws-sdk/aws-sdk-1.11/javaagent-unit-tests/build.gradle.kts

@@ -8,6 +8,4 @@ dependencies {
 
   testImplementation("com.amazonaws:aws-java-sdk-core:1.11.0")
   testImplementation("com.amazonaws:aws-java-sdk-sqs:1.11.106")
-
-  testImplementation("org.assertj:assertj-core")
 }

+ 0 - 3
instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts

@@ -10,9 +10,6 @@ dependencies {
 
   testImplementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:testing"))
 
-  testImplementation("org.assertj:assertj-core")
-  testImplementation("org.mockito:mockito-core")
-
   latestDepTestLibrary("software.amazon.awssdk:aws-core:+")
   latestDepTestLibrary("software.amazon.awssdk:aws-json-protocol:+")
   latestDepTestLibrary("software.amazon.awssdk:dynamodb:+")

+ 0 - 1
instrumentation/grpc-1.6/library/build.gradle.kts

@@ -13,6 +13,5 @@ dependencies {
   testLibrary("io.grpc:grpc-services:$grpcVersion")
   testLibrary("io.grpc:grpc-stub:$grpcVersion")
 
-  testImplementation("org.assertj:assertj-core")
   testImplementation(project(":instrumentation:grpc-1.6:testing"))
 }

+ 0 - 129
instrumentation/guava-10.0/javaagent/src/test/groovy/GuavaWithSpanInstrumentationTest.groovy

@@ -1,129 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import com.google.common.util.concurrent.Futures
-import com.google.common.util.concurrent.SettableFuture
-import io.opentelemetry.api.trace.SpanKind
-import io.opentelemetry.api.trace.StatusCode
-import io.opentelemetry.instrumentation.guava.TracedWithSpan
-import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
-
-class GuavaWithSpanInstrumentationTest extends AgentInstrumentationSpecification {
-
-  def "should capture span for already done ListenableFuture"() {
-    setup:
-    new TracedWithSpan().listenableFuture(Futures.immediateFuture("Value"))
-
-    expect:
-    assertTraces(1) {
-      trace(0, 1) {
-        span(0) {
-          name "TracedWithSpan.listenableFuture"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-          attributes {
-          }
-        }
-      }
-    }
-  }
-
-  def "should capture span for already failed ListenableFuture"() {
-    setup:
-    def error = new IllegalArgumentException("Boom")
-    new TracedWithSpan().listenableFuture(Futures.immediateFailedFuture(error))
-
-    expect:
-    assertTraces(1) {
-      trace(0, 1) {
-        span(0) {
-          name "TracedWithSpan.listenableFuture"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-          status StatusCode.ERROR
-          errorEvent(IllegalArgumentException, "Boom")
-          attributes {
-          }
-        }
-      }
-    }
-  }
-
-  def "should capture span for eventually done ListenableFuture"() {
-    setup:
-    def future = SettableFuture.<String> create()
-    new TracedWithSpan().listenableFuture(future)
-
-    expect:
-    Thread.sleep(500) // sleep a bit just to make sure no span is captured
-    assertTraces(0) {}
-
-    future.set("Value")
-
-    assertTraces(1) {
-      trace(0, 1) {
-        span(0) {
-          name "TracedWithSpan.listenableFuture"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-          attributes {
-          }
-        }
-      }
-    }
-  }
-
-  def "should capture span for eventually failed ListenableFuture"() {
-    setup:
-    def error = new IllegalArgumentException("Boom")
-    def future = SettableFuture.<String> create()
-    new TracedWithSpan().listenableFuture(future)
-
-    expect:
-    Thread.sleep(500) // sleep a bit just to make sure no span is captured
-    assertTraces(0) {}
-
-    future.setException(error)
-
-    assertTraces(1) {
-      trace(0, 1) {
-        span(0) {
-          name "TracedWithSpan.listenableFuture"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-          status StatusCode.ERROR
-          errorEvent(IllegalArgumentException, "Boom")
-          attributes {
-          }
-        }
-      }
-    }
-  }
-
-  def "should capture span for canceled ListenableFuture"() {
-    setup:
-    def future = SettableFuture.<String> create()
-    new TracedWithSpan().listenableFuture(future)
-
-    expect:
-    Thread.sleep(500) // sleep a bit just to make sure no span is captured
-    assertTraces(0) {}
-
-    future.cancel(true)
-
-    assertTraces(1) {
-      trace(0, 1) {
-        span(0) {
-          name "TracedWithSpan.listenableFuture"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-          attributes {
-            "guava.canceled" true
-          }
-        }
-      }
-    }
-  }
-}

+ 0 - 43
instrumentation/guava-10.0/javaagent/src/test/groovy/ListenableFutureTest.groovy

@@ -1,43 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import com.google.common.util.concurrent.Futures
-import com.google.common.util.concurrent.ListenableFuture
-import com.google.common.util.concurrent.SettableFuture
-import io.opentelemetry.instrumentation.test.base.AbstractPromiseTest
-import spock.lang.Shared
-
-import java.util.concurrent.Executors
-
-class ListenableFutureTest extends AbstractPromiseTest<SettableFuture<Boolean>, ListenableFuture<String>> {
-  @Shared
-  def executor = Executors.newFixedThreadPool(1)
-
-  @Override
-  SettableFuture<Boolean> newPromise() {
-    return SettableFuture.create()
-  }
-
-  @Override
-  ListenableFuture<String> map(SettableFuture<Boolean> promise, Closure<String> callback) {
-    return Futures.transform(promise, callback, executor)
-  }
-
-  @Override
-  void onComplete(ListenableFuture<String> promise, Closure callback) {
-    promise.addListener({ -> callback(promise.get()) }, executor)
-  }
-
-
-  @Override
-  void complete(SettableFuture<Boolean> promise, boolean value) {
-    promise.set(value)
-  }
-
-  @Override
-  Boolean get(SettableFuture<Boolean> promise) {
-    return promise.get()
-  }
-}

+ 106 - 0
instrumentation/guava-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaWithSpanInstrumentationTest.java

@@ -0,0 +1,106 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.guava;
+
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.SettableFuture;
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.trace.SpanKind;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.sdk.trace.data.StatusData;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class GuavaWithSpanInstrumentationTest {
+
+  @RegisterExtension
+  static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+  @Test
+  void success() {
+    SettableFuture<String> future = SettableFuture.create();
+    new TracedWithSpan().listenableFuture(future);
+    future.set("Value");
+
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span ->
+                    span.hasName("TracedWithSpan.listenableFuture")
+                        .hasKind(SpanKind.INTERNAL)
+                        .hasNoParent()
+                        .hasAttributes(Attributes.empty())));
+  }
+
+  @Test
+  void failure() {
+    IllegalArgumentException error = new IllegalArgumentException("Boom");
+    SettableFuture<String> future = SettableFuture.create();
+    new TracedWithSpan().listenableFuture(future);
+    future.setException(error);
+
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span ->
+                    span.hasName("TracedWithSpan.listenableFuture")
+                        .hasKind(SpanKind.INTERNAL)
+                        .hasNoParent()
+                        .hasStatus(StatusData.error())
+                        .hasException(error)
+                        .hasAttributes(Attributes.empty())));
+  }
+
+  @Test
+  void canceled() {
+    SettableFuture<String> future = SettableFuture.create();
+    new TracedWithSpan().listenableFuture(future);
+    future.cancel(true);
+
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span ->
+                    span.hasName("TracedWithSpan.listenableFuture")
+                        .hasKind(SpanKind.INTERNAL)
+                        .hasNoParent()
+                        .hasAttributes(attributeEntry("guava.canceled", true))));
+  }
+
+  @Test
+  void immediateSuccess() {
+    new TracedWithSpan().listenableFuture(Futures.immediateFuture("Value"));
+
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span ->
+                    span.hasName("TracedWithSpan.listenableFuture")
+                        .hasKind(SpanKind.INTERNAL)
+                        .hasNoParent()
+                        .hasAttributes(Attributes.empty())));
+  }
+
+  @Test
+  void immediateFailure() {
+    IllegalArgumentException error = new IllegalArgumentException("Boom");
+    new TracedWithSpan().listenableFuture(Futures.immediateFailedFuture(error));
+
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span ->
+                    span.hasName("TracedWithSpan.listenableFuture")
+                        .hasKind(SpanKind.INTERNAL)
+                        .hasNoParent()
+                        .hasStatus(StatusData.error())
+                        .hasException(error)
+                        .hasAttributes(Attributes.empty())));
+  }
+}

+ 197 - 0
instrumentation/guava-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/guava/ListenableFutureTest.java

@@ -0,0 +1,197 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.guava;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import io.opentelemetry.api.trace.SpanKind;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+// TODO: add a test for a longer chain of promises
+class ListenableFutureTest {
+
+  static final ExecutorService executor = Executors.newSingleThreadExecutor();
+
+  @RegisterExtension
+  static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+  @AfterAll
+  static void shutdown() {
+    executor.shutdown();
+  }
+
+  @ParameterizedTest
+  @ValueSource(booleans = {true, false})
+  void callWithParent(boolean value) {
+    SettableFuture<Boolean> future = SettableFuture.create();
+
+    testing.runWithSpan(
+        "parent",
+        () -> {
+          ListenableFuture<String> mapped = Futures.transform(future, String::valueOf, executor);
+          Futures.addCallback(
+              mapped,
+              new FutureCallback<String>() {
+                @Override
+                public void onSuccess(String result) {
+                  assertThat(result).isEqualTo(String.valueOf(value));
+                  testing.runWithSpan("callback", () -> {});
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                  throw new AssertionError(t);
+                }
+              },
+              executor);
+          testing.runWithSpan("other", () -> future.set(value));
+        });
+
+    assertThat(Futures.getUnchecked(future)).isEqualTo(value);
+
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
+                span ->
+                    span.hasName("other").hasKind(SpanKind.INTERNAL).hasParent(trace.getSpan(0)),
+                span ->
+                    span.hasName("callback")
+                        .hasKind(SpanKind.INTERNAL)
+                        .hasParent(trace.getSpan(0))));
+  }
+
+  @ParameterizedTest
+  @ValueSource(booleans = {true, false})
+  void callWithParentCompleteOutsideSpan(boolean value) {
+    SettableFuture<Boolean> future = SettableFuture.create();
+
+    testing.runWithSpan(
+        "parent",
+        () -> {
+          ListenableFuture<String> mapped = Futures.transform(future, String::valueOf, executor);
+          Futures.addCallback(
+              mapped,
+              new FutureCallback<String>() {
+                @Override
+                public void onSuccess(String result) {
+                  assertThat(result).isEqualTo(String.valueOf(value));
+                  testing.runWithSpan("callback", () -> {});
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                  throw new AssertionError(t);
+                }
+              },
+              executor);
+        });
+
+    testing.runWithSpan("other", () -> future.set(value));
+
+    assertThat(Futures.getUnchecked(future)).isEqualTo(value);
+
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
+                span ->
+                    span.hasName("callback")
+                        .hasKind(SpanKind.INTERNAL)
+                        .hasParent(trace.getSpan(0))),
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span -> span.hasName("other").hasKind(SpanKind.INTERNAL).hasNoParent()));
+  }
+
+  @ParameterizedTest
+  @ValueSource(booleans = {true, false})
+  void callWithParentCompleteOnSeparateThread(boolean value) {
+
+    SettableFuture<Boolean> future = SettableFuture.create();
+
+    testing.runWithSpan(
+        "parent",
+        () -> {
+          ListenableFuture<String> mapped = Futures.transform(future, String::valueOf, executor);
+          Futures.addCallback(
+              mapped,
+              new FutureCallback<String>() {
+                @Override
+                public void onSuccess(String result) {
+                  assertThat(result).isEqualTo(String.valueOf(value));
+                  testing.runWithSpan("callback", () -> {});
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                  throw new AssertionError(t);
+                }
+              },
+              executor);
+          executor.submit(() -> future.set(value));
+        });
+
+    assertThat(Futures.getUnchecked(future)).isEqualTo(value);
+
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(),
+                span ->
+                    span.hasName("callback")
+                        .hasKind(SpanKind.INTERNAL)
+                        .hasParent(trace.getSpan(0))));
+  }
+
+  @ParameterizedTest
+  @ValueSource(booleans = {true, false})
+  void callWithNoParent(boolean value) {
+    SettableFuture<Boolean> future = SettableFuture.create();
+
+    ListenableFuture<String> mapped = Futures.transform(future, String::valueOf, executor);
+    Futures.addCallback(
+        mapped,
+        new FutureCallback<String>() {
+          @Override
+          public void onSuccess(String result) {
+            assertThat(result).isEqualTo(String.valueOf(value));
+            testing.runWithSpan("callback", () -> {});
+          }
+
+          @Override
+          public void onFailure(Throwable t) {
+            throw new AssertionError(t);
+          }
+        },
+        executor);
+    testing.runWithSpan("other", () -> future.set(value));
+
+    assertThat(Futures.getUnchecked(future)).isEqualTo(value);
+
+    // TODO: There appears to be a context propagation bug. There is no logical reason for other to
+    // be the parent of callback in this test but not in callWithParent.
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span -> span.hasName("other").hasKind(SpanKind.INTERNAL).hasNoParent(),
+                span ->
+                    span.hasName("callback")
+                        .hasKind(SpanKind.INTERNAL)
+                        .hasParent(trace.getSpan(0))));
+  }
+}

+ 3 - 3
instrumentation/guava-10.0/javaagent/src/test/java/io/opentelemetry/instrumentation/guava/TracedWithSpan.java → instrumentation/guava-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/guava/TracedWithSpan.java

@@ -3,14 +3,14 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-package io.opentelemetry.instrumentation.guava;
+package io.opentelemetry.javaagent.instrumentation.guava;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import io.opentelemetry.extension.annotations.WithSpan;
 
-public class TracedWithSpan {
+final class TracedWithSpan {
   @WithSpan
-  public ListenableFuture<String> listenableFuture(ListenableFuture<String> future) {
+  ListenableFuture<String> listenableFuture(ListenableFuture<String> future) {
     return future;
   }
 }

+ 0 - 6
instrumentation/guava-10.0/library/build.gradle.kts

@@ -6,9 +6,3 @@ dependencies {
   library("com.google.guava:guava:10.0")
   implementation(project(":instrumentation-api-annotation-support"))
 }
-
-tasks.withType<Test>().configureEach {
-  // required on jdk17, uses spock Mock that needs access to jdk internals
-  jvmArgs("--add-opens=java.base/java.lang.invoke=ALL-UNNAMED")
-  jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
-}

+ 2 - 1
instrumentation/guava-10.0/library/src/main/java/io/opentelemetry/instrumentation/guava/GuavaAsyncOperationEndStrategy.java

@@ -16,7 +16,8 @@ import io.opentelemetry.instrumentation.api.annotation.support.async.AsyncOperat
 import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
 
 public final class GuavaAsyncOperationEndStrategy implements AsyncOperationEndStrategy {
-  private static final AttributeKey<Boolean> CANCELED_ATTRIBUTE_KEY =
+  // Visible for testing
+  static final AttributeKey<Boolean> CANCELED_ATTRIBUTE_KEY =
       AttributeKey.booleanKey("guava.canceled");
 
   public static GuavaAsyncOperationEndStrategy create() {

+ 0 - 139
instrumentation/guava-10.0/library/src/test/groovy/GuavaAsyncOperationEndStrategyTest.groovy

@@ -1,139 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import com.google.common.util.concurrent.Futures
-import com.google.common.util.concurrent.ListenableFuture
-import com.google.common.util.concurrent.SettableFuture
-import io.opentelemetry.api.trace.Span
-import io.opentelemetry.context.Context
-import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter
-import io.opentelemetry.instrumentation.guava.GuavaAsyncOperationEndStrategy
-import spock.lang.Specification
-
-class GuavaAsyncOperationEndStrategyTest extends Specification {
-  String request = "request"
-  String response = "response"
-
-  Instrumenter<String, String> instrumenter
-
-  Context context
-
-  Span span
-
-  def underTest = GuavaAsyncOperationEndStrategy.create()
-
-  def underTestWithExperimentalAttributes = GuavaAsyncOperationEndStrategy.builder()
-    .setCaptureExperimentalSpanAttributes(true)
-    .build()
-
-  void setup() {
-    instrumenter = Mock()
-    context = Mock()
-    span = Mock()
-    span.storeInContext(_) >> { callRealMethod() }
-  }
-
-  def "ListenableFuture is supported"() {
-    expect:
-    underTest.supports(ListenableFuture)
-  }
-
-  def "SettableFuture is also supported"() {
-    expect:
-    underTest.supports(SettableFuture)
-  }
-
-  def "ends span on already done future"() {
-    when:
-    underTest.end(instrumenter, context, request, Futures.immediateFuture(response), String)
-
-    then:
-    1 * instrumenter.end(context, request, response, null)
-  }
-
-  def "ends span on already failed future"() {
-    given:
-    def exception = new IllegalStateException()
-
-    when:
-    underTest.end(instrumenter, context, request, Futures.immediateFailedFuture(exception), String)
-
-    then:
-    1 * instrumenter.end(context, request, null, { it.getCause() == exception })
-  }
-
-  def "ends span on eventually done future"() {
-    given:
-    def future = SettableFuture.<String> create()
-
-    when:
-    underTest.end(instrumenter, context, request, future, String)
-
-    then:
-    0 * instrumenter._
-
-    when:
-    future.set(response)
-
-    then:
-    1 * instrumenter.end(context, request, response, null)
-  }
-
-  def "ends span on eventually failed future"() {
-    given:
-    def future = SettableFuture.<String> create()
-    def exception = new IllegalStateException()
-
-    when:
-    underTest.end(instrumenter, context, request, future, String)
-
-    then:
-    0 * instrumenter._
-
-    when:
-    future.setException(exception)
-
-    then:
-    1 * instrumenter.end(context, request, null, { it.getCause() == exception })
-  }
-
-  def "ends span on eventually canceled future"() {
-    given:
-    def future = SettableFuture.<String> create()
-    def context = span.storeInContext(Context.root())
-
-    when:
-    underTest.end(instrumenter, context, request, future, String)
-
-    then:
-    0 * instrumenter._
-
-    when:
-    future.cancel(true)
-
-    then:
-    1 * instrumenter.end(context, request, null, null)
-    0 * span.setAttribute(_)
-  }
-
-  def "ends span on eventually canceled future and capturing experimental span attributes"() {
-    given:
-    def future = SettableFuture.<String> create()
-    def context = span.storeInContext(Context.root())
-
-    when:
-    underTestWithExperimentalAttributes.end(instrumenter, context, request, future, String)
-
-    then:
-    0 * instrumenter._
-
-    when:
-    future.cancel(true)
-
-    then:
-    1 * instrumenter.end(context, request, null, null)
-    1 * span.setAttribute({ it.getKey() == "guava.canceled" }, true)
-  }
-}

+ 135 - 0
instrumentation/guava-10.0/library/src/test/java/io/opentelemetry/instrumentation/guava/GuavaAsyncOperationEndStrategyTest.java

@@ -0,0 +1,135 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.guava;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+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 org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+class GuavaAsyncOperationEndStrategyTest {
+
+  @Mock private Instrumenter<String, String> instrumenter;
+
+  @Mock private Span span;
+
+  private final AsyncOperationEndStrategy strategy = GuavaAsyncOperationEndStrategy.create();
+
+  @Test
+  void listenableFutureSupported() {
+    assertThat(strategy.supports(ListenableFuture.class)).isTrue();
+  }
+
+  @Test
+  void settableFutureSupported() {
+    assertThat(strategy.supports(SettableFuture.class)).isTrue();
+  }
+
+  @Test
+  void endsSpanOnSuccess() {
+    SettableFuture<String> future = SettableFuture.create();
+
+    strategy.end(instrumenter, Context.root(), "request", future, String.class);
+    future.set("response");
+
+    verify(instrumenter).end(Context.root(), "request", "response", null);
+  }
+
+  @Test
+  void endsSpanOnFailure() {
+    SettableFuture<String> future = SettableFuture.create();
+    IllegalStateException error = new IllegalStateException();
+
+    strategy.end(instrumenter, Context.root(), "request", future, String.class);
+    future.setException(error);
+
+    verify(instrumenter)
+        .end(
+            eq(Context.root()),
+            eq("request"),
+            isNull(),
+            argThat(
+                val -> {
+                  assertThat(val).hasCause(error);
+                  return true;
+                }));
+  }
+
+  @Test
+  void endsSpanOnCancel() {
+    when(span.storeInContext(any())).thenCallRealMethod();
+
+    SettableFuture<String> future = SettableFuture.create();
+    Context context = Context.root().with(span);
+
+    strategy.end(instrumenter, context, "request", future, String.class);
+    future.cancel(true);
+
+    verify(instrumenter).end(context, "request", null, null);
+  }
+
+  @Test
+  void endsSpanOnCancelExperimentalAttribute() {
+    when(span.storeInContext(any())).thenCallRealMethod();
+    when(span.setAttribute(GuavaAsyncOperationEndStrategy.CANCELED_ATTRIBUTE_KEY, true))
+        .thenReturn(span);
+
+    SettableFuture<String> future = SettableFuture.create();
+    Context context = Context.root().with(span);
+
+    AsyncOperationEndStrategy strategy =
+        GuavaAsyncOperationEndStrategy.builder().setCaptureExperimentalSpanAttributes(true).build();
+
+    strategy.end(instrumenter, context, "request", future, String.class);
+    future.cancel(true);
+
+    verify(instrumenter).end(context, "request", null, null);
+  }
+
+  @Test
+  void endsSpanOnImmediateSuccess() {
+    ListenableFuture<String> future = Futures.immediateFuture("response");
+
+    strategy.end(instrumenter, Context.root(), "request", future, String.class);
+
+    verify(instrumenter).end(Context.root(), "request", "response", null);
+  }
+
+  @Test
+  void endsSpanOnImmediateFailure() {
+    IllegalStateException error = new IllegalStateException();
+    ListenableFuture<String> future = Futures.immediateFailedFuture(error);
+
+    strategy.end(instrumenter, Context.root(), "request", future, String.class);
+
+    verify(instrumenter)
+        .end(
+            eq(Context.root()),
+            eq("request"),
+            isNull(),
+            argThat(
+                val -> {
+                  assertThat(val).hasCause(error);
+                  return true;
+                }));
+  }
+}

+ 0 - 3
instrumentation/jms-1.1/javaagent-unit-tests/build.gradle.kts

@@ -6,7 +6,4 @@ dependencies {
   testImplementation("javax.jms:jms-api:1.1-rev-1")
   testImplementation(project(":instrumentation:jms-1.1:javaagent"))
   testImplementation(project(":instrumentation-api"))
-
-  testImplementation("org.mockito:mockito-core")
-  testImplementation("org.mockito:mockito-junit-jupiter")
 }

+ 0 - 2
instrumentation/log4j/log4j-appender-2.16/library/build.gradle.kts

@@ -11,8 +11,6 @@ dependencies {
   testImplementation(project(":instrumentation-appender-sdk-internal"))
   testImplementation("io.opentelemetry:opentelemetry-sdk-logs")
   testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
-
-  testImplementation("org.mockito:mockito-core")
 }
 
 tasks.withType<Test>().configureEach {

+ 0 - 2
instrumentation/logback/logback-appender-1.0/library/build.gradle.kts

@@ -10,8 +10,6 @@ dependencies {
 
   testImplementation("io.opentelemetry:opentelemetry-sdk-logs")
   testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
-
-  testImplementation("org.mockito:mockito-core")
 }
 
 tasks.withType<Test>().configureEach {

+ 0 - 1
instrumentation/runtime-metrics/library/build.gradle.kts

@@ -5,5 +5,4 @@ plugins {
 dependencies {
   testImplementation("io.opentelemetry:opentelemetry-sdk-metrics")
   testImplementation(project(":testing-common"))
-  testImplementation("org.mockito:mockito-core")
 }

+ 0 - 4
instrumentation/servlet/servlet-common/bootstrap/build.gradle.kts

@@ -1,7 +1,3 @@
 plugins {
   id("otel.javaagent-bootstrap")
 }
-
-dependencies {
-  testImplementation("org.assertj:assertj-core")
-}

+ 0 - 1
instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts

@@ -37,7 +37,6 @@ dependencies {
     exclude("org.junit.vintage", "junit-vintage-engine")
   }
 
-  testImplementation("org.assertj:assertj-core")
   testImplementation(project(":testing-common"))
   testImplementation("io.opentelemetry:opentelemetry-sdk")
   testImplementation("io.opentelemetry:opentelemetry-sdk-testing")

+ 0 - 3
instrumentation/spring/spring-web-3.1/library/build.gradle.kts

@@ -8,8 +8,5 @@ dependencies {
   testImplementation("org.springframework:spring-web:3.1.0.RELEASE")
 
   testImplementation(project(":testing-common"))
-  testImplementation("org.assertj:assertj-core")
-  testImplementation("org.mockito:mockito-core")
-  testImplementation("org.mockito:mockito-junit-jupiter")
   testImplementation("io.opentelemetry:opentelemetry-sdk-testing")
 }

+ 0 - 2
javaagent-bootstrap/build.gradle.kts

@@ -10,6 +10,4 @@ dependencies {
   implementation("org.slf4j:slf4j-api")
 
   testImplementation(project(":testing-common"))
-  testImplementation("org.mockito:mockito-core")
-  testImplementation("org.assertj:assertj-core")
 }

+ 0 - 3
javaagent-instrumentation-api/build.gradle.kts

@@ -16,7 +16,4 @@ dependencies {
   annotationProcessor("com.google.auto.value:auto-value")
 
   testImplementation(project(":testing-common"))
-  testImplementation("org.mockito:mockito-core")
-  testImplementation("org.mockito:mockito-junit-jupiter")
-  testImplementation("org.assertj:assertj-core")
 }

+ 11 - 3
javaagent-tooling/build.gradle.kts

@@ -62,9 +62,6 @@ dependencies {
 
   testImplementation(project(":testing-common"))
   testImplementation("com.google.guava:guava")
-  testImplementation("org.assertj:assertj-core")
-  testImplementation("org.mockito:mockito-core")
-  testImplementation("org.mockito:mockito-junit-jupiter")
 }
 
 // Here we only include autoconfigure but don"t include OTLP exporters to ensure they are only in
@@ -82,3 +79,14 @@ tasks {
     }
   }
 }
+
+// Mockito inline mocking uses byte-buddy but agent tooling currently uses byte-buddy-dep, which cannot be on the same
+// classpath. Disable inline mocking to prevent conflicts.
+// TODO(anuraaga): Find a better solution
+configurations {
+  testRuntimeClasspath {
+    dependencies {
+      exclude("org.mockito", "mockito-inline")
+    }
+  }
+}

+ 0 - 1
javaagent/build.gradle.kts

@@ -80,7 +80,6 @@ dependencies {
   testImplementation("com.google.guava:guava")
   testImplementation("io.opentelemetry:opentelemetry-sdk")
   testImplementation("io.opentracing.contrib.dropwizard:dropwizard-opentracing:0.2.2")
-  testImplementation("org.assertj:assertj-core")
 }
 
 val javaagentDependencies = dependencies

+ 0 - 6
muzzle/build.gradle.kts

@@ -26,10 +26,4 @@ dependencies {
 
   testImplementation(project(":testing-common"))
   testImplementation("com.google.guava:guava")
-  testImplementation("org.assertj:assertj-core:3.19.0")
-
-  testImplementation(enforcedPlatform("org.junit:junit-bom:5.7.2"))
-  testImplementation("org.junit.jupiter:junit-jupiter-api")
-  testImplementation("org.junit.jupiter:junit-jupiter-params")
-  testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
 }

+ 0 - 185
testing-common/src/main/groovy/io/opentelemetry/instrumentation/test/base/AbstractPromiseTest.groovy

@@ -1,185 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.test.base
-
-
-import io.opentelemetry.api.trace.SpanKind
-import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
-
-// TODO: add a test for a longer chain of promises
-abstract class AbstractPromiseTest<P, M> extends AgentInstrumentationSpecification {
-
-  abstract P newPromise()
-
-  abstract M map(P promise, Closure<String> callback)
-
-  abstract void onComplete(M promise, Closure callback)
-
-  abstract void complete(P promise, boolean value)
-
-  abstract Boolean get(P promise)
-
-  def "test call with parent"() {
-    setup:
-    def promise = newPromise()
-
-    when:
-    runWithSpan("parent") {
-      def mapped = map(promise) { "$it" }
-      onComplete(mapped) {
-        assert it == "$value"
-        runWithSpan("callback") {}
-      }
-      runWithSpan("other") {
-        complete(promise, value)
-      }
-    }
-
-    then:
-    get(promise) == value
-    assertTraces(1) {
-      trace(0, 3) {
-        span(0) {
-          name "parent"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-        }
-        span(1) {
-          name "other"
-          kind SpanKind.INTERNAL
-          childOf span(0)
-        }
-        span(2) {
-          name "callback"
-          kind SpanKind.INTERNAL
-          childOf span(0)
-        }
-      }
-    }
-
-    where:
-    value << [true, false]
-  }
-
-  def "test call with parent delayed complete"() {
-    setup:
-    def promise = newPromise()
-
-    when:
-    runWithSpan("parent") {
-      def mapped = map(promise) { "$it" }
-      onComplete(mapped) {
-        assert it == "$value"
-        runWithSpan("callback") {}
-      }
-    }
-
-    runWithSpan("other") {
-      complete(promise, value)
-    }
-
-    then:
-    get(promise) == value
-    assertTraces(2) {
-      trace(0, 2) {
-        span(0) {
-          name "parent"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-        }
-        span(1) {
-          name "callback"
-          kind SpanKind.INTERNAL
-          childOf span(0)
-        }
-      }
-      trace(1, 1) {
-        span(0) {
-          name "other"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-        }
-      }
-    }
-
-    where:
-    value << [true, false]
-  }
-
-  def "test call with parent complete separate thread"() {
-    setup:
-    final promise = newPromise()
-
-    when:
-    runWithSpan("parent") {
-      def mapped = map(promise) { "$it" }
-      onComplete(mapped) {
-        assert it == "$value"
-        runWithSpan("callback") {}
-      }
-      Thread.start {
-        complete(promise, value)
-      }.join()
-    }
-
-    then:
-    get(promise) == value
-    assertTraces(1) {
-      trace(0, 2) {
-        span(0) {
-          name "parent"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-        }
-        span(1) {
-          name "callback"
-          kind SpanKind.INTERNAL
-          childOf span(0)
-        }
-      }
-    }
-
-    where:
-    value << [true, false]
-  }
-
-  def "test call with no parent"() {
-    setup:
-    def promise = newPromise()
-
-    when:
-    def mapped = map(promise) { "$it" }
-    onComplete(mapped) {
-      assert it == "$value"
-      runWithSpan("callback") {}
-    }
-
-    runWithSpan("other") {
-      complete(promise, value)
-    }
-
-    then:
-    get(promise) == value
-    assertTraces(1) {
-      trace(0, 2) {
-        // TODO: is this really the behavior we want?
-        span(0) {
-          name "other"
-          kind SpanKind.INTERNAL
-          hasNoParent()
-        }
-        span(1) {
-          name "callback"
-          kind SpanKind.INTERNAL
-          childOf span(0)
-        }
-      }
-    }
-
-    where:
-    value << [true, false]
-  }
-}