Skip to content

Commit 93c14b0

Browse files
sarahchen6AlexeyKuznetsov-DDnikita-tkachenko-datadog
authored
Add Java 25 support to Maven smoke tests (#9481)
* Upgrade jacoco to latest version * Upgrade pom.xml versions to support Java 25 * Attempt to fix JDK 25 support. * Rollback dependency changes * Fix Jacoco total probe count race * Restore JUnit 4 in JDK25 test as framework version is present in test fixtures * Remove JDK25-specific test: original test should work under JDK25 with the new Jacoco version * Add coverage exclusion * Run Jacoco Maven smoke test on JDK 25 * Fix Spock test case to run with JDK 25 * Remove max support Java version requirement --------- Co-authored-by: Alexey Kuznetsov <alexey.kuznetsov@datadoghq.com> Co-authored-by: Nikita Tkachenko <nikita.tkachenko@datadoghq.com>
1 parent 9976186 commit 93c14b0

File tree

6 files changed

+78
-19
lines changed

6 files changed

+78
-19
lines changed

dd-java-agent/instrumentation/jacoco/src/main/java/datadog/trace/instrumentation/jacoco/ClassInstrumenterInstrumentation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public static class VisitTotalProbeCountAdvice {
5252
static void enter(
5353
@Advice.FieldValue(value = "className") final String className,
5454
@Advice.Argument(0) int count) {
55-
CoveragePerTestBridge.getCoverageStoreRegistry().setTotalProbeCount(className, count);
55+
CoveragePerTestBridge.setTotalProbeCount(className, count);
5656
}
5757
}
5858
}

dd-smoke-tests/maven/src/test/groovy/datadog/smoketest/MavenSmokeTest.groovy

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package datadog.smoketest
22

3-
import datadog.environment.JavaVirtualMachine
3+
44
import datadog.trace.api.civisibility.CIConstants
55
import datadog.trace.api.config.CiVisibilityConfig
66
import datadog.trace.api.config.GeneralConfig
@@ -9,13 +9,11 @@ import okhttp3.OkHttpClient
99
import okhttp3.Request
1010
import okhttp3.Response
1111
import org.apache.maven.wrapper.MavenWrapperMain
12-
import org.junit.jupiter.api.Assumptions
1312
import org.slf4j.Logger
1413
import org.slf4j.LoggerFactory
1514
import org.w3c.dom.Document
1615
import org.w3c.dom.NodeList
1716
import spock.lang.AutoCleanup
18-
import spock.lang.IgnoreIf
1917
import spock.lang.Shared
2018
import spock.lang.TempDir
2119
import spock.util.environment.Jvm
@@ -27,6 +25,8 @@ import java.nio.file.attribute.BasicFileAttributes
2725
import java.util.concurrent.TimeUnit
2826
import java.util.concurrent.TimeoutException
2927

