Skip to content

Commit 2f79f1d

Browse files
authored
move the reactive spring tests to a different directory (#11234)
1 parent f9f3080 commit 2f79f1d

File tree

19 files changed

+213
-40
lines changed

19 files changed

+213
-40
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"resources": {
3+
"includes": [
4+
{
5+
"pattern": "META-INF/io/opentelemetry/instrumentation/.*.properties"
6+
}
7+
]
8+
}
9+
}

settings.gradle.kts

+2-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ include(":smoke-tests:images:servlet:servlet-3.0")
138138
include(":smoke-tests:images:servlet:servlet-5.0")
139139
include(":smoke-tests:images:spring-boot")
140140

141-
include(":smoke-tests-otel-starter")
141+
include(":smoke-tests-otel-starter:spring-boot-3")
142+
include(":smoke-tests-otel-starter:spring-boot-3-reactive")
142143

143144
include(":instrumentation:akka:akka-actor-2.3:javaagent")
144145
include(":instrumentation:akka:akka-actor-fork-join-2.5:javaagent")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
plugins {
2+
id("otel.java-conventions")
3+
id("org.springframework.boot") version "3.2.5"
4+
id("org.graalvm.buildtools.native")
5+
}
6+
7+
description = "smoke-tests-otel-starter-spring-boot-3-reactive"
8+
9+
otelJava {
10+
minJavaVersionSupported.set(JavaVersion.VERSION_17)
11+
}
12+
13+
dependencies {
14+
implementation(project(":instrumentation:spring:starters:spring-boot-starter"))
15+
implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
16+
17+
implementation("org.springframework.boot:spring-boot-starter-webflux")
18+
19+
testImplementation("org.springframework.boot:spring-boot-starter-test")
20+
testImplementation("io.projectreactor:reactor-test")
21+
testImplementation(project(":testing-common"))
22+
}
23+
24+
tasks {
25+
test {
26+
// suppress warning about byte-buddy-agent being loaded dynamically
27+
jvmArgs("-XX:+EnableDynamicAgentLoading")
28+
}
29+
compileAotJava {
30+
with(options) {
31+
compilerArgs.add("-Xlint:-deprecation,-unchecked,none")
32+
// To disable warnings/failure coming from the Java compiler during the Spring AOT processing
33+
// -deprecation,-unchecked and none are required (none is not enough)
34+
}
35+
}
36+
compileAotTestJava {
37+
with(options) {
38+
compilerArgs.add("-Xlint:-deprecation,-unchecked,none")
39+
// To disable warnings/failure coming from the Java compiler during the Spring AOT processing
40+
// -deprecation,-unchecked and none are required (none is not enough)
41+
}
42+
}
43+
checkstyleAot {
44+
isEnabled = false
45+
}
46+
checkstyleAotTest {
47+
isEnabled = false
48+
}
49+
}
50+
51+
// To be able to execute the tests as GraalVM native executables
52+
configurations.configureEach {
53+
exclude("org.apache.groovy", "groovy")
54+
exclude("org.apache.groovy", "groovy-json")
55+
exclude("org.spockframework", "spock-core")
56+
}
57+
58+
graalvmNative {
59+
binaries.all {
60+
// Workaround for https://github.com/junit-team/junit5/issues/3405
61+
buildArgs.add("--initialize-at-build-time=org.junit.platform.launcher.core.LauncherConfig")
62+
buildArgs.add("--initialize-at-build-time=org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter")
63+
}
64+
65+
// See https://github.com/graalvm/native-build-tools/issues/572
66+
metadataRepository {
67+
enabled.set(false)
68+
}
69+
70+
tasks.test {
71+
useJUnitPlatform()
72+
setForkEvery(1)
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.spring.smoketest;
7+
8+
import org.springframework.boot.SpringApplication;
9+
import org.springframework.boot.autoconfigure.SpringBootApplication;
10+
11+
@SpringBootApplication
12+
public class OtelReactiveSpringStarterSmokeTestApplication {
13+
14+
public OtelReactiveSpringStarterSmokeTestApplication() {}
15+
16+
public static void main(String[] args) {
17+
SpringApplication.run(OtelReactiveSpringStarterSmokeTestApplication.class);
18+
}
19+
}

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
import reactor.core.publisher.Mono;
1111

1212
@RestController
13-
public class OtelSpringStarterWebfluxSmokeTestController {
13+
public class OtelReactiveSpringStarterSmokeTestController {
1414

1515
public static final String WEBFLUX = "/webflux";
1616

1717
@GetMapping(WEBFLUX)
18-
public Mono<String> getStock() {
19-
return Mono.just("pong");
18+
public Mono<String> webflux() {
19+
return Mono.just("webflux");
2020
}
2121
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.smoketest;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
import io.opentelemetry.api.OpenTelemetry;
11+
import io.opentelemetry.api.trace.SpanKind;
12+
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
13+
import io.opentelemetry.semconv.HttpAttributes;
14+
import io.opentelemetry.semconv.UrlAttributes;
15+
import io.opentelemetry.spring.smoketest.OtelReactiveSpringStarterSmokeTestApplication;
16+
import io.opentelemetry.spring.smoketest.OtelReactiveSpringStarterSmokeTestController;
17+
import org.junit.jupiter.api.AfterEach;
18+
import org.junit.jupiter.api.BeforeEach;
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.extension.ExtendWith;
21+
import org.junit.jupiter.api.extension.RegisterExtension;
22+
import org.springframework.beans.factory.annotation.Autowired;
23+
import org.springframework.boot.test.context.SpringBootTest;
24+
import org.springframework.boot.test.system.CapturedOutput;
25+
import org.springframework.boot.test.system.OutputCaptureExtension;
26+
import org.springframework.boot.test.web.server.LocalServerPort;
27+
import org.springframework.context.annotation.Bean;
28+
import org.springframework.context.annotation.Configuration;
29+
import org.springframework.web.reactive.function.client.WebClient;
30+
31+
@ExtendWith(OutputCaptureExtension.class)
32+
@SpringBootTest(
33+
classes = {
34+
OtelReactiveSpringStarterSmokeTestApplication.class,
35+
OtelReactiveSpringStarterSmokeTest.TestConfiguration.class
36+
},
37+
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
38+
class OtelReactiveSpringStarterSmokeTest {
39+
40+
@RegisterExtension
41+
static final LibraryInstrumentationExtension testing = LibraryInstrumentationExtension.create();
42+
43+
@LocalServerPort int serverPort;
44+
45+
@Autowired WebClient.Builder webClientBuilder;
46+
private WebClient webClient;
47+
48+
@Configuration(proxyBeanMethods = false)
49+
static class TestConfiguration {
50+
@Bean
51+
OpenTelemetry openTelemetry() {
52+
return testing.getOpenTelemetry();
53+
}
54+
}
55+
56+
@BeforeEach
57+
void setUp() {
58+
webClient = webClientBuilder.baseUrl("http://localhost:" + serverPort).build();
59+
}
60+
61+
@AfterEach
62+
void tearDown(CapturedOutput output) {
63+
assertThat(output).doesNotContain("WARN").doesNotContain("ERROR");
64+
}
65+
66+
@Test
67+
void webClientAndWebFluxAndR2dbc() {
68+
webClient
69+
.get()
70+
.uri(OtelReactiveSpringStarterSmokeTestController.WEBFLUX)
71+
.retrieve()
72+
.bodyToFlux(String.class)
73+
.blockLast();
74+
75+
testing.waitAndAssertTraces(
76+
trace ->
77+
trace.hasSpansSatisfyingExactly(
78+
span ->
79+
span.hasKind(SpanKind.CLIENT)
80+
.hasName("GET")
81+
.hasAttributesSatisfying(
82+
a -> assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/webflux")),
83+
span ->
84+
span.hasKind(SpanKind.SERVER)
85+
.hasName("GET /webflux")
86+
.hasAttribute(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
87+
.hasAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L)
88+
.hasAttribute(HttpAttributes.HTTP_ROUTE, "/webflux")));
89+
}
90+
}

smoke-tests-otel-starter/build.gradle.kts smoke-tests-otel-starter/spring-boot-3/build.gradle.kts

+1-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
id("org.graalvm.buildtools.native")
55
}
66

7-
description = "smoke-tests-otel-starter"
7+
description = "smoke-tests-otel-starter-spring-boot-3"
88

99
otelJava {
1010
minJavaVersionSupported.set(JavaVersion.VERSION_17)
@@ -21,9 +21,6 @@ dependencies {
2121
implementation(project(":instrumentation:spring:starters:spring-boot-starter"))
2222
implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
2323

24-
// webflux / reactive style
25-
implementation("org.springframework.boot:spring-boot-starter-webflux")
26-
2724
testImplementation("org.springframework.boot:spring-boot-starter-test")
2825
testImplementation(project(":testing-common"))
2926
}

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

-26
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import io.opentelemetry.semconv.incubating.ServiceIncubatingAttributes;
4242
import io.opentelemetry.spring.smoketest.OtelSpringStarterSmokeTestApplication;
4343
import io.opentelemetry.spring.smoketest.OtelSpringStarterSmokeTestController;
44-
import io.opentelemetry.spring.smoketest.OtelSpringStarterWebfluxSmokeTestController;
4544
import java.time.Duration;
4645
import java.util.Collections;
4746
import java.util.List;
@@ -313,31 +312,6 @@ private void assertClient(String url) {
313312
.hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping")));
314313
}
315314

316-
@Test
317-
void webflux() {
318-
resetExporters();
319-
320-
testRestTemplate.getForObject(
321-
OtelSpringStarterWebfluxSmokeTestController.WEBFLUX, String.class);
322-
323-
TracesAssert.assertThat(expectSpans(2))
324-
.hasTracesSatisfyingExactly(
325-
traceAssert ->
326-
traceAssert.hasSpansSatisfyingExactly(
327-
clientSpan ->
328-
clientSpan
329-
.hasKind(SpanKind.CLIENT)
330-
.hasAttributesSatisfying(
331-
a ->
332-
assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/webflux")),
333-
serverSpan ->
334-
serverSpan
335-
.hasKind(SpanKind.SERVER)
336-
.hasAttribute(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
337-
.hasAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L)
338-
.hasAttribute(HttpAttributes.HTTP_ROUTE, "/webflux")));
339-
}
340-
341315
private static List<SpanData> expectSpans(int spans) {
342316
with()
343317
.conditionEvaluationListener(

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

+15-6
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,21 @@ private <T extends Consumer<TraceAssert>> void waitAndAssertTraces(
122122
try {
123123
await()
124124
.untilAsserted(() -> doAssertTraces(traceComparator, assertionsList, verifyScopeVersion));
125-
} catch (ConditionTimeoutException e) {
126-
// Don't throw this failure since the stack is the awaitility thread, causing confusion.
127-
// Instead, just assert one more time on the test thread, which will fail with a better stack
128-
// trace.
129-
// TODO(anuraaga): There is probably a better way to do this.
130-
doAssertTraces(traceComparator, assertionsList, verifyScopeVersion);
125+
} catch (Throwable t) {
126+
// awaitility is doing a jmx call that is not implemented in GraalVM:
127+
// call:
128+
// https://github.com/awaitility/awaitility/blob/fbe16add874b4260dd240108304d5c0be84eabc8/awaitility/src/main/java/org/awaitility/core/ConditionAwaiter.java#L157
129+
// see https://github.com/oracle/graal/issues/6101 (spring boot graal native image)
130+
if (t.getClass().getName().equals("com.oracle.svm.core.jdk.UnsupportedFeatureError")
131+
|| t instanceof ConditionTimeoutException) {
132+
// Don't throw this failure since the stack is the awaitility thread, causing confusion.
133+
// Instead, just assert one more time on the test thread, which will fail with a better
134+
// stack trace.
135+
// TODO(anuraaga): There is probably a better way to do this.
136+
doAssertTraces(traceComparator, assertionsList, verifyScopeVersion);
137+
} else {
138+
throw t;
139+
}
131140
}
132141
}
133142

0 commit comments

Comments
 (0)