Skip to content

Commit 1ab5883

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

File tree

5 files changed

+69
-28
lines changed

5 files changed

+69
-28
lines changed

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,39 @@
2828
public class Caller {
2929
private static final String JUNIT_PLATFORM_LAUNCHER = "org.junit.platform.launcher"; //$NON-NLS-1$
3030
private static final Bundle BUNDLE = FrameworkUtil.getBundle(Caller.class);
31-
private static final Bundle loaderBundle;
31+
static final Bundle loaderBundle5;
32+
static final Bundle loaderBundle6;
3233

3334
static {
34-
Bundle junit5RuntimeBundle = Platform.getBundle("org.eclipse.jdt.junit5.runtime"); //$NON-NLS-1$
35-
if (junit5RuntimeBundle == null) {
35+
loaderBundle5 = findJUnitBundle("org.eclipse.jdt.junit5.runtime", 5); //$NON-NLS-1$
36+
loaderBundle6 = findJUnitBundle("org.eclipse.jdt.junit6.runtime", 6); //$NON-NLS-1$
37+
}
38+
39+
private static Bundle findJUnitBundle(String bundleId, int junitVersion) {
40+
Bundle junitRuntimeBundle = Platform.getBundle(bundleId);
41+
if (junitRuntimeBundle == null) {
3642
Bundle junit4RuntimeBundle = Platform.getBundle("org.eclipse.jdt.junit4.runtime"); //$NON-NLS-1$
37-
loaderBundle = findJUnit5LauncherByRuntime(junit4RuntimeBundle);
38-
} else {
39-
loaderBundle = junit5RuntimeBundle;
43+
return findJUnitLauncherByRuntime(junit4RuntimeBundle, junitVersion);
4044
}
45+
return junitRuntimeBundle;
4146
}
4247

43-
protected static Bundle findJUnit5LauncherByRuntime(Bundle junit4RuntimeBundle) {
48+
protected static Bundle findJUnitLauncherByRuntime(Bundle junit4RuntimeBundle, int majorVersion) {
4449
if (junit4RuntimeBundle == null) {
4550
return BUNDLE;
4651
}
4752
for (Bundle bundle : BUNDLE.getBundleContext().getBundles()) {
4853
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
4954
List<BundleCapability> capabilities = bundleWiring.getCapabilities(JUNIT_PLATFORM_LAUNCHER);
50-
if (!capabilities.isEmpty() && bundle.getVersion().getMajor() < 6) {
55+
if (!capabilities.isEmpty() && bundle.getVersion().getMajor() == majorVersion) {
5156
return bundle;
5257
}
5358
}
5459

5560
return BUNDLE;
5661
}
5762

58-
static Bundle getBundle() {
63+
static Bundle getBundle(Bundle loaderBundle) {
5964
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
6065
for (StackTraceElement element : stackTraceElements) {
6166
try {

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+
Bundle loaderBundle = Caller.loaderBundle6;
115+
if (isJUnit5) {
116+
junitRuntimeBundle = ORG_ECLIPSE_JDT_JUNIT5_RUNTIME;
117+
junitVersionRange = JUNIT5_VERSION_RANGE;
118+
loaderBundle = Caller.loaderBundle5;
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, loaderBundle));
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, Bundle loaderBundle) {
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, loaderBundle);
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+
Bundle loaderBundle = Caller.loaderBundle6;
211+
if (isJUnit5) {
212+
versionRange = JUNIT5_VERSION_RANGE;
213+
loaderBundle = Caller.loaderBundle5;
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), loaderBundle));
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 Bundle loaderBundle;
3839
private final Map<String, List<SPIMapping>> mappings = new ConcurrentHashMap<>();
3940

40-
SPIBundleClassLoader(List<Bundle> bundles) {
41+
SPIBundleClassLoader(List<Bundle> bundles, Bundle loaderBundle) {
4142
super(null);
4243
this.bundles = bundles;
44+
this.loaderBundle = loaderBundle;
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(loaderBundle);
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(loaderBundle);
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)