Browse Source

move the reactive spring tests to a different directory (#11234)

Gregor Zeitlinger 10 months ago
parent
commit
2f79f1dcc0
19 changed files with 213 additions and 40 deletions
  1. 9 0
      instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/native-image/io.opentelemetry.instrumentation/opentelemetry-spring-boot/resource-config.json
  2. 2 1
      settings.gradle.kts
  3. 74 0
      smoke-tests-otel-starter/spring-boot-3-reactive/build.gradle.kts
  4. 19 0
      smoke-tests-otel-starter/spring-boot-3-reactive/src/main/java/io/opentelemetry/spring/smoketest/OtelReactiveSpringStarterSmokeTestApplication.java
  5. 3 3
      smoke-tests-otel-starter/spring-boot-3-reactive/src/main/java/io/opentelemetry/spring/smoketest/OtelReactiveSpringStarterSmokeTestController.java
  6. 90 0
      smoke-tests-otel-starter/spring-boot-3-reactive/src/test/java/io/opentelemetry/smoketest/OtelReactiveSpringStarterSmokeTest.java
  7. 1 4
      smoke-tests-otel-starter/spring-boot-3/build.gradle.kts
  8. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/DatasourceConfig.java
  9. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestApplication.java
  10. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestController.java
  11. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/RuntimeHints.java
  12. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/SqlExecutor.java
  13. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/main/resources/META-INF/native-image/reflect-config.json
  14. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/main/resources/application-jdbc-driver-config.properties
  15. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/main/resources/application.yaml
  16. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/test/java/io/opentelemetry/smoketest/OtelSpringStarterDisabledSmokeTest.java
  17. 0 0
      smoke-tests-otel-starter/spring-boot-3/src/test/java/io/opentelemetry/smoketest/OtelSpringStarterJdbcDriverConfigSmokeTest.java
  18. 0 26
      smoke-tests-otel-starter/spring-boot-3/src/test/java/io/opentelemetry/smoketest/OtelSpringStarterSmokeTest.java
  19. 15 6
      testing-common/src/main/java/io/opentelemetry/instrumentation/testing/InstrumentationTestRunner.java

+ 9 - 0
instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/native-image/io.opentelemetry.instrumentation/opentelemetry-spring-boot/resource-config.json

@@ -0,0 +1,9 @@
+{
+  "resources": {
+    "includes": [
+      {
+        "pattern": "META-INF/io/opentelemetry/instrumentation/.*.properties"
+      }
+    ]
+  }
+}

+ 2 - 1
settings.gradle.kts

@@ -138,7 +138,8 @@ include(":smoke-tests:images:servlet:servlet-3.0")
 include(":smoke-tests:images:servlet:servlet-5.0")
 include(":smoke-tests:images:spring-boot")
 
-include(":smoke-tests-otel-starter")
+include(":smoke-tests-otel-starter:spring-boot-3")
+include(":smoke-tests-otel-starter:spring-boot-3-reactive")
 
 include(":instrumentation:akka:akka-actor-2.3:javaagent")
 include(":instrumentation:akka:akka-actor-fork-join-2.5:javaagent")

+ 74 - 0
smoke-tests-otel-starter/spring-boot-3-reactive/build.gradle.kts

@@ -0,0 +1,74 @@
+plugins {
+  id("otel.java-conventions")
+  id("org.springframework.boot") version "3.2.5"
+  id("org.graalvm.buildtools.native")
+}
+
+description = "smoke-tests-otel-starter-spring-boot-3-reactive"
+
+otelJava {
+  minJavaVersionSupported.set(JavaVersion.VERSION_17)
+}
+
+dependencies {
+  implementation(project(":instrumentation:spring:starters:spring-boot-starter"))
+  implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
+
+  implementation("org.springframework.boot:spring-boot-starter-webflux")
+
+  testImplementation("org.springframework.boot:spring-boot-starter-test")
+  testImplementation("io.projectreactor:reactor-test")
+  testImplementation(project(":testing-common"))
+}
+
+tasks {
+  test {
+    // suppress warning about byte-buddy-agent being loaded dynamically
+    jvmArgs("-XX:+EnableDynamicAgentLoading")
+  }
+  compileAotJava {
+    with(options) {
+      compilerArgs.add("-Xlint:-deprecation,-unchecked,none")
+      // To disable warnings/failure coming from the Java compiler during the Spring AOT processing
+      // -deprecation,-unchecked and none are required (none is not enough)
+    }
+  }
+  compileAotTestJava {
+    with(options) {
+      compilerArgs.add("-Xlint:-deprecation,-unchecked,none")
+      // To disable warnings/failure coming from the Java compiler during the Spring AOT processing
+      // -deprecation,-unchecked and none are required (none is not enough)
+    }
+  }
+  checkstyleAot {
+    isEnabled = false
+  }
+  checkstyleAotTest {
+    isEnabled = false
+  }
+}
+
+// To be able to execute the tests as GraalVM native executables
+configurations.configureEach {
+  exclude("org.apache.groovy", "groovy")
+  exclude("org.apache.groovy", "groovy-json")
+  exclude("org.spockframework", "spock-core")
+}
+
+graalvmNative {
+  binaries.all {
+    // Workaround for https://github.com/junit-team/junit5/issues/3405
+    buildArgs.add("--initialize-at-build-time=org.junit.platform.launcher.core.LauncherConfig")
+    buildArgs.add("--initialize-at-build-time=org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter")
+  }
+
+  // See https://github.com/graalvm/native-build-tools/issues/572
+  metadataRepository {
+    enabled.set(false)
+  }
+
+  tasks.test {
+    useJUnitPlatform()
+    setForkEvery(1)
+  }
+}

+ 19 - 0
smoke-tests-otel-starter/spring-boot-3-reactive/src/main/java/io/opentelemetry/spring/smoketest/OtelReactiveSpringStarterSmokeTestApplication.java

@@ -0,0 +1,19 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.spring.smoketest;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class OtelReactiveSpringStarterSmokeTestApplication {
+
+  public OtelReactiveSpringStarterSmokeTestApplication() {}
+
+  public static void main(String[] args) {
+    SpringApplication.run(OtelReactiveSpringStarterSmokeTestApplication.class);
+  }
+}

+ 3 - 3
smoke-tests-otel-starter/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterWebfluxSmokeTestController.java → smoke-tests-otel-starter/spring-boot-3-reactive/src/main/java/io/opentelemetry/spring/smoketest/OtelReactiveSpringStarterSmokeTestController.java

@@ -10,12 +10,12 @@ import org.springframework.web.bind.annotation.RestController;
 import reactor.core.publisher.Mono;
 
 @RestController
-public class OtelSpringStarterWebfluxSmokeTestController {
+public class OtelReactiveSpringStarterSmokeTestController {
 
   public static final String WEBFLUX = "/webflux";
 
   @GetMapping(WEBFLUX)
-  public Mono<String> getStock() {
-    return Mono.just("pong");
+  public Mono<String> webflux() {
+    return Mono.just("webflux");
   }
 }

+ 90 - 0
smoke-tests-otel-starter/spring-boot-3-reactive/src/test/java/io/opentelemetry/smoketest/OtelReactiveSpringStarterSmokeTest.java

@@ -0,0 +1,90 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.smoketest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.opentelemetry.api.OpenTelemetry;
+import io.opentelemetry.api.trace.SpanKind;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import io.opentelemetry.semconv.HttpAttributes;
+import io.opentelemetry.semconv.UrlAttributes;
+import io.opentelemetry.spring.smoketest.OtelReactiveSpringStarterSmokeTestApplication;
+import io.opentelemetry.spring.smoketest.OtelReactiveSpringStarterSmokeTestController;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.system.CapturedOutput;
+import org.springframework.boot.test.system.OutputCaptureExtension;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.reactive.function.client.WebClient;
+
+@ExtendWith(OutputCaptureExtension.class)
+@SpringBootTest(
+    classes = {
+      OtelReactiveSpringStarterSmokeTestApplication.class,
+      OtelReactiveSpringStarterSmokeTest.TestConfiguration.class
+    },
+    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+class OtelReactiveSpringStarterSmokeTest {
+
+  @RegisterExtension
+  static final LibraryInstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @LocalServerPort int serverPort;
+
+  @Autowired WebClient.Builder webClientBuilder;
+  private WebClient webClient;
+
+  @Configuration(proxyBeanMethods = false)
+  static class TestConfiguration {
+    @Bean
+    OpenTelemetry openTelemetry() {
+      return testing.getOpenTelemetry();
+    }
+  }
+
+  @BeforeEach
+  void setUp() {
+    webClient = webClientBuilder.baseUrl("http://localhost:" + serverPort).build();
+  }
+
+  @AfterEach
+  void tearDown(CapturedOutput output) {
+    assertThat(output).doesNotContain("WARN").doesNotContain("ERROR");
+  }
+
+  @Test
+  void webClientAndWebFluxAndR2dbc() {
+    webClient
+        .get()
+        .uri(OtelReactiveSpringStarterSmokeTestController.WEBFLUX)
+        .retrieve()
+        .bodyToFlux(String.class)
+        .blockLast();
+
+    testing.waitAndAssertTraces(
+        trace ->
+            trace.hasSpansSatisfyingExactly(
+                span ->
+                    span.hasKind(SpanKind.CLIENT)
+                        .hasName("GET")
+                        .hasAttributesSatisfying(
+                            a -> assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/webflux")),
+                span ->
+                    span.hasKind(SpanKind.SERVER)
+                        .hasName("GET /webflux")
+                        .hasAttribute(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
+                        .hasAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L)
+                        .hasAttribute(HttpAttributes.HTTP_ROUTE, "/webflux")));
+  }
+}

+ 1 - 4
smoke-tests-otel-starter/build.gradle.kts → smoke-tests-otel-starter/spring-boot-3/build.gradle.kts

@@ -4,7 +4,7 @@ plugins {
   id("org.graalvm.buildtools.native")
 }
 
-description = "smoke-tests-otel-starter"
+description = "smoke-tests-otel-starter-spring-boot-3"
 
 otelJava {
   minJavaVersionSupported.set(JavaVersion.VERSION_17)
@@ -21,9 +21,6 @@ dependencies {
   implementation(project(":instrumentation:spring:starters:spring-boot-starter"))
   implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
 
-  // webflux / reactive style
-  implementation("org.springframework.boot:spring-boot-starter-webflux")
-
   testImplementation("org.springframework.boot:spring-boot-starter-test")
   testImplementation(project(":testing-common"))
 }

+ 0 - 0
smoke-tests-otel-starter/src/main/java/io/opentelemetry/spring/smoketest/DatasourceConfig.java → smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/DatasourceConfig.java


+ 0 - 0
smoke-tests-otel-starter/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestApplication.java → smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestApplication.java


+ 0 - 0
smoke-tests-otel-starter/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestController.java → smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestController.java


+ 0 - 0
smoke-tests-otel-starter/src/main/java/io/opentelemetry/spring/smoketest/RuntimeHints.java → smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/RuntimeHints.java


+ 0 - 0
smoke-tests-otel-starter/src/main/java/io/opentelemetry/spring/smoketest/SqlExecutor.java → smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/SqlExecutor.java


+ 0 - 0
smoke-tests-otel-starter/src/main/resources/META-INF/native-image/reflect-config.json → smoke-tests-otel-starter/spring-boot-3/src/main/resources/META-INF/native-image/reflect-config.json


+ 0 - 0
smoke-tests-otel-starter/src/main/resources/application-jdbc-driver-config.properties → smoke-tests-otel-starter/spring-boot-3/src/main/resources/application-jdbc-driver-config.properties


+ 0 - 0
smoke-tests-otel-starter/src/main/resources/application.yaml → smoke-tests-otel-starter/spring-boot-3/src/main/resources/application.yaml


+ 0 - 0
smoke-tests-otel-starter/src/test/java/io/opentelemetry/smoketest/OtelSpringStarterDisabledSmokeTest.java → smoke-tests-otel-starter/spring-boot-3/src/test/java/io/opentelemetry/smoketest/OtelSpringStarterDisabledSmokeTest.java


+ 0 - 0
smoke-tests-otel-starter/src/test/java/io/opentelemetry/smoketest/OtelSpringStarterJdbcDriverConfigSmokeTest.java → smoke-tests-otel-starter/spring-boot-3/src/test/java/io/opentelemetry/smoketest/OtelSpringStarterJdbcDriverConfigSmokeTest.java


+ 0 - 26
smoke-tests-otel-starter/src/test/java/io/opentelemetry/smoketest/OtelSpringStarterSmokeTest.java → smoke-tests-otel-starter/spring-boot-3/src/test/java/io/opentelemetry/smoketest/OtelSpringStarterSmokeTest.java

@@ -41,7 +41,6 @@ import io.opentelemetry.semconv.incubating.DbIncubatingAttributes;
 import io.opentelemetry.semconv.incubating.ServiceIncubatingAttributes;
 import io.opentelemetry.spring.smoketest.OtelSpringStarterSmokeTestApplication;
 import io.opentelemetry.spring.smoketest.OtelSpringStarterSmokeTestController;
-import io.opentelemetry.spring.smoketest.OtelSpringStarterWebfluxSmokeTestController;
 import java.time.Duration;
 import java.util.Collections;
 import java.util.List;
@@ -313,31 +312,6 @@ class OtelSpringStarterSmokeTest {
                             .hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping")));
   }
 
-  @Test
-  void webflux() {
-    resetExporters();
-
-    testRestTemplate.getForObject(
-        OtelSpringStarterWebfluxSmokeTestController.WEBFLUX, String.class);
-
-    TracesAssert.assertThat(expectSpans(2))
-        .hasTracesSatisfyingExactly(
-            traceAssert ->
-                traceAssert.hasSpansSatisfyingExactly(
-                    clientSpan ->
-                        clientSpan
-                            .hasKind(SpanKind.CLIENT)
-                            .hasAttributesSatisfying(
-                                a ->
-                                    assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/webflux")),
-                    serverSpan ->
-                        serverSpan
-                            .hasKind(SpanKind.SERVER)
-                            .hasAttribute(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
-                            .hasAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L)
-                            .hasAttribute(HttpAttributes.HTTP_ROUTE, "/webflux")));
-  }
-
   private static List<SpanData> expectSpans(int spans) {
     with()
         .conditionEvaluationListener(

+ 15 - 6
testing-common/src/main/java/io/opentelemetry/instrumentation/testing/InstrumentationTestRunner.java

@@ -122,12 +122,21 @@ public abstract class InstrumentationTestRunner {
     try {
       await()
           .untilAsserted(() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion));
-    } catch (ConditionTimeoutException e) {
-      // Don't throw this failure since the stack is the awaitility thread, causing confusion.
-      // Instead, just assert one more time on the test thread, which will fail with a better stack
-      // trace.
-      // TODO(anuraaga): There is probably a better way to do this.
-      doAssertTraces(traceComparator, assertionsList, verifyScopeVersion);
+    } catch (Throwable t) {
+      // awaitility is doing a jmx call that is not implemented in GraalVM:
+      // call:
+      // https://github.com/awaitility/awaitility/blob/fbe16add874b4260dd240108304d5c0be84eabc8/awaitility/src/main/java/org/awaitility/core/ConditionAwaiter.java#L157
+      // see https://github.com/oracle/graal/issues/6101 (spring boot graal native image)
+      if (t.getClass().getName().equals("com.oracle.svm.core.jdk.UnsupportedFeatureError")
+          || t instanceof ConditionTimeoutException) {
+        // Don't throw this failure since the stack is the awaitility thread, causing confusion.
+        // Instead, just assert one more time on the test thread, which will fail with a better
+        // stack trace.
+        // TODO(anuraaga): There is probably a better way to do this.
+        doAssertTraces(traceComparator, assertionsList, verifyScopeVersion);
+      } else {
+        throw t;
+      }
     }
   }