Skip to content

Conversation

trancexpress
Copy link
Contributor

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

Copy link

github-actions bot commented Oct 10, 2025

Test Results

  693 files   -  78    693 suites   - 78   42m 2s ⏱️ - 49m 17s
3 303 tests  - 306  3 279 ✅  - 278  24 💤  - 28  0 ❌ ±0 
9 909 runs   - 918  9 837 ✅  - 833  72 💤  - 85  0 ❌ ±0 

Results for commit 6bf5bbb. ± Comparison against base commit 3201782.

This pull request removes 306 tests.
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnit5SuiteExecutionTest ‑ executePackage
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnit5SuiteExecutionTest ‑ executeProject
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnit5SuiteExecutionTest ‑ executeSuite
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest ‑ executeMethod[JUnit4 (JUnitPlatform) Fragment]
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest ‑ executeMethod[JUnit4 (JUnitPlatform)]
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest ‑ executeMethod[JUnit4 Fragment]
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest ‑ executeMethod[JUnit4]
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest ‑ executeMethod[JUnit5 Fragment]
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest ‑ executeMethod[JUnit5]
JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest ‑ executeMethod[Java 11 bundle with module limit]
…

♻️ This comment has been updated with latest results.

@trancexpress
Copy link
Contributor Author

@HannesWell could you take a look here as well?

@HannesWell HannesWell self-requested a review October 10, 2025 16:10
@HannesWell
Copy link
Member

@HannesWell could you take a look here as well?

I'll have a look at it tomorrow. Thanks for working on this!

Copy link
Member

@HannesWell HannesWell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this work.
I tried to answer at least some of your questions, but I think it needs a bit more general rework to handle versions properly.

Furthermore the class org.eclipse.pde.unittest.junit.launcher.JUnitPluginLaunchConfigurationDelegate, which is more or less a copy needs the similar adjustments too.

@trancexpress trancexpress force-pushed the gh2006 branch 2 times, most recently from f1b72a9 to 1515b1f Compare October 13, 2025 16:14
@eclipse-pde-bot
Copy link
Contributor

eclipse-pde-bot commented Oct 13, 2025

This pull request changes some projects for the first time in this development cycle.
Therefore the following files need a version increment:

features/org.eclipse.pde.unittest.junit-feature/feature.xml
ui/org.eclipse.pde.unittest.junit/META-INF/MANIFEST.MF

An additional commit containing all the necessary changes was pushed to the top of this PR's branch. To obtain these changes (for example if you want to push more changes) either fetch from your fork or apply the git patch.

Git patch
From 301b68d6fea1d3027688831970460c0feee5914c Mon Sep 17 00:00:00 2001
From: Eclipse PDE Bot <[email protected]>
Date: Fri, 17 Oct 2025 21:06:02 +0000
Subject: [PATCH] Version bump(s) for 4.38 stream


diff --git a/features/org.eclipse.pde.unittest.junit-feature/feature.xml b/features/org.eclipse.pde.unittest.junit-feature/feature.xml
index 526088e3ee..175b86fb6b 100644
--- a/features/org.eclipse.pde.unittest.junit-feature/feature.xml
+++ b/features/org.eclipse.pde.unittest.junit-feature/feature.xml
@@ -2,7 +2,7 @@
 <feature
       id="org.eclipse.pde.unittest.junit"
       label="%featureName"
-      version="1.0.1100.qualifier"
+      version="1.0.1200.qualifier"
       provider-name="%providerName"
       license-feature="org.eclipse.license"
       license-feature-version="0.0.0">
diff --git a/ui/org.eclipse.pde.unittest.junit/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.unittest.junit/META-INF/MANIFEST.MF
index 149fe2a092..59f7d8b1d7 100644
--- a/ui/org.eclipse.pde.unittest.junit/META-INF/MANIFEST.MF
+++ b/ui/org.eclipse.pde.unittest.junit/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Automatic-Module-Name: org.eclipse.pde.unittest.junit
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.pde.unittest.junit;singleton:=true
-Bundle-Version: 1.2.100.qualifier
+Bundle-Version: 1.2.200.qualifier
 Bundle-Activator: org.eclipse.pde.unittest.junit.JUnitPluginTestPlugin
 Bundle-ActivationPolicy: lazy
 Bundle-Vendor: %providerName
-- 
2.51.0

Further information are available in Common Build Issues - Missing version increments.

@trancexpress
Copy link
Contributor Author

Thanks for this work. I tried to answer at least some of your questions, but I think it needs a bit more general rework to handle versions properly.

Unfortunately I don't know enough about the code and available APIs to provide a rework.

Furthermore the class org.eclipse.pde.unittest.junit.launcher.JUnitPluginLaunchConfigurationDelegate, which is more or less a copy needs the similar adjustments too.

I've made change there too now.

@trancexpress
Copy link
Contributor Author

@HannesWell can you continue reviewing this? It would be nice to continue working on JUnit 6, which is blocked by the issue here.

@trancexpress
Copy link
Contributor Author

trancexpress commented Oct 15, 2025

