Skip to content

Commit 06737b9

Browse files
authored
Merge pull request #811 from graalvm/vj/support-compatibility-mode-preserve
Support compatibility mode in GraalVM
2 parents ffb728f + 1ba5ebc commit 06737b9

10 files changed

Lines changed: 85 additions & 167 deletions

File tree

common/junit-platform-native/src/main/java/org/graalvm/junit/platform/JUnitPlatformFeature.java

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,9 @@
4242
package org.graalvm.junit.platform;
4343

4444
import org.graalvm.junit.platform.config.core.PluginConfigProvider;
45-
import org.graalvm.nativeimage.ImageSingletons;
4645
import org.graalvm.nativeimage.hosted.Feature;
4746
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization;
4847
import org.graalvm.nativeimage.hosted.RuntimeReflection;
49-
5048
import org.junit.platform.engine.DiscoverySelector;
5149
import org.junit.platform.engine.discovery.DiscoverySelectors;
5250
import org.junit.platform.engine.discovery.UniqueIdSelector;
@@ -77,32 +75,21 @@
7775
@SuppressWarnings("unused")
7876
public final class JUnitPlatformFeature implements Feature {
7977

80-
public final boolean debug = System.getProperty("debug") != null;
81-
private static final NativeImageConfigurationImpl nativeImageConfigImpl = new NativeImageConfigurationImpl();
8278
private final ServiceLoader<PluginConfigProvider> extensionConfigProviders = ServiceLoader.load(PluginConfigProvider.class);
8379

84-
public static void debug(String format, Object... args) {
85-
if (debug()) {
86-
System.out.printf("[Debug] " + format + "%n", args);
87-
}
88-
}
89-
9080
@Override
9181
public void afterRegistration(AfterRegistrationAccess access) {
92-
extensionConfigProviders.forEach(p -> p.initialize(access.getApplicationClassLoader(), nativeImageConfigImpl));
93-
}
94-
95-
private static boolean debug() {
96-
return ImageSingletons.lookup(JUnitPlatformFeature.class).debug;
82+
extensionConfigProviders.forEach(p -> p.initialize(access.getApplicationClassLoader()));
9783
}
9884

9985
@Override
10086
public void duringSetup(DuringSetupAccess access) {
101-
forEachProvider(p -> p.onLoad(nativeImageConfigImpl));
87+
forEachProvider(PluginConfigProvider::onLoad);
10288
}
10389

10490
@Override
10591
public void beforeAnalysis(BeforeAnalysisAccess access) {
92+
RuntimeClassInitialization.initializeAtBuildTime("org.graalvm.junit.platform.JUnitPlatformFeatureUtils");
10693
/* Before GraalVM version 22 we couldn't have classes initialized at run-time
10794
* that are also used at build-time but not added to the image heap */
10895
if (Runtime.version().feature() <= 21) {
@@ -141,7 +128,8 @@ private List<? extends DiscoverySelector> getSelectors() {
141128
return selectors;
142129
}
143130
} catch (Exception ex) {
144-
debug("Failed to read UIDs from UniqueIdTrackingListener output files: " + ex.getMessage());
131+
String format = "Failed to read UIDs from UniqueIdTrackingListener output files: " + ex.getMessage();
132+
JUnitPlatformFeatureUtils.debug(format);
145133
}
146134

147135
throw new RuntimeException("Cannot compute test selectors from test ids.");
@@ -156,9 +144,9 @@ private void registerTestClassesForReflection(List<? extends DiscoverySelector>
156144
.build();
157145

158146
TestClassRegistrar testClassRegistrar = new TestClassRegistrar(clazz -> {
159-
debug("Registering test class for reflection: %s", clazz.getName());
160-
nativeImageConfigImpl.registerAllClassMembersForReflection(clazz);
161-
forEachProvider(p -> p.onTestClassRegistered(clazz, nativeImageConfigImpl));
147+
JUnitPlatformFeatureUtils.debug("Registering test class for reflection: %s", clazz.getName());
148+
JUnitPlatformFeatureUtils.registerAllClassMembersForReflection(clazz);
149+
forEachProvider(p -> p.onTestClassRegistered(clazz));
162150
});
163151

164152
Launcher launcher = LauncherFactory.create();
@@ -195,8 +183,8 @@ private static Stream<Path> findFiles(Path dir, String prefix) throws IOExceptio
195183
return Stream.empty();
196184
}
197185
return Files.find(dir, Integer.MAX_VALUE,
198-
(path, basicFileAttributes) -> (basicFileAttributes.isRegularFile()
199-
&& path.getFileName().toString().startsWith(prefix)));
186+
(path, basicFileAttributes) -> (basicFileAttributes.isRegularFile()
187+
&& path.getFileName().toString().startsWith(prefix)));
200188
}
201189

