2727import java .util .Collection ;
2828import java .util .Collections ;
2929import java .util .Comparator ;
30- import java .util .HashSet ;
3130import java .util .LinkedHashMap ;
3231import java .util .LinkedHashSet ;
3332import java .util .List ;
3433import java .util .Map ;
3534import java .util .Properties ;
3635import java .util .Set ;
36+ import java .util .function .Supplier ;
3737import java .util .jar .JarOutputStream ;
3838import java .util .jar .Manifest ;
3939import java .util .stream .Collectors ;
8888import org .eclipse .pde .internal .launching .launcher .RequirementHelper ;
8989import org .eclipse .pde .internal .launching .launcher .VMHelper ;
9090import org .osgi .framework .Constants ;
91+ import org .osgi .framework .VersionRange ;
9192
9293/**
9394 * A launch delegate for launching JUnit Plug-in tests.
99100 */
100101public 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 }
0 commit comments