One oddity with the current code is, I do need to specify junit-jupiter-api;bundle-version="[5,6)" for a JUnit plug-in test launch. If I don't specify the version constraints, even though we correctly detect and add JUnit 5 bundles in JUnitLaunchConfigurationDelegate.addRequiredJunitRuntimePlugins(ILaunchConfiguration), I still get this dialog:

junit_plugin_test_launch_errors

And so just launching a JUnit plug-in continues to not work when JUnit 5 and 6 are in the platform. The JUnit 5 plug-in test launch requires a MANIFEST.MF change. This is not the case for normal JUnit tests, where we run with JUnit 6 if we can (and in the case that the test must run on JUnit 5, the user has to change the MANIFEST.MF)...

@trancexpress trancexpress force-pushed the gh2006 branch 2 times, most recently from 315b26e to 8a1fa96 Compare October 15, 2025 11:52
Copy link
Member

@HannesWell HannesWell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HannesWell can you continue reviewing this? It would be nice to continue working on JUnit 6, which is blocked by the issue here.

Yes, I'll continue tomorrow with an in-depth review. Sorry for the delay.
For now I just have a few style remarks.
Furthermore it looks like you added more changes to the version-bump commit pushed by the bot. I suggest you squash your changes into one commit and remove the version bump so that the bot can do it's thing again after you (force) pushed the update.

@trancexpress trancexpress force-pushed the gh2006 branch 2 times, most recently from b6c7fa7 to b1232ad Compare October 16, 2025 06:27
@trancexpress
Copy link
Contributor Author

Lets wait for test results, if everything is fine we should be able to merge.

@trancexpress
Copy link
Contributor Author

trancexpress commented Oct 17, 2025

OK, I can now reproduce the problem locally too, I had to do some extra change (and use the mvn command from the jenkins file):

diff --git a/org.eclipse.pde.doc.user/META-INF/MANIFEST.MF b/org.eclipse.pde.doc.user/META-INF/MANIFEST.MF
index 9acdc38884..02be78658a 100644
--- a/org.eclipse.pde.doc.user/META-INF/MANIFEST.MF
+++ b/org.eclipse.pde.doc.user/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.pde.doc.user; singleton:=true
-Bundle-Version: 3.17.300.qualifier
+Bundle-Version: 3.17.400.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Require-Bundle: org.eclipse.help;bundle-version="[3.2.0,4.0.0)"
diff --git a/org.eclipse.pde.doc.user/pom.xml b/org.eclipse.pde.doc.user/pom.xml
index e00c354770..6095472619 100644
--- a/org.eclipse.pde.doc.user/pom.xml
+++ b/org.eclipse.pde.doc.user/pom.xml
@@ -17,7 +17,7 @@
     <version>4.38.0-SNAPSHOT</version>
   </parent>
   <artifactId>org.eclipse.pde.doc.user</artifactId>
-  <version>3.17.300-SNAPSHOT</version>
+  <version>3.17.400-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
   
   <properties>

I also had to take the version bumps by the bot here.

Then I see the validation dialog popped up and the tests seem to be waiting forever on it:

image
"main" #1 [74324] prio=6 os_prio=0 cpu=13219.50ms elapsed=4611.57s tid=0x00007f5d84019d50 nid=74324 runnable  [0x00007f5d8b5fa000]
   java.lang.Thread.State: RUNNABLE
        at org.eclipse.swt.internal.gtk.OS.Call(Native Method)
        at org.eclipse.swt.widgets.Display.sleep(Display.java:5675)
        at org.eclipse.jface.window.Window.runEventLoop(Window.java:825)
        at org.eclipse.jface.window.Window.open(Window.java:804)
        at org.eclipse.pde.internal.ui.launcher.PluginValidationStatusHandler.lambda$0(PluginValidationStatusHandler.java:64)
        at org.eclipse.pde.internal.ui.launcher.PluginValidationStatusHandler$$Lambda/0x00007f5d0c728d88.run(Unknown Source)
        at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:183)
        at org.eclipse.ui.internal.UISynchronizer.syncExec(UISynchronizer.java:136)
        at org.eclipse.swt.widgets.Display.syncExec(Display.java:5994)
        at org.eclipse.pde.internal.ui.launcher.PluginValidationStatusHandler.displayValidationError(PluginValidationStatusHandler.java:58)
        at org.eclipse.pde.internal.ui.launcher.PluginValidationStatusHandler.handleStatus(PluginValidationStatusHandler.java:43)
        at org.eclipse.pde.internal.launching.launcher.LaunchPluginValidator.runValidationOperation(LaunchPluginValidator.java:111)
        at org.eclipse.pde.launching.JUnitLaunchConfigurationDelegate.validatePluginDependencies(JUnitLaunchConfigurationDelegate.java:614)
        at org.eclipse.pde.launching.JUnitLaunchConfigurationDelegate.preLaunchCheck(JUnitLaunchConfigurationDelegate.java:533)
        at org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate.getVMRunnerConfiguration(JUnitLaunchConfigurationDelegate.java:138)
        at org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate.launch(JUnitLaunchConfigurationDelegate.java:275)
        - locked <0x000000071f500910> (a org.eclipse.pde.launching.JUnitLaunchConfigurationDelegate)
        at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:778)
        at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:689)
        at org.eclipse.debug.internal.ui.DebugUIPlugin.buildAndLaunch(DebugUIPlugin.java:1052)
        at org.eclipse.debug.ui.DebugUITools.buildAndLaunch(DebugUITools.java:1044)
        at org.eclipse.pde.junit.runtime.tests.TestExecutionUtil.launchAndWaitForTermination(TestExecutionUtil.java:126)
        at org.eclipse.pde.junit.runtime.tests.TestExecutionUtil.runTest(TestExecutionUtil.java:81)
        at org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest.executePackage(JUnitExecutionTest.java:111)