202190
private static void registerClassesForHamcrestSupport(BeforeAnalysisAccess access) {
@@ -239,4 +227,5 @@ private static void initializeClassesForJDK21OrEarlier() {
239227
throw new RuntimeException("Failed to process build time initializations for JDK 21 or earlier");
240228
}
241229
}
230+
242231
}

common/junit-platform-native/src/main/java/org/graalvm/junit/platform/NativeImageConfigurationImpl.java renamed to common/junit-platform-native/src/main/java/org/graalvm/junit/platform/JUnitPlatformFeatureUtils.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2026, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -38,29 +38,29 @@
3838
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3939
* SOFTWARE.
4040
*/
41-
4241
package org.graalvm.junit.platform;
4342

44-
import org.graalvm.junit.platform.config.core.NativeImageConfiguration;
43+
import org.graalvm.nativeimage.ImageInfo;
4544
import org.graalvm.nativeimage.hosted.RuntimeReflection;
4645

47-
import java.lang.reflect.Executable;
48-
import java.lang.reflect.Field;
49-
50-
class NativeImageConfigurationImpl implements NativeImageConfiguration {
51-
52-
@Override
53-
public void registerForReflection(Class<?>... classes) {
54-
RuntimeReflection.register(classes);
55-
}
46+
public class JUnitPlatformFeatureUtils {
47+
public static final boolean debug = System.getProperty("org.graalvm.junit.platform.debug") != null;
5648

57-
@Override
58-
public void registerForReflection(Executable... methods) {
59-
RuntimeReflection.register(methods);
49+
public static void debug(String format, Object... args) {
50+
if (JUnitPlatformFeatureUtils.debug) {
51+
System.out.printf("[Debug] " + format + "%n", args);
52+
}
6053
}
6154

62-
@Override
63-
public void registerForReflection(Field... fields) {
64-
RuntimeReflection.register(fields);
55+
public static void registerAllClassMembersForReflection(Class<?>... classes) {
56+
if (ImageInfo.inImageBuildtimeCode()) {
57+
for (Class<?> clazz : classes) {
58+
JUnitPlatformFeatureUtils.debug("[Native Image Configuration] Registering for reflection: %s", clazz.getName());
59+
RuntimeReflection.register(clazz);
60+
RuntimeReflection.register(clazz.getDeclaredConstructors());
61+
RuntimeReflection.register(clazz.getDeclaredMethods());
62+
RuntimeReflection.register(clazz.getDeclaredFields());
63+
}
64+
}
6565
}
6666
}

common/junit-platform-native/src/main/java/org/graalvm/junit/platform/config/core/NativeImageConfiguration.java

Lines changed: 0 additions & 71 deletions
This file was deleted.

common/junit-platform-native/src/main/java/org/graalvm/junit/platform/config/core/PluginConfigProvider.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,13 @@
4747
public abstract class PluginConfigProvider {
4848

4949
protected ClassLoader applicationClassLoader;
50-
protected NativeImageConfiguration nativeImageConfigImpl;
5150

51+
public abstract void onLoad();
5252

53-
public abstract void onLoad(NativeImageConfiguration config);
53+
public abstract void onTestClassRegistered(Class<?> testClass);
5454

55-
public abstract void onTestClassRegistered(Class<?> testClass, NativeImageConfiguration registry);
56-
57-
public final void initialize(ClassLoader classLoader, NativeImageConfiguration nic) {
55+
public final void initialize(ClassLoader classLoader) {
5856
applicationClassLoader = classLoader;
59-
nativeImageConfigImpl = nic;
6057
}
6158

6259
@SuppressWarnings("unchecked")

common/junit-platform-native/src/main/java/org/graalvm/junit/platform/config/jupiter/JupiterConfigProvider.java

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@
4141

4242
package org.graalvm.junit.platform.config.jupiter;
4343

44-
import org.graalvm.junit.platform.config.core.NativeImageConfiguration;
44+
import org.graalvm.junit.platform.JUnitPlatformFeatureUtils;
4545
import org.graalvm.junit.platform.config.core.PluginConfigProvider;
4646
import org.graalvm.junit.platform.config.util.AnnotationUtils;
47+
import org.graalvm.junit.platform.config.util.Utils;
4748
import org.junit.jupiter.api.DisplayNameGeneration;
4849
import org.junit.jupiter.api.IndicativeSentencesGeneration;
4950
import org.junit.jupiter.api.TestMethodOrder;
@@ -61,56 +62,55 @@
6162
import java.util.ArrayList;
6263
import java.util.List;
6364

64-
import static org.graalvm.junit.platform.JUnitPlatformFeature.debug;
65+
import static org.graalvm.junit.platform.JUnitPlatformFeatureUtils.debug;
6566

6667
public class JupiterConfigProvider extends PluginConfigProvider {
6768

6869
@Override
69-
public void onLoad(NativeImageConfiguration config) {
70+
public void onLoad() {
7071
/* Provide support for Timeout annotation */
71-
config.registerAllClassMembersForReflection(
72+
JUnitPlatformFeatureUtils.registerAllClassMembersForReflection(Utils.toClasses(
7273
"org.junit.jupiter.engine.extension.TimeoutExtension$ExecutorResource",
73-
"org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource"
74-
);
74+
"org.junit.jupiter.engine.extension.TimeoutInvocationFactory$SingleThreadExecutorResource"));
7575
}
7676

7777
@Override
78-
public void onTestClassRegistered(Class<?> testClass, NativeImageConfiguration registry) {
78+
public void onTestClassRegistered(Class<?> testClass) {
7979
/* Provide support for various annotations */
8080

8181
/* Annotations from org.junit.jupiter.api */
8282
try {
83-
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, TestMethodOrder.class, TestMethodOrder::value);
84-
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, ExtendWith.class, ExtendWith::value);
85-
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, DisplayNameGeneration.class, DisplayNameGeneration::value);
86-
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, IndicativeSentencesGeneration.class, IndicativeSentencesGeneration::generator);
87-
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, EnabledIf.class, JupiterConfigProvider::handleEnabledIf);
88-
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, DisabledIf.class, JupiterConfigProvider::handleDisabledIf);
83+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, TestMethodOrder.class, TestMethodOrder::value);
84+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, ExtendWith.class, ExtendWith::value);
85+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, DisplayNameGeneration.class, DisplayNameGeneration::value);
86+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, IndicativeSentencesGeneration.class, IndicativeSentencesGeneration::generator);
87+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, EnabledIf.class, JupiterConfigProvider::handleEnabledIf);
88+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, DisabledIf.class, JupiterConfigProvider::handleDisabledIf);
8989
} catch (NoClassDefFoundError e) {
9090
debug("Cannot register annotations %s from 'org.junit.jupiter.api'. " +
91-
"Please verify that you have dependency that includes 'org.junit.jupiter.api' if you want to use these annotations.",
92-
List.of("TestMethodOrder", "ExtendWith", "DisplayNameGeneration", "IndicativeSentencesGeneration", "EnabledIf", "DisabledIf"));
91+
"Please verify that you have dependency that includes 'org.junit.jupiter.api' if you want to use these annotations.",
92+
List.of("TestMethodOrder", "ExtendWith", "DisplayNameGeneration", "IndicativeSentencesGeneration", "EnabledIf", "DisabledIf"));
9393
}
9494

