From e0fab709b5ba95904ece9ed14b13c0cfa472149f Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 10 Jul 2026 15:25:22 -0400 Subject: [PATCH 1/3] Migrate Java 25 concurrent smoke tests --- .../concurrent/java-25/build.gradle | 17 +----- .../AbstractStructuredConcurrencyTest.groovy | 59 ------------------- .../concurrent/MultipleTasksTest.groovy | 40 ------------- .../concurrent/NestedTasksTest.groovy | 43 -------------- .../ScheduledForkJoinTaskTest.groovy | 37 ------------ .../smoketest/concurrent/SimpleTest.groovy | 42 ------------- .../AbstractStructuredConcurrencyTest.java | 59 +++++++++++++++++++ .../concurrent/MultipleTasksTest.java | 41 +++++++++++++ .../smoketest/concurrent/NestedTasksTest.java | 48 +++++++++++++++ .../concurrent/ScheduledForkJoinTaskTest.java | 50 ++++++++++++++++ .../concurrent/SimpleCallableTest.java | 15 +++++ .../concurrent/SimpleRunnableTest.java | 15 +++++ .../smoketest/concurrent/SimpleTest.java | 16 +++++ 13 files changed, 245 insertions(+), 237 deletions(-) delete mode 100644 dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.groovy delete mode 100644 dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/MultipleTasksTest.groovy delete mode 100644 dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/NestedTasksTest.groovy delete mode 100644 dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.groovy delete mode 100644 dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/SimpleTest.groovy create mode 100644 dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.java create mode 100644 dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/MultipleTasksTest.java create mode 100644 dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/NestedTasksTest.java create mode 100644 dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.java create mode 100644 dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleCallableTest.java create mode 100644 dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleRunnableTest.java create mode 100644 dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleTest.java diff --git a/dd-smoke-tests/concurrent/java-25/build.gradle b/dd-smoke-tests/concurrent/java-25/build.gradle index 8aeb5484287..729bbb44910 100644 --- a/dd-smoke-tests/concurrent/java-25/build.gradle +++ b/dd-smoke-tests/concurrent/java-25/build.gradle @@ -7,14 +7,7 @@ plugins { } testJvmConstraints { - // This smoke test should be limited to Java 25 and above - // But the groovy testing framework cannot run on Java 25 - // Using Java 8 for now and runs a JVM 25 when forking tests process. - // Relying on forked JVM 25 is hardcoded in the test suites (see createProcessBuilder()). - minJavaVersion = JavaVersion.VERSION_1_8 - maxJavaVersion = JavaVersion.VERSION_1_8 - // Only runs on Temurin build as it spawns a Temurin 25 for test process. - excludeJdk = ['IBM8', 'SEMERU8'] + minJavaVersion = JavaVersion.VERSION_25 } description = 'JDK 25 Concurrent Integration Tests' @@ -32,13 +25,6 @@ tasks.named('compileJava', JavaCompile) { options.compilerArgs.add("--enable-preview") } -// TODO: drop Groovy here at all -// The Groovy test framework can't run on Java 25 (the module's default toolchain), so pin the -// Groovy test compiler back to JDK 8 — matches the Java 8 test JVM that forks a Java 25 subprocess. -tasks.named('compileTestGroovy') { - configureCompiler(it, 8, JavaVersion.VERSION_1_8, "Groovy test framework cannot run on JDK 25") -} - application { mainClass = 'datadog.smoketest.concurrent.ConcurrentApp' } @@ -51,7 +37,6 @@ dependencies { tasks.withType(Test).configureEach { def shadowJarTask = tasks.named('shadowJar', ShadowJar) dependsOn shadowJarTask - environment("JAVA_HOME", getLazyJavaHomeFor(25)) jvmArgumentProviders.add(new CommandLineArgumentProvider() { @Override Iterable asArguments() { diff --git a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.groovy b/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.groovy deleted file mode 100644 index 52ae573544b..00000000000 --- a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.groovy +++ /dev/null @@ -1,59 +0,0 @@ -package datadog.smoketest.concurrent - -import datadog.smoketest.AbstractSmokeTest -import datadog.trace.test.agent.decoder.DecodedSpan -import datadog.trace.test.agent.decoder.DecodedTrace - -import java.nio.file.Paths -import java.util.function.Function - -import static java.util.concurrent.TimeUnit.SECONDS - -abstract class AbstractStructuredConcurrencyTest extends AbstractSmokeTest { - @Override - protected boolean expectsProcessAliveBeforeEachTest() { - false - } - - protected static final int TIMEOUT_SECS = 10 - protected abstract String testCaseName() - - @Override - ProcessBuilder createProcessBuilder() { - def jarPath = System.getProperty("datadog.smoketest.shadowJar.path") - def command = new ArrayList() - - def javaHome = Paths.get(System.getenv("JAVA_HOME"), "bin", "java").toString() - command.add(javaHome) - command.addAll(defaultJavaProperties) - command.add("--enable-preview") - command.add("-Ddd.trace.otel.enabled=true") - command.addAll(["-jar", jarPath]) - command.add(testCaseName()) - - ProcessBuilder processBuilder = new ProcessBuilder(command) - processBuilder.directory(new File(buildDirectory)) - } - - @Override - Closure decodedTracesCallback() { - return {} // force traces decoding - } - - protected void receivedCorrectTrace() { - assert testedProcess.waitFor(TIMEOUT_SECS, SECONDS) - assert testedProcess.exitValue() == 0 - waitForTrace(defaultPoll, checkTrace()) - assert traceCount.get() == 1 - } - - protected abstract Function checkTrace() - - protected DecodedSpan findRootSpan(DecodedTrace trace, String resource) { - return trace.spans.find { it.resource == resource && it.parentId == 0 } - } - - protected DecodedSpan findChildSpan(DecodedTrace trace, String resource, long parentSpanId) { - return trace.spans.find { it.resource == resource && it.parentId == parentSpanId } - } -} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/MultipleTasksTest.groovy b/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/MultipleTasksTest.groovy deleted file mode 100644 index 56f50e358e8..00000000000 --- a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/MultipleTasksTest.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package datadog.smoketest.concurrent - -import datadog.trace.test.agent.decoder.DecodedTrace - -import java.util.function.Function - -/** - * Tests the structured task scope with a multiple tasks. - * Here is the expected task/span structure: - *
- *   parent
- *   |-- child1
- *   |-- child2
- *   \-- child3
- * 
- */ -class MultipleTasksTest extends AbstractStructuredConcurrencyTest { - @Override - protected String testCaseName() { - 'MultipleTasks' - } - - @Override - protected Function checkTrace() { - return { - trace -> - // Look for 'parent' span - def parentSpan = findRootSpan(trace, 'parent') - // Look for 'child1', 'child2', and 'child3' spans - return parentSpan && findChildSpan(trace, 'child1', parentSpan.spanId) - && findChildSpan(trace, 'child2', parentSpan.spanId) - && findChildSpan(trace, 'child3', parentSpan.spanId) - } - } - - def 'test multiple tasks'() { - expect: - receivedCorrectTrace() - } -} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/NestedTasksTest.groovy b/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/NestedTasksTest.groovy deleted file mode 100644 index cc5df9c227f..00000000000 --- a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/NestedTasksTest.groovy +++ /dev/null @@ -1,43 +0,0 @@ -package datadog.smoketest.concurrent - -import datadog.trace.test.agent.decoder.DecodedTrace - -import java.util.function.Function - -/** - * Tests the structured task scope with a multiple nested tasks. - * Here is the expected task/span structure: - *
- *   parent
- *   |-- child1
- *   |   |-- great-child1-1
- *   |   \-- great-child1-2
- *   \-- child2
- * 
- */ -class NestedTasksTest extends AbstractStructuredConcurrencyTest { - @Override - protected String testCaseName() { - 'NestedTasks' - } - - @Override - protected Function checkTrace() { - return { - trace -> - // Look for 'parent' span - def parentSpan = findRootSpan(trace, 'parent') - // Look for 'child1' span - def child1Span = parentSpan ? findChildSpan(trace, 'child1', parentSpan.spanId) : null - // Look for 'child2', 'great-child1-1' and 'great-child1-2' spans - return child1Span && findChildSpan(trace, 'child2', parentSpan.spanId) - && findChildSpan(trace, 'great-child1-1', child1Span.spanId) - && findChildSpan(trace, 'great-child1-2', child1Span.spanId) - } - } - - def 'test nested tasks'() { - expect: - receivedCorrectTrace() - } -} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.groovy b/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.groovy deleted file mode 100644 index 91570bcf747..00000000000 --- a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package datadog.smoketest.concurrent - -import datadog.trace.test.agent.decoder.DecodedTrace - -import java.util.function.Function - -import static java.util.concurrent.TimeUnit.SECONDS - -class ScheduledForkJoinTaskTest extends AbstractStructuredConcurrencyTest { - @Override - protected String testCaseName() { - 'ScheduledForkJoinTask' - } - - @Override - protected Function checkTrace() { - return { trace -> - def parent = findRootSpan(trace, 'parent') - def scheduled = parent ? findChildSpan(trace, 'scheduled', parent.spanId) : null - return trace.spans.size() == 3 && scheduled && findChildSpan(trace, 'nested', scheduled.spanId) - } - } - - def 'propagates delayed context across executors and clears it after execution'() { - expect: - testedProcess.waitFor(TIMEOUT_SECS, SECONDS) - testedProcess.exitValue() == 0 - waitForTrace(defaultPoll, checkTrace()) - waitForTrace(defaultPoll, { trace -> - trace.spans.size() == 1 && findRootSpan(trace, 'unrelated-forkjoin') - }) - waitForTrace(defaultPoll, { trace -> - trace.spans.size() == 1 && findRootSpan(trace, 'unrelated-executor') - }) - traceCount.get() == 3 - } -} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/SimpleTest.groovy b/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/SimpleTest.groovy deleted file mode 100644 index b4ba0a4c0b0..00000000000 --- a/dd-smoke-tests/concurrent/java-25/src/test/groovy/datadog/smoketest/concurrent/SimpleTest.groovy +++ /dev/null @@ -1,42 +0,0 @@ -package datadog.smoketest.concurrent - -import datadog.trace.test.agent.decoder.DecodedTrace - -import java.util.function.Function - -abstract class SimpleTest extends AbstractStructuredConcurrencyTest { - @Override - protected Function checkTrace() { - return { trace -> - // Look for 'parent' span - def parentSpan = findRootSpan(trace, 'parent') - // Look for 'child' span - return parentSpan && findChildSpan(trace, 'child', parentSpan.spanId) - } - } -} - -class SimpleRunnableTest extends SimpleTest { - @Override - protected String testCaseName() { - 'SimpleRunnableTask' - } - - def 'test simple runnable'() { - expect: - receivedCorrectTrace() - } -} - -class SimpleCallableTest extends SimpleTest { - @Override - protected String testCaseName() { - 'SimpleCallableTask' - } - - def 'test simple callable'() { - expect: - receivedCorrectTrace() - } -} - diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.java new file mode 100644 index 00000000000..94533dbe6a8 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.java @@ -0,0 +1,59 @@ +package datadog.smoketest.concurrent; + +import static datadog.smoketest.backend.AgentBackend.mockAgent; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import datadog.smoketest.SmokeCliApp; +import datadog.trace.test.agent.decoder.DecodedSpan; +import datadog.trace.test.agent.decoder.DecodedTrace; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.RegisterExtension; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +abstract class AbstractStructuredConcurrencyTest { + @RegisterExtension + final SmokeCliApp app = + SmokeCliApp.named(testCaseName()) + .jar(System.getProperty("datadog.smoketest.shadowJar.path")) + .jvmArgs("--enable-preview", "-Ddd.trace.otel.enabled=true") + .args(testCaseName()) + .backend(mockAgent()) + .build(); + + protected abstract String testCaseName(); + + protected abstract Predicate checkTrace(); + + protected void receivedCorrectTrace() { + app.assertCompletesWithValue(10, SECONDS, 0); + app.traces().waitForTraceCount(1); + List traces = app.traces().getTraces(); + assertEquals(1, traces.size()); + assertTrue(checkTrace().test(traces.get(0)), "Unexpected structured concurrency trace"); + } + + protected Optional findRootSpan(DecodedTrace trace, String resource) { + return trace.getSpans().stream() + .filter(span -> Objects.equals(resource, span.getResource()) && span.getParentId() == 0) + .findFirst(); + } + + protected Optional findChildSpan( + DecodedTrace trace, String resource, long parentSpanId) { + return trace.getSpans().stream() + .filter( + span -> + Objects.equals(resource, span.getResource()) && span.getParentId() == parentSpanId) + .findFirst(); + } + + protected boolean hasChildSpan(DecodedTrace trace, String resource, long parentSpanId) { + return findChildSpan(trace, resource, parentSpanId).isPresent(); + } +} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/MultipleTasksTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/MultipleTasksTest.java new file mode 100644 index 00000000000..7eccf24c5d8 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/MultipleTasksTest.java @@ -0,0 +1,41 @@ +package datadog.smoketest.concurrent; + +import datadog.trace.test.agent.decoder.DecodedTrace; +import java.util.function.Predicate; +import org.junit.jupiter.api.Test; + +/** + * Tests the structured task scope with multiple tasks. Here is the expected task/span structure: + * + *
+ *   parent
+ *   |-- child1
+ *   |-- child2
+ *   \-- child3
+ * 
+ */ +class MultipleTasksTest extends AbstractStructuredConcurrencyTest { + @Override + protected String testCaseName() { + return "MultipleTasks"; + } + + @Override + protected Predicate checkTrace() { + // 'parent' with 'child1', 'child2', and 'child3' as direct children + return trace -> + trace.getSpans().size() == 4 + && findRootSpan(trace, "parent") + .filter( + parent -> + hasChildSpan(trace, "child1", parent.getSpanId()) + && hasChildSpan(trace, "child2", parent.getSpanId()) + && hasChildSpan(trace, "child3", parent.getSpanId())) + .isPresent(); + } + + @Test + void testMultipleTasks() throws Exception { + receivedCorrectTrace(); + } +} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/NestedTasksTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/NestedTasksTest.java new file mode 100644 index 00000000000..fad04954019 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/NestedTasksTest.java @@ -0,0 +1,48 @@ +package datadog.smoketest.concurrent; + +import datadog.trace.test.agent.decoder.DecodedTrace; +import java.util.function.Predicate; +import org.junit.jupiter.api.Test; + +/** + * Tests the structured task scope with multiple nested tasks. Here is the expected task/span + * structure: + * + *
+ *   parent
+ *   |-- child1
+ *   |   |-- great-child1-1
+ *   |   \-- great-child1-2
+ *   \-- child2
+ * 
+ */ +class NestedTasksTest extends AbstractStructuredConcurrencyTest { + @Override + protected String testCaseName() { + return "NestedTasks"; + } + + @Override + protected Predicate checkTrace() { + // 'parent' -> 'child1' -> {'great-child1-1', 'great-child1-2'}, and 'parent' -> 'child2' + return trace -> + trace.getSpans().size() == 5 + && findRootSpan(trace, "parent") + .filter( + parent -> + findChildSpan(trace, "child1", parent.getSpanId()) + .filter( + child1 -> + hasChildSpan(trace, "child2", parent.getSpanId()) + && hasChildSpan(trace, "great-child1-1", child1.getSpanId()) + && hasChildSpan( + trace, "great-child1-2", child1.getSpanId())) + .isPresent()) + .isPresent(); + } + + @Test + void testNestedTasks() throws Exception { + receivedCorrectTrace(); + } +} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.java new file mode 100644 index 00000000000..e085c754f43 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.java @@ -0,0 +1,50 @@ +package datadog.smoketest.concurrent; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import datadog.trace.test.agent.decoder.DecodedTrace; +import java.util.List; +import java.util.function.Predicate; +import org.junit.jupiter.api.Test; + +class ScheduledForkJoinTaskTest extends AbstractStructuredConcurrencyTest { + @Override + protected String testCaseName() { + return "ScheduledForkJoinTask"; + } + + @Override + protected Predicate checkTrace() { + return trace -> + trace.getSpans().size() == 3 + && findRootSpan(trace, "parent") + .flatMap(parent -> findChildSpan(trace, "scheduled", parent.getSpanId())) + .filter(scheduled -> hasChildSpan(trace, "nested", scheduled.getSpanId())) + .isPresent(); + } + + @Test + void propagatesDelayedContextAcrossExecutorsAndClearsItAfterExecution() { + app.assertCompletesWithValue(10, SECONDS, 0); + app.traces().waitForTraceCount(3); + List traces = app.traces().getTraces(); + assertEquals(3, traces.size()); + assertTrue(traces.stream().anyMatch(checkTrace()), "Missing scheduled task trace"); + assertTrue( + traces.stream() + .anyMatch( + trace -> + trace.getSpans().size() == 1 + && findRootSpan(trace, "unrelated-forkjoin").isPresent()), + "Missing unrelated fork-join trace"); + assertTrue( + traces.stream() + .anyMatch( + trace -> + trace.getSpans().size() == 1 + && findRootSpan(trace, "unrelated-executor").isPresent()), + "Missing unrelated executor trace"); + } +} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleCallableTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleCallableTest.java new file mode 100644 index 00000000000..81b309a3703 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleCallableTest.java @@ -0,0 +1,15 @@ +package datadog.smoketest.concurrent; + +import org.junit.jupiter.api.Test; + +class SimpleCallableTest extends SimpleTest { + @Override + protected String testCaseName() { + return "SimpleCallableTask"; + } + + @Test + void testSimpleCallable() throws Exception { + receivedCorrectTrace(); + } +} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleRunnableTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleRunnableTest.java new file mode 100644 index 00000000000..e09ee9372b9 --- /dev/null +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleRunnableTest.java @@ -0,0 +1,15 @@ +package datadog.smoketest.concurrent; + +import org.junit.jupiter.api.Test; + +class SimpleRunnableTest extends SimpleTest { + @Override + protected String testCaseName() { + return "SimpleRunnableTask"; + } + + @Test + void testSimpleRunnable() throws Exception { + receivedCorrectTrace(); + } +} diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleTest.java new file mode 100644 index 00000000000..e78c881ce4c --- /dev/null +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/SimpleTest.java @@ -0,0 +1,16 @@ +package datadog.smoketest.concurrent; + +import datadog.trace.test.agent.decoder.DecodedTrace; +import java.util.function.Predicate; + +abstract class SimpleTest extends AbstractStructuredConcurrencyTest { + @Override + protected Predicate checkTrace() { + // 'parent' with a single 'child' + return trace -> + trace.getSpans().size() == 2 + && findRootSpan(trace, "parent") + .filter(parent -> hasChildSpan(trace, "child", parent.getSpanId())) + .isPresent(); + } +} From 764ce594d46cc5fb4456eaa72e043d798d838deb Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Wed, 4 Nov 2026 20:43:50 -0500 Subject: [PATCH 2/3] Fixed failed test. --- dd-smoke-tests/concurrent/java-25/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dd-smoke-tests/concurrent/java-25/build.gradle b/dd-smoke-tests/concurrent/java-25/build.gradle index 729bbb44910..f971b3f1ada 100644 --- a/dd-smoke-tests/concurrent/java-25/build.gradle +++ b/dd-smoke-tests/concurrent/java-25/build.gradle @@ -8,6 +8,10 @@ plugins { testJvmConstraints { minJavaVersion = JavaVersion.VERSION_25 + // Newer JVMs can run ordinary Java 25 bytecode, but these are tests for preview of StructuredTaskScope API. + // Preview bytecode runs only on the Java release that compiled it. + // Even with --enable-preview, Java 27 accepts only Java 27 preview bytecode, not Java 25's. + maxJavaVersion = JavaVersion.VERSION_25 } description = 'JDK 25 Concurrent Integration Tests' From 6564453de9df98ab343438d2fd8f12a86bdfe918 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Sun, 8 Nov 2026 11:35:37 -0500 Subject: [PATCH 3/3] Spotless. --- .../AbstractStructuredConcurrencyTest.java | 5 ++--- .../smoketest/concurrent/MultipleTasksTest.java | 9 ++++----- .../smoketest/concurrent/NestedTasksTest.java | 17 +++++++---------- .../concurrent/ScheduledForkJoinTaskTest.java | 14 ++++++-------- 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.java index 94533dbe6a8..0498d982c0e 100644 --- a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.java +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/AbstractStructuredConcurrencyTest.java @@ -47,9 +47,8 @@ protected Optional findRootSpan(DecodedTrace trace, String resource protected Optional findChildSpan( DecodedTrace trace, String resource, long parentSpanId) { return trace.getSpans().stream() - .filter( - span -> - Objects.equals(resource, span.getResource()) && span.getParentId() == parentSpanId) + .filter(span -> + Objects.equals(resource, span.getResource()) && span.getParentId() == parentSpanId) .findFirst(); } diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/MultipleTasksTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/MultipleTasksTest.java index 7eccf24c5d8..a76f330ae5b 100644 --- a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/MultipleTasksTest.java +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/MultipleTasksTest.java @@ -26,11 +26,10 @@ protected Predicate checkTrace() { return trace -> trace.getSpans().size() == 4 && findRootSpan(trace, "parent") - .filter( - parent -> - hasChildSpan(trace, "child1", parent.getSpanId()) - && hasChildSpan(trace, "child2", parent.getSpanId()) - && hasChildSpan(trace, "child3", parent.getSpanId())) + .filter(parent -> + hasChildSpan(trace, "child1", parent.getSpanId()) + && hasChildSpan(trace, "child2", parent.getSpanId()) + && hasChildSpan(trace, "child3", parent.getSpanId())) .isPresent(); } diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/NestedTasksTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/NestedTasksTest.java index fad04954019..e060db5e531 100644 --- a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/NestedTasksTest.java +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/NestedTasksTest.java @@ -28,16 +28,13 @@ protected Predicate checkTrace() { return trace -> trace.getSpans().size() == 5 && findRootSpan(trace, "parent") - .filter( - parent -> - findChildSpan(trace, "child1", parent.getSpanId()) - .filter( - child1 -> - hasChildSpan(trace, "child2", parent.getSpanId()) - && hasChildSpan(trace, "great-child1-1", child1.getSpanId()) - && hasChildSpan( - trace, "great-child1-2", child1.getSpanId())) - .isPresent()) + .filter(parent -> + findChildSpan(trace, "child1", parent.getSpanId()) + .filter(child1 -> + hasChildSpan(trace, "child2", parent.getSpanId()) + && hasChildSpan(trace, "great-child1-1", child1.getSpanId()) + && hasChildSpan(trace, "great-child1-2", child1.getSpanId())) + .isPresent()) .isPresent(); } diff --git a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.java b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.java index e085c754f43..9f70adbaa50 100644 --- a/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.java +++ b/dd-smoke-tests/concurrent/java-25/src/test/java/datadog/smoketest/concurrent/ScheduledForkJoinTaskTest.java @@ -34,17 +34,15 @@ void propagatesDelayedContextAcrossExecutorsAndClearsItAfterExecution() { assertTrue(traces.stream().anyMatch(checkTrace()), "Missing scheduled task trace"); assertTrue( traces.stream() - .anyMatch( - trace -> - trace.getSpans().size() == 1 - && findRootSpan(trace, "unrelated-forkjoin").isPresent()), + .anyMatch(trace -> + trace.getSpans().size() == 1 + && findRootSpan(trace, "unrelated-forkjoin").isPresent()), "Missing unrelated fork-join trace"); assertTrue( traces.stream() - .anyMatch( - trace -> - trace.getSpans().size() == 1 - && findRootSpan(trace, "unrelated-executor").isPresent()), + .anyMatch(trace -> + trace.getSpans().size() == 1 + && findRootSpan(trace, "unrelated-executor").isPresent()), "Missing unrelated executor trace"); } }