Skip to content

Commit 7185660

Browse files
trancexpressiloveeclipse
authored andcommitted
Support JUnit 6 plug-in test launches
Fixes #2108
1 parent b00ef59 commit 7185660

File tree

5 files changed

+78
-27
lines changed

5 files changed

+78
-27
lines changed

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

Lines changed: 23 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,52 @@
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$
3035
private static final Bundle BUNDLE = FrameworkUtil.getBundle(Caller.class);
31-
private static final Bundle loaderBundle;
36+
private static final Bundle LOADER_BUNDLE_JUNIT_5 = findJUnitBundle("org.eclipse.jdt.junit5.runtime", JUNIT5_VERSION_RANGE); //$NON-NLS-1$
37+
private static final Bundle LOADER_BUNDLE_JUNIT_6 = findJUnitBundle("org.eclipse.jdt.junit6.runtime", JUNIT6_VERSION_RANGE); //$NON-NLS-1$
3238

33-
static {
34-
Bundle junit5RuntimeBundle = Platform.getBundle("org.eclipse.jdt.junit5.runtime"); //$NON-NLS-1$
35-
if (junit5RuntimeBundle == null) {
39+
private static Bundle findJUnitBundle(String bundleId, VersionRange versionRange) {
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, versionRange);
4044
}
45+
return junitRuntimeBundle;
4146
}
4247

43-
protected static Bundle findJUnit5LauncherByRuntime(Bundle junit4RuntimeBundle) {
48+
protected static Bundle findJUnitLauncherByRuntime(Bundle junit4RuntimeBundle, VersionRange junitPlatformVersionRange) {
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() && junitPlatformVersionRange.includes(bundle.getVersion())) {
5156
return bundle;
5257
}
5358
}
5459

5560
return BUNDLE;
5661
}
5762

58-
static Bundle getBundle() {
63+
static Bundle getBundle(int junitVersion) {
5964
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
6065
for (StackTraceElement element : stackTraceElements) {
6166
try {
6267
String className = element.getClassName();
68+
Bundle loaderBundle;
69+
if (junitVersion == 5) {
70+
loaderBundle = LOADER_BUNDLE_JUNIT_5;
71+
} else if (junitVersion == 6) {
72+
loaderBundle = LOADER_BUNDLE_JUNIT_6;
73+
} else {
74+
throw new IllegalArgumentException("Unsupported junit version: " + junitVersion); //$NON-NLS-1$
75+
}
6376
Class<?> clz = loaderBundle.loadClass(className);
6477
Bundle bundle = FrameworkUtil.getBundle(clz);
6578
if (bundle == BUNDLE) {

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

Lines changed: 43 additions & 12 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)) {
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+
if (isJUnitJupiter) {
106122
//change the classloader so that the test classes in testplugin are discoverable
107123
//by junit5 framework see bug 520811
108-
Thread.currentThread().setContextClassLoader(createJUnit5PluginClassLoader(testRunner.getTestPluginName()));
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,23 +147,25 @@ 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();
150-
return Arrays.stream(bundleContext.getBundles()).filter(RemotePluginTestRunner::providesTestEngine).collect(Collectors.toCollection(ArrayList::new));
166+
return Arrays.stream(bundleContext.getBundles()).filter(RemotePluginTestRunner::providesTestEngine) //
167+
.filter(b -> versionRange.includes(b.getVersion())) //
168+
.collect(Collectors.toCollection(ArrayList::new));
151169
}
152170

153171
/**
@@ -186,12 +204,20 @@ public ClassLoader getClassLoader(final String bundleId) {
186204
@Override
187205
public void init(String[] args) {
188206
readPluginArgs(args);
189-
if (isJUnit5(args)) {
190-
// changing the classloader to get the testengines for junit5
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) {
216+
// changing the classloader to get the testengines for junit5/junit6
191217
// during initialization - see bug 520811
192218
ClassLoader currentTCCL = Thread.currentThread().getContextClassLoader();
193219
try {
194-
Thread.currentThread().setContextClassLoader(new SPIBundleClassLoader(findTestEngineBundles()));
220+
Thread.currentThread().setContextClassLoader(new SPIBundleClassLoader(findTestEngineBundles(versionRange), junitVersion));
195221
defaultInit(args);
196222
} finally {
197223
Thread.currentThread().setContextClassLoader(currentTCCL);
@@ -206,6 +232,11 @@ private static boolean isJUnit5(String[] args) {
206232
return indexOf(args, "-runasjunit5"::equalsIgnoreCase) > -1 || indexOf(args, "org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader"::equals) > -1;
207233
}
208234

235+
@SuppressWarnings("nls")
236+
private static boolean isJUnit6(String[] args) {
237+
return indexOf(args, "-runasjunit6"::equalsIgnoreCase) > -1 || indexOf(args, "org.eclipse.jdt.internal.junit6.runner.JUnit6TestLoader"::equals) > -1;
238+
}
239+
209240
public void readPluginArgs(String[] args) {
210241
fTestPluginName = getArgumentValue(args, "-testpluginname"); //$NON-NLS-1$
211242
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)