Skip to content

Commit d35054f

Browse files
committed
Use bundle versions when adding JUnit to launch
This change adjusts JUnitLaunchConfigurationDelegate, to use bundle versions when adding required JUnit bundles. E.g. when adding JUnit bundles for a JUnit 5 test, JUnit 5 versions are added. This avoids conflicts when both JUnit 5 and JUnit 6 bundles are in the platform, since they share symbolic names. Fixes: #2006
1 parent c06c4ef commit d35054f

File tree

2 files changed

+113
-25
lines changed

2 files changed

+113
-25
lines changed

ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/JUnitLaunchConfigurationDelegate.java

Lines changed: 76 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@
2727
import java.util.Collection;
2828
import java.util.Collections;
2929
import java.util.Comparator;
30-
import java.util.HashSet;
3130
import java.util.LinkedHashMap;
3231
import java.util.LinkedHashSet;
3332
import java.util.List;
3433
import java.util.Map;
3534
import java.util.Properties;
3635
import java.util.Set;
36+
import java.util.function.Supplier;
3737
import java.util.jar.JarOutputStream;
3838
import java.util.jar.Manifest;
3939
import java.util.stream.Collectors;
@@ -88,6 +88,7 @@
8888
import org.eclipse.pde.internal.launching.launcher.RequirementHelper;
8989
import org.eclipse.pde.internal.launching.launcher.VMHelper;
9090
import org.osgi.framework.Constants;
91+
import org.osgi.framework.VersionRange;
9192