That seems to be part of .m2:

➜  ~ ls -la /tmp/test/.m2/repository/org/junit/platform/junit-platform-suite-engine
total 0
drwxr-xr-x 4 sandreev sandreev  80 Oct 17 13:11 .
drwxr-xr-x 9 sandreev sandreev 180 Oct 17 13:11 ..
drwxr-xr-x 2 sandreev sandreev 240 Oct 17 13:11 1.14.0
drwxr-xr-x 2 sandreev sandreev 240 Oct 17 13:11 6.0.0

But its not loaded in the process:

➜  ~ lsof -p 74321 | grep "jupiter"
java    74321 sandreev  45r      REG               0,42    242442   132934 /tmp/test/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.14.0/junit-jupiter-api-5.14.0.jar
java    74321 sandreev  87r      REG               0,42    341011   132947 /tmp/test/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.14.0/junit-jupiter-engine-5.14.0.jar

I'm not sure what is missing here... The pom.xml does have this requirement:

							<requirement>
								<type>eclipse-plugin</type>
								<id>org.eclipse.jdt.junit5.runtime</id>
								<versionRange>0.0.0</versionRange>
							</requirement>

Maybe we have somehow messed up other requirements...

I don't see anything unusual there, with standard out prints:

Running JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest
Before:
junit-jupiter-engine_5.14.0
junit-platform-commons_1.14.0
junit-platform-engine_1.14.0
junit-jupiter-api_5.14.0
junit-platform-launcher_1.14.0
After:
junit-jupiter-engine_5.14.0
junit-platform-commons_1.14.0
junit-platform-engine_1.14.0
junit-jupiter-api_5.14.0
junit-platform-launcher_1.14.0
junit-platform-suite-engine_1.14.0
junit-platform-suite-commons_1.14.0
junit-platform-runner_1.14.0
junit-vintage-engine_5.14.0
junit-jupiter-migrationsupport_5.14.0
junit-jupiter-params_5.14.0
junit-platform-suite-api_1.14.0
diff --git a/ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/JUnitLaunchConfigurationDelegate.java b/ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/JUnitLaunchConfigurationDelegate.java
index dfd2610cdf..47db0ff9b7 100644
--- a/ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/JUnitLaunchConfigurationDelegate.java
+++ b/ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/JUnitLaunchConfigurationDelegate.java
@@ -518,9 +518,15 @@ public class JUnitLaunchConfigurationDelegate extends org.eclipse.jdt.junit.laun
                fAllBundles = fModels.keySet().stream().collect(Collectors.groupingBy(m -> m.getPluginBase().getId(), LinkedHashMap::new, Collectors.toCollection(ArrayList::new)));
                launchMode = launch.getLaunchMode();
 
+               System.out.println("Before:");
+               fModels.keySet().stream().map(IPluginModelBase::getBundleDescription).filter(d -> d.getSymbolicName().startsWith("junit")).forEach(System.out::println);
+
                // implicitly add the plug-ins required for JUnit testing if necessary
                JUnitLaunchRequirements.addRequiredJunitRuntimePlugins(configuration, fAllBundles, fModels);
 
