Skip to content

Commit d5d9fc8

Browse files
author
Aleksandar Gradinac
committed
Introduce and migrate to a plugin configuration mechanism
1 parent 9120801 commit d5d9fc8

File tree

13 files changed

+648
-81
lines changed

13 files changed

+648
-81
lines changed

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

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@
4040
*/
4141
package org.graalvm.junit.platform;
4242

43+
import org.graalvm.junit.platform.config.NativeImageConfigurationImpl;
44+
import org.graalvm.junit.platform.config.core.PluginConfigProvider;
4345
import org.graalvm.nativeimage.ImageSingletons;
4446
import org.graalvm.nativeimage.hosted.Feature;
4547
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization;
46-
import org.graalvm.nativeimage.hosted.RuntimeReflection;
4748
import org.junit.platform.engine.DiscoverySelector;
4849
import org.junit.platform.engine.discovery.DiscoverySelectors;
4950
import org.junit.platform.engine.support.descriptor.ClassSource;
@@ -60,58 +61,29 @@
6061
import java.io.IOException;
6162
import java.io.InputStream;
6263
import java.io.InputStreamReader;
63-
import java.lang.reflect.Field;
64-
import java.lang.reflect.Method;
6564
import java.nio.file.Path;
6665
import java.util.HashSet;
6766
import java.util.List;
6867
import java.util.Optional;
68+
import java.util.ServiceLoader;
69+
import java.util.function.Consumer;
6970
import java.util.stream.Collectors;
7071