9595
/* Annotations from org.junit.jupiter.params */
9696
try {
97-
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, ArgumentsSource.class, ArgumentsSource::value);
98-
AnnotationUtils.forEachAnnotatedMethodParameter(testClass, ConvertWith.class, annotation -> registry.registerAllClassMembersForReflection(annotation.value()));
99-
AnnotationUtils.forEachAnnotatedMethodParameter(testClass, AggregateWith.class, annotation -> registry.registerAllClassMembersForReflection(annotation.value()));
100-
AnnotationUtils.forEachAnnotatedMethod(testClass, EnumSource.class, (m, annotation) -> handleEnumSource(m, annotation, registry));
101-
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, MethodSource.class, JupiterConfigProvider::handleMethodSource);
97+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, ArgumentsSource.class, ArgumentsSource::value);
98+
AnnotationUtils.forEachAnnotatedMethodParameter(testClass, ConvertWith.class, annotation -> JUnitPlatformFeatureUtils.registerAllClassMembersForReflection(annotation.value()));
99+
AnnotationUtils.forEachAnnotatedMethodParameter(testClass, AggregateWith.class, annotation -> JUnitPlatformFeatureUtils.registerAllClassMembersForReflection(annotation.value()));
100+
AnnotationUtils.forEachAnnotatedMethod(testClass, EnumSource.class, (m, annotation) -> handleEnumSource(m, annotation));
101+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, MethodSource.class, JupiterConfigProvider::handleMethodSource);
102102