+               System.out.println("After:");
+               fModels.keySet().stream().map(IPluginModelBase::getBundleDescription).filter(d -> d.getSymbolicName().startsWith("junit")).forEach(System.out::println);
+
                String attribute = launch.getAttribute(PDE_JUNIT_SHOW_COMMAND);
                boolean isShowCommand = false;
                if (attribute != null) {

I guess I'll have to debug this, I don't know why there is a missing bundle.

The bundle description for junit-platform-suite-engine collides with the one for org.apiguardian.api:

88 -> junit-platform-suite-engine_1.14.0

Both have ID 88. From then on org.eclipse.osgi.internal.resolver.StateImpl.add(BundleDescription, Map<Long, BundleDescription>, boolean) doesn't add junit-platform-suite-engine, since it already has org.apiguardian.api...

I.e.:

Running JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest
Before:
40 -> junit-jupiter-api_5.14.0
48 -> junit-platform-commons_1.14.0
52 -> junit-platform-launcher_1.14.0
50 -> junit-platform-engine_1.14.0
42 -> junit-jupiter-engine_5.14.0
88 -> org.apiguardian.api_1.1.2
After:
40 -> junit-jupiter-api_5.14.0
48 -> junit-platform-commons_1.14.0
52 -> junit-platform-launcher_1.14.0
50 -> junit-platform-engine_1.14.0
42 -> junit-jupiter-engine_5.14.0
88 -> org.apiguardian.api_1.1.2
29 -> junit-platform-runner_1.14.0
5 -> junit-platform-suite-api_1.14.0
196 -> junit-jupiter-migrationsupport_5.14.0
4 -> junit-vintage-engine_5.14.0
142 -> junit-platform-suite-commons_1.14.0
118 -> junit-jupiter-params_5.14.0
88 -> junit-platform-suite-engine_1.14.0

@trancexpress
Copy link
Contributor Author

We definitely have more problems here. Trying to run org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest results in errors:

Caused by: java.util.ServiceConfigurationError: org.junit.platform.engine.TestEngine: org.junit.jupiter.engine.JupiterTestEngine not a subtype

So looks like the replacement code doesn't work... In JUnitLaunchRequirements.addAbsentRequirements(), having a good and a bad version results in not replacing the bad version:

id=junit-platform-engine, replace=false
junit-platform-engine_6.0.0
junit-platform-engine_1.14.0

I do wonder how we have both though?...

@trancexpress
Copy link
Contributor Author

trancexpress commented Oct 17, 2025

diff --git a/ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/JUnitLaunchConfigurationDelegate.java b/ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/JUnitLaunchConfigurationDelegate.java
index dfd2610cdf..c4f53522a6 100644
--- a/ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/JUnitLaunchConfigurationDelegate.java
+++ b/ui/org.eclipse.pde.launching/src/org/eclipse/pde/launching/JUnitLaunchConfigurationDelegate.java
@@ -518,9 +518,15 @@ public class JUnitLaunchConfigurationDelegate extends org.eclipse.jdt.junit.laun
                fAllBundles = fModels.keySet().stream().collect(Collectors.groupingBy(m -> m.getPluginBase().getId(), LinkedHashMap::new, Collectors.toCollection(ArrayList::new)));
                launchMode = launch.getLaunchMode();
 
+               System.out.println("Before:");
+               fModels.keySet().stream().map(IPluginModelBase::getBundleDescription).filter(d -> d.getSymbolicName().startsWith("junit") || d.getSymbolicName().equals("org.apiguardian.api")).forEach(d -> System.out.println(d.getBun
dleId() + " -> " + d));
+
                // implicitly add the plug-ins required for JUnit testing if necessary
                JUnitLaunchRequirements.addRequiredJunitRuntimePlugins(configuration, fAllBundles, fModels);
 
+               System.out.println("After:");
+               fModels.keySet().stream().map(IPluginModelBase::getBundleDescription).filter(d -> d.getSymbolicName().startsWith("junit") || d.getSymbolicName().equals("org.apiguardian.api")).forEach(d -> System.out.println(d.getBun
dleId() + " -> " + d));
+
                String attribute = launch.getAttribute(PDE_JUNIT_SHOW_COMMAND);
                boolean isShowCommand = false;
                if (attribute != null) {
Running JUnitRuntimeTests org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest
Before:
40 -> junit-jupiter-api_5.14.0
48 -> junit-platform-commons_1.14.0
52 -> junit-platform-launcher_1.14.0
50 -> junit-platform-engine_1.14.0
42 -> junit-jupiter-engine_5.14.0
88 -> org.apiguardian.api_1.1.2
After:
40 -> junit-jupiter-api_5.14.0
48 -> junit-platform-commons_1.14.0
52 -> junit-platform-launcher_1.14.0
50 -> junit-platform-engine_1.14.0
42 -> junit-jupiter-engine_5.14.0
88 -> org.apiguardian.api_1.1.2
29 -> junit-platform-runner_1.14.0
5 -> junit-platform-suite-api_1.14.0
196 -> junit-jupiter-migrationsupport_5.14.0
4 -> junit-vintage-engine_5.14.0
142 -> junit-platform-suite-commons_1.14.0
118 -> junit-jupiter-params_5.14.0
88 -> junit-platform-suite-engine_1.14.0

@HannesWell could it be that by finding bundles in the target or in the host, we can get ID collisions like this? See IDs for junit-platform-suite-engine and org.apiguardian.api. Unfortunately I'm not familiar with how bundle IDs are computed.

	private static IPluginModelBase findRequiredPluginInTargetOrHost(String id, IPluginModelBase model) throws CoreException {
		System.out.println("id=" + id + ", model=" + model);
id=junit-platform-suite-engine, model=null

@merks
Copy link
Contributor

merks commented Oct 17, 2025

Maybe this table helps?

https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/table.html

The underlined things (5.14.0 and 1.14.0) would be part of a junit 5 launch, while all the 6.0.0 things would be part of a junit 6 launch:

image

Best the two sets not get mixed together in a launch.

@HannesWell
Copy link
Member

@HannesWell could it be that by finding bundles in the target or in the host, we can get ID collisions like this? See IDs for junit-platform-suite-engine and org.apiguardian.api. Unfortunately I'm not familiar with how bundle IDs are computed.

Sorry, this is a lot of input at the moment. I'm currently working through the change as it is to propose refinements and (besides others) to also consider version ranges when looking up dependencies in the host. Maybe this already helps.
I don't know how far I get with that today, but I'll let you know and will continue tomorrow.

@HannesWell
Copy link
Member

Best the two sets not get mixed together in a launch.

Absolutely!

@trancexpress
Copy link
Contributor Author

Maybe this table helps?

What the change computes in terms of versions is fine. Something else breaks, which makes plug-in validation miss one of the bundles. See my previous comments.

@HannesWell
Copy link
Member

I just added a commit with the suggestions from my review, but I didn't had the times to dive into the problem you described. Will do that tomorrow.
I cannot tell if my suggestions help at all in that regard (maybe they make it even worse they are not yet tested, as it's 'WIP').

trancexpress and others added 3 commits October 18, 2025 00:00
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: eclipse-pde#2006
- Move code a bit around, trying to simplify it a bit
- Implement version handling when looking up dependencies in host
- Avoid unnecessary code
- Add TODOs
@trancexpress
Copy link
Contributor Author

I just added a commit with the suggestions from my review, but I didn't had the times to dive into the problem you described. Will do that tomorrow. I cannot tell if my suggestions help at all in that regard (maybe they make it even worse they are not yet tested, as it's 'WIP').

With that commit on top of my changes, running the tests locally no longer results in a hang. I've pushed small changes I had to my commit that lead to merge conflicts with your changes, ideally please pull before you continue with your changes @HannesWell .

Note that the local build is failing if I don't do the version bumps from one of the commits I've pushed. From my POV better to have that change too, so that local builds don't fail.

@trancexpress
Copy link
Contributor Author

Fails on Linux/Windows:

 Errors: 
  JUnit5SuiteExecutionTest.executePackage:67 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnit5SuiteExecutionTest.executeProject:74 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnit5SuiteExecutionTest.executeSuite:52 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnitExecutionTest.executeMethod:129 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeMethod:129 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeMethod:129 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeMethod:129 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeMethod:129 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnitExecutionTest.executeMethod:129 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnitExecutionTest.executeMethod:129 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeMethod:129 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executePackage:111 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executePackage:111 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executePackage:111 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executePackage:111 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executePackage:111 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnitExecutionTest.executePackage:111 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnitExecutionTest.executePackage:111 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executePackage:111 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeProject:119 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeProject:119 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeProject:119 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeProject:119 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeProject:119 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnitExecutionTest.executeProject:119 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnitExecutionTest.executeProject:119 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeProject:119 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeType:102 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeType:102 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeType:102 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeType:102 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeType:102 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnitExecutionTest.executeType:102 � Core Required plug-in 'org.hamcrest' could not be found.
  JUnitExecutionTest.executeType:102 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.
  JUnitExecutionTest.executeType:102 � Core Required plug-in 'org.eclipse.equinox.preferences' could not be found.

E.g.:

org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest.executeMethod[JUnit5 Fragment] -- Time elapsed: 0.079 s <<< ERROR!
org.eclipse.core.runtime.CoreException: Required plug-in 'org.hamcrest' could not be found.
	at org.eclipse.pde.internal.launching.JUnitLaunchRequirements.findRequiredPluginInTargetOrHost(JUnitLaunchRequirements.java:144)
	at org.eclipse.pde.internal.launching.JUnitLaunchRequirements.addAbsentRequirements(JUnitLaunchRequirements.java:111)
	at org.eclipse.pde.internal.launching.JUnitLaunchRequirements.addRequiredJunitRuntimePlugins(JUnitLaunchRequirements.java:60)
	at org.eclipse.pde.launching.JUnitLaunchConfigurationDelegate.preLaunchCheck(JUnitLaunchConfigurationDelegate.java:522)
	at org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate.getVMRunnerConfiguration(JUnitLaunchConfigurationDelegate.java:138)
	at org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate.launch(JUnitLaunchConfigurationDelegate.java:275)
	at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:778)
	at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:689)
	at org.eclipse.debug.internal.ui.DebugUIPlugin.buildAndLaunch(DebugUIPlugin.java:1052)
	at org.eclipse.debug.ui.DebugUITools.buildAndLaunch(DebugUITools.java:1044)
	at org.eclipse.pde.junit.runtime.tests.TestExecutionUtil.launchAndWaitForTermination(TestExecutionUtil.java:126)
	at org.eclipse.pde.junit.runtime.tests.TestExecutionUtil.runTest(TestExecutionUtil.java:81)
	at org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest.executeMethod(JUnitExecutionTest.java:129)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.eclipse.pde.ui.tests.runtime.TestUtils$1.evaluate(TestUtils.java:267)

org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest.executePackage[JUnit4] -- Time elapsed: 0.097 s <<< ERROR!
org.eclipse.core.runtime.CoreException: Required plug-in 'org.eclipse.equinox.preferences' could not be found.
	at org.eclipse.pde.internal.launching.JUnitLaunchRequirements.findRequiredPluginInTargetOrHost(JUnitLaunchRequirements.java:144)
	at org.eclipse.pde.internal.launching.JUnitLaunchRequirements.addAbsentRequirements(JUnitLaunchRequirements.java:111)
	at org.eclipse.pde.internal.launching.JUnitLaunchRequirements.addRequiredJunitRuntimePlugins(JUnitLaunchRequirements.java:60)
	at org.eclipse.pde.launching.JUnitLaunchConfigurationDelegate.preLaunchCheck(JUnitLaunchConfigurationDelegate.java:522)
	at org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate.getVMRunnerConfiguration(JUnitLaunchConfigurationDelegate.java:138)
	at org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate.launch(JUnitLaunchConfigurationDelegate.java:275)
	at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:778)
	at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:689)
	at org.eclipse.debug.internal.ui.DebugUIPlugin.buildAndLaunch(DebugUIPlugin.java:1052)
	at org.eclipse.debug.ui.DebugUITools.buildAndLaunch(DebugUITools.java:1044)
	at org.eclipse.pde.junit.runtime.tests.TestExecutionUtil.launchAndWaitForTermination(TestExecutionUtil.java:126)
	at org.eclipse.pde.junit.runtime.tests.TestExecutionUtil.runTest(TestExecutionUtil.java:81)
	at org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest.executePackage(JUnitExecutionTest.java:111)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.eclipse.pde.ui.tests.runtime.TestUtils$1.evaluate(TestUtils.java:267)