7172
@SuppressWarnings("unused")
7273
public final class JUnitPlatformFeature implements Feature {
7374

74-
final boolean debug = System.getProperty("debug") != null;
75+
public final boolean debug = System.getProperty("debug") != null;
76+
77+
private static final NativeImageConfigurationImpl nativeImageConfigImpl = new NativeImageConfigurationImpl();
78+
private final ServiceLoader<PluginConfigProvider> extensionConfigProviders = ServiceLoader.load(PluginConfigProvider.class);
7579

7680
@Override
7781
public void duringSetup(DuringSetupAccess access) {
78-
try {
79-
RuntimeReflection.register(org.junit.platform.commons.annotation.Testable.class.getMethods());
80-
RuntimeReflection.register(Class.forName("org.junit.jupiter.params.ParameterizedTestExtension").getDeclaredMethods());
81-
RuntimeReflection.registerForReflectiveInstantiation(Class.forName("org.junit.jupiter.params.ParameterizedTestExtension"));
82-
RuntimeReflection.register(Class.forName("org.junit.jupiter.params.provider.CsvArgumentsProvider").getMethods());
83-
RuntimeReflection.register(Class.forName("org.junit.jupiter.params.provider.CsvArgumentsProvider").getDeclaredMethods());
84-
RuntimeReflection.registerForReflectiveInstantiation(Class.forName("org.junit.jupiter.params.provider.CsvArgumentsProvider"));
85-
} catch (ClassNotFoundException e) {
86-
throw new RuntimeException("Missing some JUnit Platform classes for runtime reflection configuration. \n" +
87-
"Check if JUnit Platform is on your classpath or if that version is supported. \n" +
88-
"Original error: " + e);
89-
}
82+
forEachProvider(p -> p.onLoad(nativeImageConfigImpl));
9083
}
9184

9285
@Override
9386
public void beforeAnalysis(BeforeAnalysisAccess access) {
94-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.vintage.engine.support.UniqueIdReader");
95-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.vintage.engine.support.UniqueIdStringifier");
96-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.platform.launcher.core.InternalTestPlan");
97-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.platform.commons.util.StringUtils");
98-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.platform.launcher.core.TestExecutionListenerRegistry");
99-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.platform.commons.logging.LoggerFactory$DelegatingLogger");
100-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.platform.launcher.core.EngineDiscoveryOrchestrator");
101-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.platform.launcher.core.LauncherConfigurationParameters");
102-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.platform.commons.logging.LoggerFactory");
103-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.config.EnumConfigurationParameterConverter");
104-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.descriptor.ClassTestDescriptor");
105-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor");
106-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor");
107-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.platform.engine.UniqueIdFormat");
108-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.descriptor.JupiterTestDescriptor");
109-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor");
110-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor");
111-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.platform.commons.util.ReflectionUtils");
112-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor");
113-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.execution.ConditionEvaluator");
114-
RuntimeClassInitialization.initializeAtBuildTime("org.junit.jupiter.engine.execution.ExecutableInvoker");
11587
RuntimeClassInitialization.initializeAtBuildTime(NativeImageJUnitLauncher.class);
11688

11789
Launcher launcher = LauncherFactory.create();
@@ -166,13 +138,13 @@ private void registerTestClassForReflection(Class<?> clazz) {
166138
if (debug) {
167139
System.out.println("[Debug] Registering test class for reflection: " + clazz.getName());
168140
}
169-
RuntimeReflection.register(clazz.getDeclaredConstructors());
141+
nativeImageConfigImpl.registerAllClassMembersForReflection(clazz);
142+
forEachProvider(p -> p.onTestClassRegistered(clazz, nativeImageConfigImpl));
143+
}
170144

171-
for (Field field : clazz.getDeclaredFields()) {
172-
RuntimeReflection.register(field);
173-
}
174-
for (Method method : clazz.getDeclaredMethods()) {
175-
RuntimeReflection.register(method);
145+
private void forEachProvider(Consumer<PluginConfigProvider> consumer) {
146+
for (PluginConfigProvider provider: extensionConfigProviders) {
147+
consumer.accept(provider);
176148
}
177149
}
178150
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright (c) 2021, 2021 Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package org.graalvm.junit.platform.config;
42+
43+
import org.graalvm.junit.platform.JUnitPlatformFeature;
44+
import org.graalvm.junit.platform.config.core.NativeImageConfiguration;
45+
import org.graalvm.nativeimage.ImageSingletons;
46+
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization;
47+
import org.graalvm.nativeimage.hosted.RuntimeReflection;
48+
49+
import java.lang.reflect.Executable;
50+
import java.lang.reflect.Field;
51+
52+
public class NativeImageConfigurationImpl extends NativeImageConfiguration {
53+
54+
@Override
55+
public void registerForReflection(Class<?>... classes) {
56+
RuntimeReflection.register(classes);
57+
}
58+
59+
@Override
60+
public void registerForReflection(Executable... methods) {
61+
RuntimeReflection.register(methods);
62+
}
63+
64+
@Override
65+
public void registerForReflection(Field... fields) {
66+
RuntimeReflection.register(fields);
67+
}
68+
69+
@Override
70+
public void initializeAtBuildTime(String... classNames) {
71+
for (String className : classNames) {
72+
Class<?> clazz;
73+
try {
74+
clazz = Class.forName(className);
75+
RuntimeClassInitialization.initializeAtBuildTime(clazz);
76+
} catch (ClassNotFoundException e) {
77+
JUnitPlatformFeature feature = ImageSingletons.lookup(JUnitPlatformFeature.class);
78+
if (feature.debug) {
79+
System.out.println("[Debug] Failed to register class for build time initialization: " + className + " Reason: " + e);
80+
}
81+
}
82+
}
83+
}
84+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2021, 2021 Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package org.graalvm.junit.platform.config.core;
42+
43+
import java.lang.reflect.Executable;
44+
import java.lang.reflect.Field;
45+
46+
public abstract class NativeImageConfiguration {
47+
48+
public abstract void registerForReflection(Class<?>... classes);
49+
50+
public abstract void registerForReflection(Executable... methods);
51+
52+
public abstract void registerForReflection(Field... fields);
53+
54+
public void registerAllClassMembersForReflection(Class<?>... classes) {
55+
for (Class<?> clazz : classes) {
56+
registerForReflection(clazz.getDeclaredConstructors());
57+
registerForReflection(clazz.getDeclaredMethods());
58+
registerForReflection(clazz.getMethods());
59+
registerForReflection(clazz.getFields());
60+
registerForReflection(clazz.getDeclaredFields());
61+
}
62+
}
63+
64+
public abstract void initializeAtBuildTime(String... classNames);
65+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (c) 2021, 2021 Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package org.graalvm.junit.platform.config.core;
42+
43+
public interface PluginConfigProvider {
44+
45+
void onLoad(NativeImageConfiguration registry);
46+
47+
void onTestClassRegistered(Class<?> testClass, NativeImageConfiguration registry);
48+
49+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (c) 2021, 2021 Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package org.graalvm.junit.platform.config.jupiter;
42+
43+
import org.graalvm.junit.platform.config.core.NativeImageConfiguration;
44+
import org.graalvm.junit.platform.config.core.PluginConfigProvider;
45+
import org.graalvm.junit.platform.config.util.AnnotationUtils;
46+
import org.junit.jupiter.api.extension.ExtendWith;
47+
import org.junit.jupiter.params.provider.ArgumentsSource;
48+
49+
public class JupiterConfigProvider implements PluginConfigProvider {
50+
51+
@Override
52+
public void onLoad(NativeImageConfiguration registry) {
53+
String[] buildTimeInitializedClasses = new String[]{
54+
"org.junit.jupiter.engine.config.EnumConfigurationParameterConverter",
55+
"org.junit.jupiter.engine.descriptor.ClassTestDescriptor",
56+
"org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor",
57+
"org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor",
58+
"org.junit.jupiter.engine.descriptor.JupiterTestDescriptor",
59+
"org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor",
60+
"org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor",
61+
"org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor",
62+
"org.junit.jupiter.engine.execution.ConditionEvaluator",
63+
"org.junit.jupiter.engine.execution.ExecutableInvoker"
64+
};
65+
for (String className : buildTimeInitializedClasses) {
66+
registry.initializeAtBuildTime(className);
67+
}
68+
}
69+
70+
@Override
71+
public void onTestClassRegistered(Class<?> testClass, NativeImageConfiguration registry) {
72+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, ArgumentsSource.class, source -> new Class[]{source.value()});
73+
AnnotationUtils.registerClassesFromAnnotationForReflection(testClass, registry, ExtendWith.class, ExtendWith::value);
74+
}
75+
76+
}

0 commit comments

Comments
 (0)