9293
/**
9394
* A launch delegate for launching JUnit Plug-in tests.
@@ -99,6 +100,11 @@
99100
*/
100101
public class JUnitLaunchConfigurationDelegate extends org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate {
101102

103+
public static final String JUNIT4_RUNTIME_PLUGIN = "org.eclipse.jdt.junit4.runtime"; //$NON-NLS-1$
104+
public static final String JUNIT5_RUNTIME_PLUGIN = "org.eclipse.jdt.junit5.runtime"; //$NON-NLS-1$
105+
106+
private static final VersionRange JUNIT5_VERSIONS = new VersionRange("[1, 5)"); //$NON-NLS-1$
107+
102108
static {
103109
RequirementHelper.registerLaunchTypeRequirements("org.eclipse.pde.ui.JunitLaunchConfig", lc -> { //$NON-NLS-1$
104110
// Junit launch configs can have the core test application set in either the 'app to test' or the 'application' attribute
@@ -393,14 +399,32 @@ protected String getApplication(ILaunchConfiguration configuration) {
393399
return application;
394400
}
395401

396-
private IPluginModelBase findRequiredPluginInTargetOrHost(String id) throws CoreException {
397-
IPluginModelBase model = PluginRegistry.findModel(id);
402+
private static IPluginModelBase findRequiredPluginInTargetOrHost(String id) throws CoreException {
403+
IPluginModelBase model = findRequiredPluginInTargetOrHost(id, () -> PluginRegistry.findModel(id));
404+
return model;
405+
}
406+
407+
private static IPluginModelBase findRequiredPluginInTargetOrHost(String id, VersionRange versionRange) throws CoreException {
408+
IPluginModelBase model = findRequiredPluginInTargetOrHost(id, () -> PluginRegistry.findModel(id, versionRange));
409+
return model;
410+
}
411+
412+
private static IPluginModelBase findRequiredPluginInTargetOrHost(BundleDescription bundleDescription) throws CoreException {
413+
String id = bundleDescription.getSymbolicName();
414+
IPluginModelBase model = findRequiredPluginInTargetOrHost(id, () -> PluginRegistry.findModel((org.osgi.resource.Resource) bundleDescription));
415+
return model;
416+
}
417+
418+
private static IPluginModelBase findRequiredPluginInTargetOrHost(String id, Supplier<IPluginModelBase> findModel) throws CoreException {
419+
IPluginModelBase model = findModel.get();
398420
if (model == null || !model.getBundleDescription().isResolved()) {
399421
// prefer bundle from host over unresolved bundle from target
400422
model = PDECore.getDefault().findPluginInHost(id);
401423
}
402424
if (model == null) {
403-
abort(NLS.bind(PDEMessages.JUnitLaunchConfiguration_error_missingPlugin, id), null, IStatus.OK);
425+
String message = NLS.bind(PDEMessages.JUnitLaunchConfiguration_error_missingPlugin, id);
426+
Status error = new Status(IStatus.ERROR, IPDEConstants.PLUGIN_ID, IStatus.OK, message, null);
427+
throw new CoreException(error);
404428
}
405429
return model;
406430
}
@@ -559,19 +583,45 @@ protected void preLaunchCheck(ILaunchConfiguration configuration, ILaunch launch
559583
}
560584

561585
private void addRequiredJunitRuntimePlugins(ILaunchConfiguration configuration) throws CoreException {
562-
Set<String> requiredPlugins = new LinkedHashSet<>(getRequiredJunitRuntimePlugins(configuration));
586+
Collection<String> plugins = getRequiredJunitRuntimePlugins(configuration);
587+
addPlugins(plugins);
588+
if (plugins.contains(JUNIT5_RUNTIME_PLUGIN) &&
589+
(fAllBundles.containsKey("junit-platform-runner") || fAllBundles.containsKey("org.junit.platform.runner"))) { //$NON-NLS-1$ //$NON-NLS-2$
590+
Set<BundleDescription> descriptions = junit5PlatformRequirements();
591+
Set<BundleDescription> junitRquirements = DependencyManager.findRequirementsClosure(descriptions);
592+
addAbsentRequirements(junitRquirements);
593+
}
594+
}
563595

564-
if (fAllBundles.containsKey("junit-platform-runner") || fAllBundles.containsKey("org.junit.platform.runner")) { //$NON-NLS-1$ //$NON-NLS-2$
565-
// add launcher and jupiter.engine to support @RunWith(JUnitPlatform.class)
566-
requiredPlugins.add("junit-platform-launcher"); //$NON-NLS-1$
567-
requiredPlugins.add("junit-jupiter-engine"); //$NON-NLS-1$
596+
/**
597+
* @noreference This method is not intended to be referenced by clients.
598+
* @return plugins required by JUnit 5 platform bundle
599+
*/
600+
public static Set<BundleDescription> junit5PlatformRequirements() throws CoreException {
601+
// add launcher and jupiter.engine to support @RunWith(JUnitPlatform.class)
602+
String[] requiredPlugins = {
603+
"junit-platform-launcher", //$NON-NLS-1$
604+
"junit-jupiter-engine", //$NON-NLS-1$
605+
};
606+
Set<BundleDescription> descriptions = new LinkedHashSet<>();
607+
for (String id : requiredPlugins) {
608+
IPluginModelBase model = findRequiredPluginInTargetOrHost(id, JUNIT5_VERSIONS);
609+
if (model != null) {
610+
BundleDescription description = model.getBundleDescription();
611+
descriptions.add(description);
612+
}
568613
}
569-
Set<BundleDescription> addedRequirements = new HashSet<>();
614+
return descriptions;
615+
}
616+
617+
private void addPlugins(Collection<String> plugins) throws CoreException {
618+
Set<String> requiredPlugins = new LinkedHashSet<>(plugins);
619+
620+
Set<BundleDescription> addedRequirements = new LinkedHashSet<>();
570621
addAbsentRequirements(requiredPlugins, addedRequirements);
571622

572623
Set<BundleDescription> requirementsOfRequirements = DependencyManager.findRequirementsClosure(addedRequirements);
573-
Set<String> rorIds = requirementsOfRequirements.stream().map(BundleDescription::getSymbolicName).collect(Collectors.toSet());
574-
addAbsentRequirements(rorIds, null);
624+
addAbsentRequirements(requirementsOfRequirements);
575625
}
576626

577627
private void addAbsentRequirements(Collection<String> requirements, Set<BundleDescription> addedRequirements) throws CoreException {
@@ -588,6 +638,18 @@ private void addAbsentRequirements(Collection<String> requirements, Set<BundleDe
588638
}
589639
}
590640

641+
private void addAbsentRequirements(Set<BundleDescription> toAdd) throws CoreException {
642+
for (BundleDescription requirement : toAdd) {
643+
String id = requirement.getSymbolicName();
644+
List<IPluginModelBase> models = fAllBundles.computeIfAbsent(id, k -> new ArrayList<>());
645+
if (models.stream().noneMatch(m -> m.getBundleDescription().isResolved())) {
646+
IPluginModelBase model = findRequiredPluginInTargetOrHost(requirement);
647+
models.add(model);
648+
BundleLauncherHelper.addDefaultStartingBundle(fModels, model);
649+
}
650+
}
651+
}
652+
591653
/**
592654
* @noreference This method is not intended to be referenced by clients.
593655
* @param configuration non null config
@@ -603,9 +665,9 @@ public static Collection<String> getRequiredJunitRuntimePlugins(ILaunchConfigura
603665
plugins.add("org.eclipse.pde.junit.runtime"); //$NON-NLS-1$
604666

605667
if (org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT4_TEST_KIND_ID.equals(testKind.getId())) {
606-
plugins.add("org.eclipse.jdt.junit4.runtime"); //$NON-NLS-1$
668+
plugins.add(JUNIT4_RUNTIME_PLUGIN);
607669
} else if (org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT5_TEST_KIND_ID.equals(testKind.getId())) {
608-
plugins.add("org.eclipse.jdt.junit5.runtime"); //$NON-NLS-1$
670+
plugins.add(JUNIT5_RUNTIME_PLUGIN);
609671
}
610672
return plugins;
611673
}

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

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.List;
3434
import java.util.Map;
3535
import java.util.Set;
36+
import java.util.function.Supplier;
3637
import java.util.stream.Collectors;
3738

3839
import org.eclipse.core.resources.IProject;
@@ -390,20 +391,19 @@ private void addRequiredJunitRuntimePlugins(ILaunchConfiguration configuration)
390391
Set<String> requiredPlugins = new LinkedHashSet<>(
391392
JUnitLaunchConfigurationDelegate.getRequiredJunitRuntimePlugins(configuration));
392393

393-
if (fAllBundles.containsKey("junit-platform-runner")) { //$NON-NLS-1$
394-
// add launcher and jupiter.engine to support @RunWith(JUnitPlatform.class)
395-
requiredPlugins.add("junit-platform-launcher"); //$NON-NLS-1$
396-
requiredPlugins.add("junit-jupiter-engine"); //$NON-NLS-1$
397-
}
398-
399-
Set<BundleDescription> addedRequirements = new HashSet<>();
394+
Set<BundleDescription> addedRequirements = new LinkedHashSet<>();
400395
addAbsentRequirements(requiredPlugins, addedRequirements);
401396

397+
if (requiredPlugins.contains(JUnitLaunchConfigurationDelegate.JUNIT5_RUNTIME_PLUGIN)
398+
&& fAllBundles.containsKey("junit-platform-runner") //$NON-NLS-1$
399+
|| fAllBundles.containsKey("org.junit.platform.runner")) { //$NON-NLS-1$
400+
Set<BundleDescription> requirements = JUnitLaunchConfigurationDelegate.junit5PlatformRequirements();
401+
addedRequirements.addAll(requirements);
402+
}
403+
402404
Set<BundleDescription> requirementsOfRequirements = DependencyManager
403405
.findRequirementsClosure(addedRequirements);
404-
Set<String> rorIds = requirementsOfRequirements.stream().map(BundleDescription::getSymbolicName)
405-
.collect(Collectors.toSet());
406-
addAbsentRequirements(rorIds, null);
406+
addAbsentRequirements(requirementsOfRequirements);
407407
}
408408

409409
private void addAbsentRequirements(Collection<String> requirements, Set<BundleDescription> addedRequirements)
@@ -421,6 +421,18 @@ private void addAbsentRequirements(Collection<String> requirements, Set<BundleDe
421421
}
422422
}
423423

424+
private void addAbsentRequirements(Set<BundleDescription> toAdd) throws CoreException {
425+
for (BundleDescription requirement : toAdd) {
426+
String id = requirement.getSymbolicName();
427+
List<IPluginModelBase> models = fAllBundles.computeIfAbsent(id, k -> new ArrayList<>());
428+
if (models.stream().noneMatch(m -> m.getBundleDescription().isResolved())) {
429+
IPluginModelBase model = findRequiredPluginInTargetOrHost(requirement);
430+
models.add(model);
431+
BundleLauncherHelper.addDefaultStartingBundle(fModels, model);
432+
}
433+
}
434+
}
435+
424436
@Override
425437
public String getJavaProjectName(ILaunchConfiguration configuration) throws CoreException {
426438
return configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null);
@@ -1086,7 +1098,21 @@ protected String getApplication(ILaunchConfiguration configuration) {
10861098
}
10871099

10881100
private IPluginModelBase findRequiredPluginInTargetOrHost(String id) throws CoreException {
1089-
IPluginModelBase model = PluginRegistry.findModel(id);
1101+
IPluginModelBase model = findRequiredPluginInTargetOrHost(id, () -> PluginRegistry.findModel(id));
1102+
return model;
1103+
}
1104+
1105+
private IPluginModelBase findRequiredPluginInTargetOrHost(BundleDescription bundleDescription)
1106+
throws CoreException {
1107+
String id = bundleDescription.getSymbolicName();
1108+
IPluginModelBase model = findRequiredPluginInTargetOrHost(id,
1109+
() -> PluginRegistry.findModel((org.osgi.resource.Resource) bundleDescription));
1110+
return model;
1111+
}
1112+
1113+
private IPluginModelBase findRequiredPluginInTargetOrHost(String id, Supplier<IPluginModelBase> findModel)
1114+
throws CoreException {
1115+
IPluginModelBase model = findModel.get();
10901116
if (model == null || !model.getBundleDescription().isResolved()) {
10911117
// prefer bundle from host over unresolved bundle from target
10921118
model = PDECore.getDefault().findPluginInHost(id);

0 commit comments

Comments
 (0)