- The JUNIT5_VERSIONS VersionRange should be [1, 6) because [1, 5)
excludes Junit 5.
- The case for TestKindRegistry.JUNIT5_TEST_KIND_ID should add
JUNIT5_JDT_RUNTIME_PLUGIN not JUNIT4_JDT_RUNTIME_PLUGIN.
- The search range `new VersionRange(VersionRange.LEFT_OPEN, version,
version, VersionRange.RIGHT_OPEN))` is always empty so should use `new
VersionRange(VersionRange.LEFT_CLOSED, version, version,
VersionRange.RIGHT_CLOSED))`.
@merks
Copy link
Contributor

merks commented Oct 18, 2025

There are some small but fundamentally important mistakes that I tried to correct in this commit:

cc9a4df

I created the following separate PR for that based on all the commits in this PR:

#2029

@HannesWell
Copy link
Member

With that commit on top of my changes, running the tests locally no longer results in a hang. I've pushed small changes I had to my commit that lead to merge conflicts with your changes, ideally please pull before you continue with your changes @HannesWell .

I believe I fetched before I pushed to your branch (and also didn't force push). I'm sorry if it caused trouble, I didn't meant to do that.

Note that the local build is failing if I don't do the version bumps from one of the commits I've pushed. From my POV better to have that change too, so that local builds don't fail.

Personally I often don't build locally but just let the CI do it, and as the bot just recreates the version increment quickly and therefore don't keep them. But I'll keep them here.

There are some small but fundamentally important mistakes that I tried to correct in this commit:

Sorry, it was a late for me after very long day and I oversaw some things. Will incorporate your changes, they are all correct.

Copy link
Member

@HannesWell HannesWell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have now in cooperated the fixes suggested by Ed in
#2029

Furthermore I have removed parts that are actually unnecessary, see below.
For the moment I added these changes as separate commit, but eventually it should be squashed.

Comment on lines 112 to 119
if (replace) {
String startLevel = null;
for (IPluginModelBase m : models) {
startLevel = allModels.remove(m);
}
models.clear();
allModels.put(model, startLevel); //TODO: isn't this overwritten? Should it be retained or just ignored?
}
Copy link
Member

@HannesWell HannesWell Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that we now only add requirements of the o.e.jdt.junitX.runtime here and in general is possible that the same one bundle is present in a runtime in multiple versions, but it's generally recommended to use only one JUnit version at the time and not mix them, I wonder if we really should have this replacement here?
I think it might be better to just add each requirement here, if there isn't an exactly matching version present already.
@trancexpress what do you think?

One also has to consider that we're just considering here what's added to the runtime. During Start-up the OSGi Framework will create all the wiring and among all bundles available in the runtime.
And while generally one should be precise when assembling the runtime and should ideally neither add too many nor too few bundles, just replacing what was deemed required before can also be destructive.
Therefore in this place I would say: Better add a bit more than remove bundles.
The conflicts could not only arise among the JUnit bundles, but also among the other requirements of the o.e.jdt.junitX.runtime bundle.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't understand this at all. While debugging the startLevel was assignment multiple times; most just null.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't say, I'll need to re-test what I describe here: #2013 (comment)

I'm all for less code, if I can still run tests as usual.

Copy link
Contributor Author

@trancexpress trancexpress Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that its best to work on this with both JUnit 5 and 6 in the platform.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, when I commented out the remove with the following in the target platform I did have problems launching.

image
Caused by: java.util.ServiceConfigurationError: org.junit.platform.engine.TestEngine: org.junit.jupiter.engine.JupiterTestEngine not a subtype
	at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:593)