28+
import static org.junit.jupiter.api.Assumptions.assumeTrue
29+
3030
class MavenSmokeTest extends CiVisibilitySmokeTest {
3131

3232
private static final Logger LOGGER = LoggerFactory.getLogger(MavenSmokeTest)
@@ -50,12 +50,9 @@ class MavenSmokeTest extends CiVisibilitySmokeTest {
5050
mockBackend.reset()
5151
}
5252

53-
@IgnoreIf(reason = "TODO: Fix for Java 25. test_successful_maven_run_junit_platform_runner jacoco coverage is failing, possibly due to lack of jacoco support for Java 25. Recommended fix is to update DEFAULT_CIVISIBILITY_JACOCO_PLUGIN_VERSION when support is added: https://github.com/jacoco/jacoco/releases", value = {
54-
JavaVirtualMachine.isJavaVersionAtLeast(25)
55-
})
5653
def "test #projectName, v#mavenVersion"() {
5754
println "Starting: ${projectName} ${mavenVersion}"
58-
Assumptions.assumeTrue(Jvm.current.isJavaVersionCompatible(minSupportedJavaVersion),
55+
assumeTrue(Jvm.current.isJavaVersionCompatible(minSupportedJavaVersion),
5956
"Current JVM " + Jvm.current.javaVersion + " is not compatible with minimum required version " + minSupportedJavaVersion)
6057

6158
givenWrapperPropertiesFile(mavenVersion)
@@ -161,7 +158,7 @@ class MavenSmokeTest extends CiVisibilitySmokeTest {
161158
verifyTestOrder(mockBackend.waitForEvents(eventsNumber), expectedOrder)
162159

163160
where:
164-
testcaseName | projectName | mavenVersion | surefireVersion | flakyTests | knownTests | expectedOrder | eventsNumber
161+
testcaseName | projectName | mavenVersion | surefireVersion | flakyTests | knownTests | expectedOrder | eventsNumber
165162
"junit4-provider" | "test_successful_maven_run_junit4_class_ordering" | "3.9.9" | "3.0.0" | [
166163
test("datadog.smoke.TestSucceedB", "test_succeed"),
167164
test("datadog.smoke.TestSucceedB", "test_succeed_another"),
@@ -177,15 +174,15 @@ class MavenSmokeTest extends CiVisibilitySmokeTest {
177174
test("datadog.smoke.TestSucceedA", "test_succeed"),
178175
test("datadog.smoke.TestSucceedB", "test_succeed"),
179176
test("datadog.smoke.TestSucceedB", "test_succeed_another")
180-
] | 15
177+
] | 15
181178
"junit47-provider" | "test_successful_maven_run_junit4_class_ordering_parallel" | "3.9.9" | "3.0.0" | [test("datadog.smoke.TestSucceedC", "test_succeed")] | [
182179
test("datadog.smoke.TestSucceedC", "test_succeed"),
183180
test("datadog.smoke.TestSucceedA", "test_succeed")
184181
] | [
185182
test("datadog.smoke.TestSucceedB", "test_succeed"),
186183
test("datadog.smoke.TestSucceedC", "test_succeed"),
187184
test("datadog.smoke.TestSucceedA", "test_succeed")
188-
] | 12
185+
] | 12
189186
"junit4-provider-latest-surefire" | "test_successful_maven_run_junit4_class_ordering" | "3.9.9" | getLatestMavenSurefireVersion() | [
190187
test("datadog.smoke.TestSucceedB", "test_succeed"),
191188
test("datadog.smoke.TestSucceedB", "test_succeed_another"),
@@ -201,15 +198,15 @@ class MavenSmokeTest extends CiVisibilitySmokeTest {
201198
test("datadog.smoke.TestSucceedA", "test_succeed"),
202199
test("datadog.smoke.TestSucceedB", "test_succeed"),
203200
test("datadog.smoke.TestSucceedB", "test_succeed_another")
204-
] | 15
201+
] | 15
205202
"junit47-provider-latest-surefire" | "test_successful_maven_run_junit4_class_ordering_parallel" | "3.9.9" | getLatestMavenSurefireVersion() | [test("datadog.smoke.TestSucceedC", "test_succeed")] | [
206203
test("datadog.smoke.TestSucceedC", "test_succeed"),
207204
test("datadog.smoke.TestSucceedA", "test_succeed")
208205
] | [
209206
test("datadog.smoke.TestSucceedB", "test_succeed"),
210207
test("datadog.smoke.TestSucceedC", "test_succeed"),
211208
test("datadog.smoke.TestSucceedA", "test_succeed")
212-
] | 12
209+
] | 12
213210
}
214211

215212
def "test service name is propagated to child processes"() {

dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_junit_platform_runner/pom.xml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@
5454
<type>pom</type>
5555
<scope>import</scope>
5656
</dependency>
57+
<dependency>
58+
<groupId>org.apache.groovy</groupId>
59+
<artifactId>groovy-bom</artifactId>
60+
<version>4.0.28</version>
61+
<type>pom</type>
62+
<scope>import</scope>
63+
</dependency>
5764
</dependencies>
5865
</dependencyManagement>
5966

@@ -73,14 +80,19 @@
7380
<artifactId>spock-core</artifactId>
7481
<scope>test</scope>
7582
</dependency>
83+
<dependency>
84+
<groupId>org.apache.groovy</groupId>
85+
<artifactId>groovy</artifactId>
86+
<scope>test</scope>
87+
</dependency>
7688
</dependencies>
7789

7890
<build>
7991
<plugins>
8092
<plugin>
8193
<groupId>org.codehaus.gmavenplus</groupId>
8294
<artifactId>gmavenplus-plugin</artifactId>
83-
<version>3.0.2</version>
95+
<version>4.2.1</version>
8496
<executions>
8597
<execution>
8698
<goals>

dd-smoke-tests/maven/src/test/resources/test_successful_maven_run_with_jacoco_and_argline/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
<plugin>
6363
<groupId>org.jacoco</groupId>
6464
<artifactId>jacoco-maven-plugin</artifactId>
65-
<version>0.8.10</version>
65+
<version>0.8.13</version>
6666
<executions>
6767
<execution>
6868
<id>default-prepare-agent</id>

internal-api/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ val excludedClassesCoverage by extra(
123123
"datadog.trace.api.civisibility.config.TestSourceData",
124124
"datadog.trace.api.civisibility.config.LibraryCapability",
125125
"datadog.trace.api.civisibility.coverage.CoveragePerTestBridge",
126+
"datadog.trace.api.civisibility.coverage.CoveragePerTestBridge.TotalProbeCount",
126127
"datadog.trace.api.civisibility.coverage.CoveragePercentageBridge",
127128
"datadog.trace.api.civisibility.coverage.NoOpCoverageStore",
128129
"datadog.trace.api.civisibility.coverage.NoOpCoverageStore.Factory",

internal-api/src/main/java/datadog/trace/api/civisibility/coverage/CoveragePerTestBridge.java

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,68 @@
22

33
import datadog.trace.api.civisibility.InstrumentationTestBridge;
44
import datadog.trace.api.civisibility.domain.TestContext;
5+
import java.util.ArrayDeque;
6+
import java.util.Queue;
7+
import javax.annotation.Nonnull;
8+
import javax.annotation.concurrent.GuardedBy;
59

610
public abstract class CoveragePerTestBridge {
711

812
private static final ThreadLocal<CoverageProbes> COVERAGE_PROBES = new ThreadLocal<>();
913

1014
private static volatile CoverageStore.Registry COVERAGE_STORE_REGISTRY;
15+
private static final Object COVERAGE_STORE_REGISTRY_LOCK = new Object();
1116

12-
public static void registerCoverageStoreRegistry(CoverageStore.Registry coverageStoreRegistry) {
13-
COVERAGE_STORE_REGISTRY = coverageStoreRegistry;
17+
@GuardedBy("COVERAGE_STORE_REGISTRY_LOCK")
18+
private static final Queue<TotalProbeCount> DEFERRED_PROBE_COUNTS = new ArrayDeque<>();
19+
20+
public static void registerCoverageStoreRegistry(
21+
@Nonnull CoverageStore.Registry coverageStoreRegistry) {
22+
synchronized (COVERAGE_STORE_REGISTRY_LOCK) {
23+
while (!DEFERRED_PROBE_COUNTS.isEmpty()) {
24+
TotalProbeCount c = DEFERRED_PROBE_COUNTS.poll();
25+
coverageStoreRegistry.setTotalProbeCount(c.className, c.count);
26+
}
27+
COVERAGE_STORE_REGISTRY = coverageStoreRegistry;
28+
}
1429
}
1530

16-
public static CoverageStore.Registry getCoverageStoreRegistry() {
17-
return COVERAGE_STORE_REGISTRY;
31+
/**
32+
* {@link #COVERAGE_STORE_REGISTRY} is set when CI Visibility is initialized. It is possible, that
33+
* core/internal JDK classes are loaded and transformed by Jacoco before this happens. As the
34+
* result this method may be called when {@link #COVERAGE_STORE_REGISTRY} is still {@code null}.
35+
*
36+
* <p>While instrumenting core/internal JDK classes with Jacoco makes little sense, we do not
37+
* always have the control over the users' Jacoco {@code includes} setting, therefore we have to
38+
* account for this case and support it.
39+
*
40+
* <p>If this method finds {@link #COVERAGE_STORE_REGISTRY} to be {@code null}, the probe counts
41+
* are saved in {@link #DEFERRED_PROBE_COUNTS} to be processed when {@link
42+
* #COVERAGE_STORE_REGISTRY} is set.
43+
*/
44+
public static void setTotalProbeCount(String className, int totalProbeCount) {
45+
if (COVERAGE_STORE_REGISTRY != null) {
46+
COVERAGE_STORE_REGISTRY.setTotalProbeCount(className, totalProbeCount);
47+
return;
48+
}
49+
50+
synchronized (COVERAGE_STORE_REGISTRY_LOCK) {
51+
if (COVERAGE_STORE_REGISTRY != null) {
52+
COVERAGE_STORE_REGISTRY.setTotalProbeCount(className, totalProbeCount);
53+
} else {
54+
DEFERRED_PROBE_COUNTS.offer(new TotalProbeCount(className, totalProbeCount));
55+
}
56+
}
57+
}
58+
59+
private static final class TotalProbeCount {
60+
private final String className;
61+
private final int count;
62+
63+
private TotalProbeCount(String className, int count) {
64+
this.className = className;
65+
this.count = count;
66+
}
1867
}
1968

2069
/* This method is referenced by name in bytecode added in jacoco instrumentation module (see datadog.trace.instrumentation.jacoco.ProbeInserterInstrumentation.InsertProbeAdvice) */

0 commit comments

Comments
 (0)