Skip to content

Commit f936c01

Browse files
committed
Fix class-level execution conditions on GraalVM (#3785)
* Update to latest version of native build tools * Track descendants of skipped containers * Disable integration test if GRAALVM_HOME env var is not set Fixes #3745. (cherry picked from commit 8b24ca8)
1 parent 76b7c05 commit f936c01

File tree

7 files changed

+86
-22
lines changed

7 files changed

+86
-22
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-5.10.3.adoc

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ on GitHub.
1717

1818
* The `junit-platform-suite-engine` now includes configuration provided via
1919
`@ConfigurationParameter` when selecting tests by `UniqueId`.
20+
* In order to support using `@EnabledInNativeImage` on test classes,
21+
`UniqueIdTrackingListener` now tracks descendants of skipped test containers.
2022

2123
==== Deprecations and Breaking Changes
2224

junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java

+22-4
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ public class UniqueIdTrackingListener implements TestExecutionListener {
130130
private final List<String> uniqueIds = new ArrayList<>();
131131

132132
private boolean enabled;
133+
private TestPlan testPlan;
133134

134135
public UniqueIdTrackingListener() {
135136
// to avoid missing-explicit-ctor warning
@@ -138,22 +139,38 @@ public UniqueIdTrackingListener() {
138139
@Override
139140
public void testPlanExecutionStarted(TestPlan testPlan) {
140141
this.enabled = testPlan.getConfigurationParameters().getBoolean(LISTENER_ENABLED_PROPERTY_NAME).orElse(false);
142+
this.testPlan = testPlan;
141143
}
142144

143145
@Override
144146
public void executionSkipped(TestIdentifier testIdentifier, String reason) {
145-
trackTestUid(testIdentifier);
147+
if (this.enabled) {
148+
// When a container is skipped, there are no events for its children.
149+
// Therefore, in order to track them, we need to traverse the subtree.
150+
trackTestUidRecursively(testIdentifier);
151+
}
146152
}
147153

148154
@Override
149155
public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
150-
trackTestUid(testIdentifier);
156+
if (this.enabled) {
157+
trackTestUid(testIdentifier);
158+
}
159+
}
160+
161+
private void trackTestUidRecursively(TestIdentifier testIdentifier) {
162+
boolean tracked = trackTestUid(testIdentifier);
163+
if (!tracked) {
164+
this.testPlan.getChildren(testIdentifier).forEach(this::trackTestUidRecursively);
165+
}
151166
}
152167

153-
private void trackTestUid(TestIdentifier testIdentifier) {
154-
if (this.enabled && testIdentifier.isTest()) {
168+
private boolean trackTestUid(TestIdentifier testIdentifier) {
169+
if (testIdentifier.isTest()) {
155170
this.uniqueIds.add(testIdentifier.getUniqueId());
171+
return true;
156172
}
173+
return false;
157174
}
158175

159176
@Override
@@ -178,6 +195,7 @@ public void testPlanExecutionFinished(TestPlan testPlan) {
178195
logger.error(ex, () -> "Failed to write unique IDs to output file " + outputFile.toAbsolutePath());
179196
}
180197
}
198+
this.testPlan = null;
181199
}
182200

183201
private Path createOutputFile(ConfigurationParameters configurationParameters) {

platform-tests/src/test/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListenerIntegrationTests.java

+28-2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.assertj.core.api.Condition;
4747
import org.junit.jupiter.api.Disabled;
4848
import org.junit.jupiter.api.DynamicTest;
49+
import org.junit.jupiter.api.Nested;
4950
import org.junit.jupiter.api.Test;
5051
import org.junit.jupiter.api.TestFactory;
5152
import org.junit.platform.engine.TestDescriptor;
@@ -54,6 +55,7 @@
5455
import org.junit.platform.launcher.LauncherDiscoveryRequest;
5556
import org.junit.platform.launcher.TestExecutionListener;
5657
import org.junit.platform.launcher.TestIdentifier;
58+
import org.junit.platform.launcher.TestPlan;
5759
import org.junit.platform.launcher.core.LauncherFactory;
5860
import org.junit.platform.testkit.engine.EngineTestKit;
5961
import org.junit.platform.testkit.engine.Event;
@@ -79,9 +81,10 @@ class UniqueIdTrackingListenerIntegrationTests {
7981
private static final String testD = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase3]/[method:testD()]";
8082
private static final String testE = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase4]/[method:testE()]";
8183
private static final String testF = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$TestCase4]/[method:testF()]";
84+
private static final String testG = "[engine:junit-jupiter]/[class:org.junit.platform.launcher.listeners.UniqueIdTrackingListenerIntegrationTests$DisabledTestCase]/[nested-class:Inner]/[method:testG()]";
8285

8386
private static final String[] expectedUniqueIds = { passingTest, skippedTest, abortedTest, failingTest,
84-
dynamicTest1, dynamicTest2, testA, testB };
87+
dynamicTest1, dynamicTest2, testA, testB, testG };
8588

8689
private static final String[] expectedConcurrentUniqueIds = { testA, testB, testC, testD, testE, testF };
8790

@@ -225,11 +228,21 @@ private static List<String> executeTests(Map<String, String> configurationParame
225228
.build();
226229
LauncherFactory.create().execute(request, new TestExecutionListener() {
227230

231+
private TestPlan testPlan;
232+
233+
@Override
234+
public void testPlanExecutionStarted(TestPlan testPlan) {
235+
this.testPlan = testPlan;
236+
}
237+
228238
@Override
229239
public void executionSkipped(TestIdentifier testIdentifier, String reason) {
230240
if (testIdentifier.isTest()) {
231241
uniqueIds.add(testIdentifier.getUniqueId());
232242
}
243+
else {
244+
this.testPlan.getChildren(testIdentifier).forEach(child -> executionSkipped(child, reason));
245+
}
233246
}
234247

235248
@Override
@@ -243,7 +256,8 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult
243256
}
244257

245258
private static ClassSelector[] selectClasses() {
246-
return new ClassSelector[] { selectClass(TestCase1.class), selectClass(TestCase2.class) };
259+
return new ClassSelector[] { selectClass(TestCase1.class), selectClass(TestCase2.class),
260+
selectClass(DisabledTestCase.class) };
247261
}
248262

249263
private static Stream<Path> findFiles(String dir, String prefix) throws IOException {
@@ -340,4 +354,16 @@ void testF() {
340354
}
341355
}
342356

357+
@Disabled
358+
static class DisabledTestCase {
359+
360+
@Nested
361+
class Inner {
362+
363+
@Test
364+
void testG() {
365+
}
366+
}
367+
}
368+
343369
}

platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts

-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ tasks.test {
3131
graalvmNative {
3232
binaries {
3333
named("test") {
34-
buildArgs.add("--initialize-at-build-time=org.junit.platform.launcher.core.LauncherConfig")
35-
buildArgs.add("--initialize-at-build-time=org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter")
3634
buildArgs.add("-H:+ReportExceptionStackTraces")
3735
}
3836
}

platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pluginManagement {
22
plugins {
3-
id("org.graalvm.buildtools.native") version "0.9.13"
3+
id("org.graalvm.buildtools.native") version "0.10.1"
44
}
55
repositories {
66
mavenCentral()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2015-2024 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package com.example.project;
12+
13+
import org.junit.jupiter.api.Nested;
14+
import org.junit.jupiter.api.Test;
15+
import org.junit.jupiter.api.condition.EnabledInNativeImage;
16+
17+
@EnabledInNativeImage
18+
class ClassLevelAnnotationTests {
19+
@Nested
20+
class Inner {
21+
@Test
22+
void test() {
23+
}
24+
}
25+
}

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GraalVmStarterTests.java

+8-13
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,25 @@
1010

1111
package platform.tooling.support.tests;
1212

13+
import static org.assertj.core.api.Assertions.assertThat;
1314
import static org.junit.jupiter.api.Assertions.assertEquals;
1415
import static org.junit.jupiter.api.Assertions.assertFalse;
15-
import static org.junit.jupiter.api.Assertions.assertTrue;
16-
import static org.junit.jupiter.api.Assumptions.assumeFalse;
17-
import static platform.tooling.support.tests.XmlAssertions.verifyContainsExpectedStartedOpenTestReport;
1816

1917
import java.nio.file.Paths;
2018
import java.time.Duration;
2119

2220
import de.sormuras.bartholdy.tool.GradleWrapper;
2321

2422
import org.junit.jupiter.api.Test;
23+
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
2524

2625
import platform.tooling.support.MavenRepo;
2726
import platform.tooling.support.Request;
2827

2928
/**
3029
* @since 1.9.1
3130
*/
31+
@EnabledIfEnvironmentVariable(named = "GRAALVM_HOME", matches = ".+")
3232
class GraalVmStarterTests {
3333

3434
@Test
@@ -38,23 +38,18 @@ void runsTestsInNativeImage() {
3838
.setProject("graalvm-starter") //
3939
.addArguments("-Dmaven.repo=" + MavenRepo.dir()) //
4040
.addArguments("javaToolchains", "nativeTest", "--no-daemon", "--stacktrace") //
41-
.addArguments("-Porg.gradle.java.installations.fromEnv=GRAALVM_HOME") //
4241
.setTimeout(Duration.ofMinutes(10)) //
4342
.build();
4443

4544
var result = request.run();
4645

4746
assertFalse(result.isTimedOut(), () -> "tool timed out: " + result);
4847

49-
assumeFalse(
50-
result.getOutputLines("err").stream().anyMatch(
51-
line -> line.contains("No locally installed toolchains match")),
52-
"Abort test if GraalVM is not installed");
53-
5448
assertEquals(0, result.getExitCode());
55-
assertTrue(result.getOutputLines("out").stream().anyMatch(line -> line.contains("BUILD SUCCESSFUL")));
56-
57-
var testResultsDir = Request.WORKSPACE.resolve(request.getWorkspace()).resolve("build/test-results/test");
58-
verifyContainsExpectedStartedOpenTestReport(testResultsDir);
49+
assertThat(result.getOutputLines("out")) //
50+
.anyMatch(line -> line.contains("CalculatorTests > 1 + 1 = 2 SUCCESSFUL")) //
51+
.anyMatch(line -> line.contains("CalculatorTests > 1 + 100 = 101 SUCCESSFUL")) //
52+
.anyMatch(line -> line.contains("ClassLevelAnnotationTests$Inner > test() SUCCESSFUL")) //
53+
.anyMatch(line -> line.contains("BUILD SUCCESSFUL"));
5954
}
6055
}

0 commit comments

Comments
 (0)