I don't understand the startLevel thing though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first non-null would seem more sensible than overwriting the variable without checking the value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can just expect users to change their manifests to restrict JUnit to "[5,6)" for a JUnit 5 launch, leaving the code as is.

Once we have JUnit 6 launches and its default, any new launch configuration will just work, assuming JRE 17+.

Old launched will need either JUnit 6 type change, or the respective plug-in will need version restrictions.

I guess there can be subtile problems without the version restriction anyway, e.g. at compile time. We would have a disruptive change though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

org.eclipse.swt.SWTException: Failed to execute runnable (java.util.ServiceConfigurationError: org.junit.platform.engine.TestEngine: org.junit.jupiter.engine.JupiterTestEngine not a subtype)

I can reproduce that error when launching a secondary Eclipse just from my 'PDE' workspace, where I only have the PDE repo checked out and get everything else from the latest I-build repo. In the that secondary Eclipse I use the following target definition to have JUnit-5 and 6 to the TP:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde version="3.8"?>
<target includeMode="feature" name="featureBased">
	<locations>
		<location includeAllPlatforms =   "false"   includeConfigurePhase  = "true" includeMode="planner" includeSource="true" type="InstallableUnit">
			<repository location="https://download.eclipse.org/eclipse/updates/4.38-I-builds/"/>
			<repository location="https://download.eclipse.org/tools/orbit/simrel/orbit-aggregation/milestone/latest"/>
			<unit id="org.eclipse.sdk.feature.group" />
			<unit id="junit-jupiter-api" version="[5,6)"/>
			<unit id="junit-jupiter-engine" version="[5,6)"/>
			<unit id="junit-jupiter-api" />
			<unit id="junit-jupiter-engine" />
		</location>
	</locations>