103103
// special case because the class might not be available because the annotation was introduced in JUnit 5.13
104104
try {
105-
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, FieldSource.class, JupiterConfigProvider::handleFieldSource);
105+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, FieldSource.class, JupiterConfigProvider::handleFieldSource);
106106
} catch (NoClassDefFoundError e) {
107107
debug("Cannot register @FieldSource annotation from org.junit.jupiter.params. " +
108108
"Please verify that you have this dependency (with version greater than JUnit 5.13) if you want to use this annotation.");
109109
}
110110
} catch (NoClassDefFoundError e) {
111111
debug("Cannot register annotations %s from 'org.junit.jupiter.params'. " +
112-
"Please verify that you have dependency that includes 'org.junit.jupiter.params' if you want to use these annotations.",
113-
List.of("ArgumentsSource", "ConvertWith", "AggregateWith", "EnumSource", "MethodSource", "FieldSource"));
112+
"Please verify that you have dependency that includes 'org.junit.jupiter.params' if you want to use these annotations.",
113+
List.of("ArgumentsSource", "ConvertWith", "AggregateWith", "EnumSource", "MethodSource", "FieldSource"));
114114
}
115115

116116
}
@@ -155,15 +155,15 @@ private static Class<?>[] handleMethodReference(String... methodNames) {
155155
return classList.toArray(new Class<?>[0]);
156156
}
157157

158-
public static void handleEnumSource(Method method, EnumSource source, NativeImageConfiguration registry) {
159-
registry.registerAllClassMembersForReflection(source.value());
158+
public static void handleEnumSource(Method method, EnumSource source) {
159+
JUnitPlatformFeatureUtils.registerAllClassMembersForReflection(source.value());
160160
if (method.getParameterCount() > 0) {
161161
Class<?>[] parameterTypes = method.getParameterTypes();
162162
/* EnumSource annotated methods without an enum in the annotation value must have the enum as the first parameter. */
163163
Class<?> enumParameterType = parameterTypes[0];
164164
if (enumParameterType.isEnum()) {
165165
debug("Registering method enum parameter for reflection. Method: %s Parameter: %s", method, parameterTypes[0]);
166-
registry.registerAllClassMembersForReflection(enumParameterType);
166+
JUnitPlatformFeatureUtils.registerAllClassMembersForReflection(enumParameterType);
167167
} else {
168168
debug("First parameter of method not an enum - skipping. Method: %s", method);
169169
}

common/junit-platform-native/src/main/java/org/graalvm/junit/platform/config/platform/PlatformConfigProvider.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,21 @@
4141

4242
package org.graalvm.junit.platform.config.platform;
4343

44-
import org.graalvm.junit.platform.config.core.NativeImageConfiguration;
4544
import org.graalvm.junit.platform.config.core.PluginConfigProvider;
45+
import org.graalvm.nativeimage.ImageInfo;
4646
import org.graalvm.nativeimage.hosted.RuntimeSerialization;
4747
import org.junit.platform.launcher.TestIdentifier;
4848

4949
public class PlatformConfigProvider extends PluginConfigProvider {
5050

5151
@Override
52-
public void onLoad(NativeImageConfiguration config) {
53-
RuntimeSerialization.register(TestIdentifier.class.getDeclaredClasses());
52+
public void onLoad() {
53+
if (ImageInfo.inImageBuildtimeCode()) {
54+
RuntimeSerialization.register(TestIdentifier.class.getDeclaredClasses());
55+
}
5456
}
5557

5658
@Override
57-
public void onTestClassRegistered(Class<?> testClass, NativeImageConfiguration registry) {
59+
public void onTestClassRegistered(Class<?> testClass) {
5860
}
5961
}

0 commit comments

Comments
 (0)