Skip to content

Commit 8a9777c

Browse files
committed
Support JUnit 6 plug-in test launches
Fixes: #2108
1 parent 6feb637 commit 8a9777c

File tree

5 files changed

+77
-29
lines changed

5 files changed

+77
-29
lines changed

ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/Caller.java

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.eclipse.core.runtime.Platform;
1919
import org.osgi.framework.Bundle;
2020
import org.osgi.framework.FrameworkUtil;
21+
import org.osgi.framework.VersionRange;
2122
import org.osgi.framework.wiring.BundleCapability;
2223
import org.osgi.framework.wiring.BundleWiring;
2324

@@ -26,40 +27,51 @@
2627
* TODO provide MR variant using stack walker, currently blocked by JDT bug ...
2728
*/
2829
public class Caller {
30+
31+
private static final VersionRange JUNIT5_VERSION_RANGE = new VersionRange("[1.0.0,6.0.0)"); //$NON-NLS-1$
32+
private static final VersionRange JUNIT6_VERSION_RANGE = new VersionRange("[6.0.0,7.0.0)"); //$NON-NLS-1$
33+
2934
private static final String JUNIT_PLATFORM_LAUNCHER = "org.junit.platform.launcher"; //$NON-NLS-1$
30-
private static final Bundle BUNDLE = FrameworkUtil.getBundle(Caller.class);
31-
private static final Bundle loaderBundle;
35+
private static final Bundle BUNDLE;
36+
private static final Bundle loaderBundleJUnit5;
37+
private static final Bundle loaderBundleJUnit6;
3238

3339
static {
34-
Bundle junit5RuntimeBundle = Platform.getBundle("org.eclipse.jdt.junit5.runtime"); //$NON-NLS-1$
35-
if (junit5RuntimeBundle == null) {
40+
BUNDLE = FrameworkUtil.getBundle(Caller.class);
41+
loaderBundleJUnit5 = findJUnitBundle("org.eclipse.jdt.junit5.runtime", JUNIT5_VERSION_RANGE); //$NON-NLS-1$
42+
loaderBundleJUnit6 = findJUnitBundle("org.eclipse.jdt.junit6.runtime", JUNIT6_VERSION_RANGE); //$NON-NLS-1$
43+
}
44+
45+
private static Bundle findJUnitBundle(String bundleId, VersionRange versionRange) {
46+
Bundle junitRuntimeBundle = Platform.getBundle(bundleId);
47+
if (junitRuntimeBundle == null) {
3648
Bundle junit4RuntimeBundle = Platform.getBundle("org.eclipse.jdt.junit4.runtime"); //$NON-NLS-1$
37-
loaderBundle = findJUnit5LauncherByRuntime(junit4RuntimeBundle);
38-
} else {
39-
loaderBundle = junit5RuntimeBundle;
49+
return findJUnitLauncherByRuntime(junit4RuntimeBundle, versionRange);
4050
}
51+
return junitRuntimeBundle;
4152
}
4253

43-
protected static Bundle findJUnit5LauncherByRuntime(Bundle junit4RuntimeBundle) {
54+
protected static Bundle findJUnitLauncherByRuntime(Bundle junit4RuntimeBundle, VersionRange junitPlatformVersionRange) {
4455
if (junit4RuntimeBundle == null) {
4556
return BUNDLE;
4657
}
4758
for (Bundle bundle : BUNDLE.getBundleContext().getBundles()) {
4859
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
4960
List<BundleCapability> capabilities = bundleWiring.getCapabilities(JUNIT_PLATFORM_LAUNCHER);
50-
if (!capabilities.isEmpty() && bundle.getVersion().getMajor() < 6) {
61+
if (!capabilities.isEmpty() && junitPlatformVersionRange.includes(bundle.getVersion())) {
5162
return bundle;
5263
}
5364
}
5465

5566
return BUNDLE;
5667
}
5768

58-
static Bundle getBundle() {
69+
static Bundle getBundle(int junitVersion) {
5970
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
6071
for (StackTraceElement element : stackTraceElements) {
6172
try {
6273
String className = element.getClassName();
74+
Bundle loaderBundle = junitVersion == 5 ? loaderBundleJUnit5 : loaderBundleJUnit6;
6375
Class<?> clz = loaderBundle.loadClass(className);
6476
Bundle bundle = FrameworkUtil.getBundle(clz);
6577
if (bundle == BUNDLE) {

ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/RemotePluginTestRunner.java

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,18 @@
2929
import org.osgi.framework.Bundle;
3030
import org.osgi.framework.BundleContext;
3131
import org.osgi.framework.FrameworkUtil;
32+
import org.osgi.framework.VersionRange;
3233
import org.osgi.framework.wiring.BundleWiring;
3334

3435
/**
3536
* Runs JUnit tests contained inside a plugin.
3637
*/
3738
public class RemotePluginTestRunner extends RemoteTestRunner {
3839

40+
private static final String ORG_ECLIPSE_JDT_JUNIT5_RUNTIME = "org.eclipse.jdt.junit5.runtime"; //$NON-NLS-1$
41+
private static final String ORG_ECLIPSE_JDT_JUNIT6_RUNTIME = "org.eclipse.jdt.junit6.runtime"; //$NON-NLS-1$
42+
private static final VersionRange JUNIT5_VERSION_RANGE = new VersionRange("[1.0.0,6.0.0)"); //$NON-NLS-1$
43+
private static final VersionRange JUNIT6_VERSION_RANGE = new VersionRange("[6.0.0,7.0.0)"); //$NON-NLS-1$
3944
private String fTestPluginName;
4045
private ClassLoader fLoaderClassLoader;
4146

@@ -102,13 +107,24 @@ public static void main(String[] args) {
102107
RemotePluginTestRunner testRunner = new RemotePluginTestRunner();
103108
testRunner.init(args);
104109
ClassLoader currentTCCL = Thread.currentThread().getContextClassLoader();
105-
if (isJUnit5(args)) {
106-
//change the classloader so that the test classes in testplugin are discoverable
107-
//by junit5 framework see bug 520811
108-
Thread.currentThread().setContextClassLoader(createJUnit5PluginClassLoader(testRunner.getTestPluginName()));
110+
boolean isJUnit5 = isJUnit5(args);
111+
boolean isJUnit6 = !isJUnit5 && isJUnit6(args);
112+
String junitRuntimeBundle = ORG_ECLIPSE_JDT_JUNIT6_RUNTIME;
113+
VersionRange junitVersionRange = JUNIT6_VERSION_RANGE;
114+
int junitVersion = 6;
115+
if (isJUnit5) {
116+
junitRuntimeBundle = ORG_ECLIPSE_JDT_JUNIT5_RUNTIME;
117+
junitVersionRange = JUNIT5_VERSION_RANGE;
118+
junitVersion = 5;
119+
}
120+
boolean isJUnitJupiter = isJUnit5 || isJUnit6;
121+
//change the classloader so that the test classes in testplugin are discoverable
122+
//by junit5 framework see bug 520811
123+
if (isJUnitJupiter) {
124+
Thread.currentThread().setContextClassLoader(createJUnitJupiterPluginClassLoader(testRunner.getTestPluginName(), junitRuntimeBundle, junitVersionRange, junitVersion));
109125
}
110126
testRunner.run();
111-
if (isJUnit5(args)) {
127+
if (isJUnitJupiter) {
112128
Thread.currentThread().setContextClassLoader(currentTCCL);
113129
}
114130
}
@@ -131,21 +147,21 @@ private static String getState(int state) {
131147
return Integer.toString(state);
132148
}
133149

134-
private static ClassLoader createJUnit5PluginClassLoader(String testPluginName) {
150+
private static ClassLoader createJUnitJupiterPluginClassLoader(String testPluginName, String junitRuntimeBundle, VersionRange versionRange, int junitVersion) {
135151
Bundle testBundle = Platform.getBundle(testPluginName);
136152
if (testBundle == null) {
137153
throw new IllegalArgumentException("Bundle \"" + testPluginName + "\" not found. Possible causes include missing dependencies, too restrictive version ranges, mixed JUnit versions, or a non-matching required execution environment."); //$NON-NLS-1$ //$NON-NLS-2$
138154
}
139-
Bundle junit5RuntimeBundle = Platform.getBundle("org.eclipse.jdt.junit5.runtime"); //$NON-NLS-1$
140-
List<Bundle> platformEngineBundles = findTestEngineBundles();
155+
Bundle junit5RuntimeBundle = Platform.getBundle(junitRuntimeBundle);
156+
List<Bundle> platformEngineBundles = findTestEngineBundles(versionRange);
141157
platformEngineBundles.add(testBundle);
142158
if (junit5RuntimeBundle != null) {
143159
platformEngineBundles.add(junit5RuntimeBundle);
144160
}
145-
return new SPIBundleClassLoader(platformEngineBundles);
161+
return new SPIBundleClassLoader(platformEngineBundles, junitVersion);
146162
}
147163

148-
private static List<Bundle> findTestEngineBundles() {
164+
private static List<Bundle> findTestEngineBundles(VersionRange versionRange) {
149165
BundleContext bundleContext = FrameworkUtil.getBundle(RemotePluginTestRunner.class).getBundleContext();
150166
return Arrays.stream(bundleContext.getBundles()).filter(RemotePluginTestRunner::providesTestEngine).collect(Collectors.toCollection(ArrayList::new));
151167
}
@@ -186,12 +202,20 @@ public ClassLoader getClassLoader(final String bundleId) {
186202
@Override
187203
public void init(String[] args) {
188204
readPluginArgs(args);
189-
if (isJUnit5(args)) {
190-
// changing the classloader to get the testengines for junit5
191-
// during initialization - see bug 520811
205+
// changing the classloader to get the testengines for junit5/junit6
206+
// during initialization - see bug 520811
207+
boolean isJUnit5 = isJUnit5(args);
208+
boolean isJUnit6 = !isJUnit5 && isJUnit6(args);
209+
VersionRange versionRange = JUNIT6_VERSION_RANGE;
210+
int junitVersion = 6;
211+
if (isJUnit5) {
212+
versionRange = JUNIT5_VERSION_RANGE;
213+
junitVersion = 5;
214+
}
215+
if (isJUnit5 || isJUnit6) {
192216
ClassLoader currentTCCL = Thread.currentThread().getContextClassLoader();
193217
try {
194-
Thread.currentThread().setContextClassLoader(new SPIBundleClassLoader(findTestEngineBundles()));
218+
Thread.currentThread().setContextClassLoader(new SPIBundleClassLoader(findTestEngineBundles(versionRange), junitVersion));
195219
defaultInit(args);
196220
} finally {
197221
Thread.currentThread().setContextClassLoader(currentTCCL);
@@ -206,6 +230,11 @@ private static boolean isJUnit5(String[] args) {
206230
return indexOf(args, "-runasjunit5"::equalsIgnoreCase) > -1 || indexOf(args, "org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader"::equals) > -1;
207231
}
208232

233+
@SuppressWarnings("nls")
234+
private static boolean isJUnit6(String[] args) {
235+
return indexOf(args, "-runasjunit6"::equalsIgnoreCase) > -1 || indexOf(args, "org.eclipse.jdt.internal.junit6.runner.JUnit6TestLoader"::equals) > -1;
236+
}
237+
209238
public void readPluginArgs(String[] args) {
210239
fTestPluginName = getArgumentValue(args, "-testpluginname"); //$NON-NLS-1$
211240
String loaderPlugin = getArgumentValue(args, "-loaderpluginname"); //$NON-NLS-1$

ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/SPIBundleClassLoader.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,20 @@ class SPIBundleClassLoader extends ClassLoader {
3535

3636
private static final String META_INF_SERVICES = "META-INF/services/"; //$NON-NLS-1$
3737
private final List<Bundle> bundles;
38+
private final int junitVersion;
3839
private final Map<String, List<SPIMapping>> mappings = new ConcurrentHashMap<>();
3940

40-
SPIBundleClassLoader(List<Bundle> bundles) {
41+
SPIBundleClassLoader(List<Bundle> bundles, int junitVersion) {
4142
super(null);
4243
this.bundles = bundles;
44+
this.junitVersion = junitVersion;
4345
}
4446

4547
@Override
4648
protected Class<?> findClass(String name) throws ClassNotFoundException {
4749
Iterator<SPIMapping> spi = mappings.values().stream().flatMap(Collection::stream).filter(mapping -> mapping.hasService(name)).iterator();
4850
if (spi.hasNext()) {
49-
Bundle caller = Caller.getBundle();
51+
Bundle caller = Caller.getBundle(junitVersion);
5052
while (spi.hasNext()) {
5153
SPIMapping mapping = spi.next();
5254
if (mapping.isCompatible(caller)) {
@@ -98,7 +100,7 @@ protected Enumeration<URL> findResources(String name) throws IOException {
98100
}
99101
return list;
100102
});
101-
Bundle caller = Caller.getBundle();
103+
Bundle caller = Caller.getBundle(junitVersion);
102104
for (SPIMapping mapping : spis) {
103105
if (mapping.isCompatible(caller)) {
104106
result.add(mapping.getUrl());

ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/JUnitLaunchRequirements.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public class JUnitLaunchRequirements {
5555
private static final String PDE_JUNIT_RUNTIME = "org.eclipse.pde.junit.runtime"; //$NON-NLS-1$
5656
private static final String JUNIT4_JDT_RUNTIME_PLUGIN = "org.eclipse.jdt.junit4.runtime"; //$NON-NLS-1$
5757
private static final String JUNIT5_JDT_RUNTIME_PLUGIN = "org.eclipse.jdt.junit5.runtime"; //$NON-NLS-1$
58+
private static final String JUNIT6_JDT_RUNTIME_PLUGIN = "org.eclipse.jdt.junit6.runtime"; //$NON-NLS-1$
5859

5960
public static void addRequiredJunitRuntimePlugins(ILaunchConfiguration configuration, Map<String, List<IPluginModelBase>> collectedModels, Map<IPluginModelBase, String> startLevelMap) throws CoreException {
6061
Collection<IPluginModelBase> runtimeBundles = getEclipseJunitRuntimePlugins(configuration, collectedModels, startLevelMap);
@@ -158,6 +159,9 @@ public static Collection<String> getRequiredJunitRuntimeEclipsePlugins(ILaunchCo
158159
case org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT5_TEST_KIND_ID -> {
159160
return List.of(PDE_JUNIT_RUNTIME, JUNIT5_JDT_RUNTIME_PLUGIN);
160161
}
162+
case org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT6_TEST_KIND_ID -> {
163+
return List.of(PDE_JUNIT_RUNTIME, JUNIT6_JDT_RUNTIME_PLUGIN);
164+
}
161165
default -> throw new IllegalArgumentException("Unsupported junit test kind: " + testKind.getId()); //$NON-NLS-1$
162166
}
163167
}

ui/org.eclipse.pde.unittest.junit/src/org/eclipse/pde/unittest/junit/launcher/JUnitPluginLaunchConfigurationDelegate.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ private VMRunnerConfiguration getVMRunnerConfiguration(ILaunchConfiguration conf
234234
String[] classpath = classpathAndModulepath[0];
235235
String[] modulepath = classpathAndModulepath[1];
236236

237-
if (junitVersion == JUnitVersion.JUNIT5) {
237+
if (junitVersion == JUnitVersion.JUNIT5 || junitVersion == JUnitVersion.JUNIT6) {
238238
if (!configuration.getAttribute(
239239
JUnitLaunchConfigurationConstants.ATTR_DONT_ADD_MISSING_JUNIT5_DEPENDENCY, false)) {
240240
if (!Arrays.stream(classpath).anyMatch(
@@ -574,7 +574,8 @@ private void internalCollectExecutionArguments(ILaunchConfiguration configuratio
574574
boolean isModularProject = JavaRuntime.isModularProject(getJavaProject(configuration));
575575
String addOpensTargets;
576576
if (isModularProject) {
577-
if (getJUnitVersion(configuration) == JUnitVersion.JUNIT5) {
577+
JUnitVersion jUnitVersion = getJUnitVersion(configuration);
578+
if (jUnitVersion == JUnitVersion.JUNIT5 || jUnitVersion == JUnitVersion.JUNIT6) {
578579
if (isOnModulePath(getJavaProject(configuration), "org.junit.jupiter.api.Test")) { //$NON-NLS-1$
579580
addOpensTargets = "junit-platform-commons,ALL-UNNAMED"; //$NON-NLS-1$
580581
} else {

0 commit comments

Comments
 (0)