</target>

I think the only difference to your state is the absence of the new org.eclipse.jdt.junit6.runtime bundle. But as that's not yet considered by PDE (I assume you plan a follow-up once it's ready?) and therefore I assume it doesn't make a difference?
In the secondary Eclipse I have created a test-plugin with the requirement
Import-Package: org.junit.jupiter.api;version="5.0.0",
which is currently equivalent to
Import-Package: org.junit.jupiter.api;version="[5.0.0,7.0.0)"
(but I think the former is what's encountered more often in practice).

Launching then fails with the described error:
Caused by: java.util.ServiceConfigurationError: org.junit.platform.engine.TestEngine: org.junit.jupiter.engine.JupiterTestEngine not a subtype

The reason is as, as indicated in #2013 (comment), that we now have two versions of the org.junit.jupiter.engine.JupiterTestEngine class in the runtime. One from junit-jupiter-engine version 5 and one from version 6. As the ServiceLoader discovers the classes by name, both are found and version 6 even seems to be preferred (I guess OSGi somehow prefers the greater version although I'm surprised the ServiceLoader works for JUnit without SPI. Maybe they have some more specialties).

The make a long story short: Having especially two versions of junit-jupiter-engine in one test-runtime is indeed a problem.
So that should be prevented. But at the same time we cannot generally prevent duplicated versions.

I guess we can just expect users to change their manifests to restrict JUnit to "[5,6)" for a JUnit 5 launch, leaving the code as is.

Once we have JUnit 6 launches and its default, any new launch configuration will just work, assuming JRE 17+.

Old launched will need either JUnit 6 type change, or the respective plug-in will need version restrictions.

I guess there can be subtile problems without the version restriction anyway, e.g. at compile time. We would have a disruptive change though.

In the context of what I've written above I second each of your statements. Having a JUnit-5 launch with JUnit-6 bundles simple doesn't work out well.

And instead of trying to be smart when launching, my suggestion is to make it clear to a user and help them to get a clean state. Therefore my suggestion is to only add a detection if the runtime contains two different versions of junit-jupiter-engine (or its old name) and if that's the case, to open a dialog explaining the problem to the user and asking to restrict version ranges or to update test launch type.
But we can also do this in a follow-up when JUnit-6 is supported by JDT.

The only thing that has to be investigated is the starvation of the org.eclipse.pde.junit.runtime.tests. I assume they don't have proper version ranges too.
I'll investigate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And instead of trying to be smart when launching, my suggestion is to make it clear to a user and help them to get a clean state. Therefore my suggestion is to only add a detection if the runtime contains two different versions of junit-jupiter-engine (or its old name) and if that's the case, to open a dialog explaining the problem to the user and asking to restrict version ranges or to update test launch type.
But we can also do this in a follow-up when JUnit-6 is supported by JDT.

Last but not least PDE should encourage users from the beginning to use suitable version ranges. While this is already the case for page imports, it's not yet done for required bundles. But the latter should be easy to do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the only difference to your state is the absence of the new org.eclipse.jdt.junit6.runtime bundle. But as that's not yet considered by PDE (I assume you plan a follow-up once it's ready?)

Yes, once this problem is out of the way.

@HannesWell HannesWell mentioned this pull request Oct 18, 2025
@trancexpress
Copy link
Contributor Author

I did manual tests with the changes here, I didn't find issues. Would be good to squash the main changes into one commit and leave the version bump commits as is.

@merks
Copy link
Contributor

merks commented Oct 18, 2025

It's odd that the following PR's jenkins job ran but this PR's jenkins job doesn't run ever!

https://ci.eclipse.org/pde/job/eclipse.pde/view/change-requests/job/PR-2029/

@HannesWell
Copy link
Member

I did manual tests with the changes here, I didn't find issues. Would be good to squash the main changes into one commit and leave the version bump commits as is.

Awesome. I just pushed another commit to further simplify/unify the search in the host and to remove the 'replacement' as suggested above.

I have to leave now, but I try to continue this evening or tomorrow morning.

Regarding your response from: #2013 (comment)

I can't say, I'll need to re-test what I describe here: #2013 (comment)

I'm all for less code, if I can still run tests as usual.

Maybe this was because org.eclipse.jdt.junit5.runtime didn't have had proper version ranges?
Because from the current code I cannot see where such an 'unbound' addition should come from.
Assuming that 'org.eclipse.jdt.junit4.runtime' and 'org.eclipse.jdt.junit5.runtime' won't have new major versions for other JUnit-version.

It's odd that the following PR's jenkins job ran but this PR's jenkins job doesn't run ever!

https://ci.eclipse.org/pde/job/eclipse.pde/view/change-requests/job/PR-2029/

Indeed. But I see it in other PRs too. Maybe it only works for Committers atm?

@laeubi
Copy link
Contributor

laeubi commented Oct 18, 2025

Caused by: java.util.ServiceConfigurationError: org.junit.platform.engine.TestEngine: org.junit.jupiter.engine.JupiterTestEngine not a subtype
at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:593)

I just wanted to note that due to the current way we execute the JUnit runtime it does not really follows OSGi semantic when it comes to SPI loading.

Because of this I prototype a new approach in Tycho that loads the JUnit Engine through the classloader of the testprobe and then installs a special SPI classloader as the thread-context loader. The important part here is to check if two SPI impls are classloader compatible.

This al works quite neat, but also shows for the matter here, that adding to much will result in problems even though OSGi itself can sort it out for its own runtime!

@trancexpress
Copy link
Contributor Author

trancexpress commented Oct 20, 2025

I see a hang when I run tests locally, with the latest batch of changes.

"main" #1 [35208] prio=6 os_prio=0 cpu=14948.25ms elapsed=5684.24s tid=0x00007fe168019d50 nid=35208 runnable  [0x00007fe16c5fa000]
   java.lang.Thread.State: RUNNABLE
        at org.eclipse.swt.internal.gtk.OS.Call(Native Method)
        at org.eclipse.swt.widgets.Display.sleep(Display.java:5675)
        at org.eclipse.jface.window.Window.runEventLoop(Window.java:825)
        at org.eclipse.jface.window.Window.open(Window.java:804)
        at org.eclipse.pde.internal.ui.launcher.PluginValidationStatusHandler.lambda$0(PluginValidationStatusHandler.java:64)
        at org.eclipse.pde.internal.ui.launcher.PluginValidationStatusHandler$$Lambda/0x00007fe0f4718d88.run(Unknown Source)
        at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:183)
        at org.eclipse.ui.internal.UISynchronizer.syncExec(UISynchronizer.java:136)
        at org.eclipse.swt.widgets.Display.syncExec(Display.java:5994)
        at org.eclipse.pde.internal.ui.launcher.PluginValidationStatusHandler.displayValidationError(PluginValidationStatusHandler.java:58)
        at org.eclipse.pde.internal.ui.launcher.PluginValidationStatusHandler.handleStatus(PluginValidationStatusHandler.java:43)
        at org.eclipse.pde.internal.launching.launcher.LaunchPluginValidator.runValidationOperation(LaunchPluginValidator.java:111)
        at org.eclipse.pde.launching.JUnitLaunchConfigurationDelegate.validatePluginDependencies(JUnitLaunchConfigurationDelegate.java:614)
        at org.eclipse.pde.launching.JUnitLaunchConfigurationDelegate.preLaunchCheck(JUnitLaunchConfigurationDelegate.java:533)
        at org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate.getVMRunnerConfiguration(JUnitLaunchConfigurationDelegate.java:138)
        at org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate.launch(JUnitLaunchConfigurationDelegate.java:275)
        - locked <0x000000071ec93160> (a org.eclipse.pde.launching.JUnitLaunchConfigurationDelegate)
        at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:778)
        at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:689)
        at org.eclipse.debug.internal.ui.DebugUIPlugin.buildAndLaunch(DebugUIPlugin.java:1052)
        at org.eclipse.debug.ui.DebugUITools.buildAndLaunch(DebugUITools.java:1044)
        at org.eclipse.pde.junit.runtime.tests.TestExecutionUtil.launchAndWaitForTermination(TestExecutionUtil.java:126)
        at org.eclipse.pde.junit.runtime.tests.TestExecutionUtil.runTest(TestExecutionUtil.java:81)
        at org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest.executePackage(JUnitExecutionTest.java:111)

I'll check if we can abort the launch on JUnit 5 launch but JUnit 6 used, that might at least avoid hangs... if there is no dialog for the abort.

Doesn't help, the problem we have is the same as what I described here:

#2013 (comment)

There is an ID collision between org.apiguardian.api_1.1.2 and junit-platform-suite-engine_1.14.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use version constraints from org.junit.jupiter.api when automatically adding JUnit 5 bundles to test launch

6 participants