diff --git a/ui/org.eclipse.pde.junit.runtime.tests/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.junit.runtime.tests/META-INF/MANIFEST.MF index 125afb6d755..44ca6b172ef 100644 --- a/ui/org.eclipse.pde.junit.runtime.tests/META-INF/MANIFEST.MF +++ b/ui/org.eclipse.pde.junit.runtime.tests/META-INF/MANIFEST.MF @@ -19,6 +19,7 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.29.0", org.eclipse.pde.ui.tests;bundle-version="3.11.500", org.eclipse.jdt.junit4.runtime;bundle-version="[1.3.0,2.0.0)", org.eclipse.jdt.junit5.runtime;bundle-version="[1.1.0,2.0.0)", + org.eclipse.jdt.junit6.runtime;bundle-version="[1.0.0,2.0.0)", org.eclipse.pde.junit.runtime;bundle-version="[3.8.0,4.0.0)" Import-Package: org.assertj.core.api;version="3.14.0", org.junit, diff --git a/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnit6SuiteExecutionTest.java b/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnit6SuiteExecutionTest.java new file mode 100644 index 00000000000..4c383970b8e --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnit6SuiteExecutionTest.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2025 Julian Honnen + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Julian Honnen - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.junit.runtime.tests; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.pde.junit.runtime.tests.JUnitExecutionTest.findType; + +import java.util.StringJoiner; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.internal.junit.model.TestElement; +import org.eclipse.jdt.junit.model.ITestElement; +import org.eclipse.jdt.junit.model.ITestElementContainer; +import org.eclipse.jdt.junit.model.ITestRunSession; +import org.eclipse.pde.ui.tests.util.ProjectUtils; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TestRule; + +public class JUnit6SuiteExecutionTest { + + @ClassRule + public static final TestRule CLEAR_WORKSPACE = ProjectUtils.DELETE_ALL_WORKSPACE_PROJECTS_BEFORE_AND_AFTER; + + private static IJavaProject project; + + @BeforeClass + public static void setupProjects() throws Exception { + Assert.assertNotNull("junit-platform-suite-engine bundle missing", Platform.getBundle("junit-platform-suite-engine")); + Assert.assertNotNull("org.eclipse.jdt.junit6.runtime bundle missing", Platform.getBundle("org.eclipse.jdt.junit6.runtime")); + + JUnitExecutionTest.setupProjects(); + project = JUnitExecutionTest.getJProject("verification.tests.junit6.suite"); + } + + @Test + public void executeSuite() throws Exception { + ITestRunSession session = TestExecutionUtil.runTest(findType(project, "TestSuite")); + JUnitExecutionTest.assertSuccessful(session); + Assert.assertEquals(""" + verification.tests.junit6.suite.TestSuite + JUnit Jupiter + verification.tests.junit6.Test1 + test1(verification.tests.junit6.Test1) + test2(verification.tests.junit6.Test1) + verification.tests.junit6.Test2 + test(verification.tests.junit6.Test2) + """.strip(), toString(session).strip()); + } + + @Test + public void executePackage() throws Exception { + ITestRunSession session = TestExecutionUtil.runTest(findType(project, "TestSuite").getPackageFragment()); + JUnitExecutionTest.assertSuccessful(session); + assertThat(session.getChildren()).isNotEmpty(); + } + + @Test + public void executeProject() throws Exception { + ITestRunSession session = TestExecutionUtil.runTest(project); + JUnitExecutionTest.assertSuccessful(session); + assertThat(session.getChildren()).isNotEmpty(); + } + + private static String toString(ITestRunSession session) { + StringJoiner sb = new StringJoiner("\n"); + for (ITestElement element : session.getChildren()) { + append(sb, element, 0); + } + return sb.toString(); + } + + private static void append(StringJoiner sb, ITestElement element, int indent) { + sb.add(" ".repeat(indent) + ((TestElement) element).getTestName()); + if (element instanceof ITestElementContainer container) { + for (ITestElement child : container.getChildren()) { + append(sb, child, indent + 1); + } + } + } + +} diff --git a/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnitExecutionTest.java b/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnitExecutionTest.java index d4f2c76c3a8..1706fd8759a 100644 --- a/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnitExecutionTest.java +++ b/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnitExecutionTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 Julian Honnen + * Copyright (c) 2019, 2025 Julian Honnen * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -77,7 +77,10 @@ public static void setupProjects() throws Exception { @Parameters(name = "{0}") public static Object[][] parameters() { - return new Object[][] { { "JUnit5", getJProject("verification.tests.junit5") }, + return new Object[][] { + { "JUnit6", getJProject("verification.tests.junit6") }, + { "JUnit6 Fragment", getJProject("verification.tests.junit6.fragment") }, + { "JUnit5", getJProject("verification.tests.junit5") }, { "JUnit5 Fragment", getJProject("verification.tests.junit5.fragment") }, { "JUnit4", getJProject("verification.tests.junit4") }, { "JUnit4 Fragment", getJProject("verification.tests.junit4.fragment") }, diff --git a/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnitRuntimeTests.java b/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnitRuntimeTests.java index ba9ba65f00c..ae2a10103ae 100644 --- a/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnitRuntimeTests.java +++ b/ui/org.eclipse.pde.junit.runtime.tests/src/org/eclipse/pde/junit/runtime/tests/JUnitRuntimeTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 Julian Honnen + * Copyright (c) 2019, 2025 Julian Honnen * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -18,7 +18,7 @@ import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) -@SuiteClasses({ JUnitExecutionTest.class, JUnit5SuiteExecutionTest.class }) +@SuiteClasses({ JUnitExecutionTest.class, JUnit5SuiteExecutionTest.class, JUnit6SuiteExecutionTest.class }) public class JUnitRuntimeTests { } diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/.classpath b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/.classpath new file mode 100644 index 00000000000..675a5e2962b --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/.project b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/.project new file mode 100644 index 00000000000..3716aef27b9 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/.project @@ -0,0 +1,28 @@ + + + verification.tests.junit6.fragment + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/.settings/org.eclipse.jdt.core.prefs b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0c68a61dca8 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..44da3b74804 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/META-INF/MANIFEST.MF @@ -0,0 +1,9 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Fragment +Bundle-SymbolicName: verification.tests.junit6.fragment +Bundle-Version: 1.0.0.qualifier +Fragment-Host: verification.tests.junit5;bundle-version="1.0.0.qualifier" +Automatic-Module-Name: verification.tests.junit6.fragment +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Export-Package: verification.tests.junit6.fragment diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/build.properties b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/build.properties new file mode 100644 index 00000000000..34d2e4d2dad --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/src/verification/tests/junit6/fragment/Test1.java b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/src/verification/tests/junit6/fragment/Test1.java new file mode 100644 index 00000000000..83d4ae85770 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/src/verification/tests/junit6/fragment/Test1.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2025 Julian Honnen + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Julian Honnen - initial API and implementation + *******************************************************************************/ +package verification.tests.junit6.fragment; + +import org.junit.jupiter.api.Test; + +class Test1 { + + @Test + void test1() { + + } + + @Test + void test2() { + + } + +} diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/src/verification/tests/junit6/fragment/Test2.java b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/src/verification/tests/junit6/fragment/Test2.java new file mode 100644 index 00000000000..6335f113c58 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.fragment/src/verification/tests/junit6/fragment/Test2.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Julian Honnen + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Julian Honnen - initial API and implementation + *******************************************************************************/ +package verification.tests.junit6.fragment; + +import org.junit.jupiter.api.Test; + +class Test2 { + + @Test + void test() { + + } + +} diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/.classpath b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/.classpath new file mode 100644 index 00000000000..675a5e2962b --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/.project b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/.project new file mode 100644 index 00000000000..bfd1abdc735 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/.project @@ -0,0 +1,28 @@ + + + verification.tests.junit6.suite + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/.settings/org.eclipse.jdt.core.prefs b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0c68a61dca8 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..27ce8cabbc8 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/META-INF/MANIFEST.MF @@ -0,0 +1,10 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Tests +Bundle-SymbolicName: verification.tests.junit6.suite +Bundle-Version: 1.0.0.qualifier +Automatic-Module-Name: verification.tests +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Require-Bundle: junit-platform-suite-api;bundle-version="[6.0.0,7.0.0)", + verification.tests.junit6 +Export-Package: verification.tests.junit6.suite diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/build.properties b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/build.properties new file mode 100644 index 00000000000..34d2e4d2dad --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/src/verification/tests/junit6/suite/TestSuite.java b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/src/verification/tests/junit6/suite/TestSuite.java new file mode 100644 index 00000000000..6275982bc02 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6.suite/src/verification/tests/junit6/suite/TestSuite.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2025 Julian Honnen + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Julian Honnen - initial API and implementation + *******************************************************************************/ +package verification.tests.junit6.suite; + +import org.junit.platform.suite.api.SelectClasses; +import org.junit.platform.suite.api.Suite; + +@Suite +@SelectClasses({ verification.tests.junit6.Test1.class, verification.tests.junit6.Test2.class }) +class TestSuite { + +} diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/.classpath b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/.classpath new file mode 100644 index 00000000000..675a5e2962b --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/.project b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/.project new file mode 100644 index 00000000000..5748e70184b --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/.project @@ -0,0 +1,28 @@ + + + verification.tests.junit6 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/.settings/org.eclipse.jdt.core.prefs b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0c68a61dca8 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..37b46c1839d --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/META-INF/MANIFEST.MF @@ -0,0 +1,9 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Tests +Bundle-SymbolicName: verification.tests.junit6 +Bundle-Version: 1.0.0.qualifier +Automatic-Module-Name: verification.tests +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Require-Bundle: junit-jupiter-api;bundle-version="[6.0.0,7.0.0)" +Export-Package: verification.tests.junit6 diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/build.properties b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/build.properties new file mode 100644 index 00000000000..34d2e4d2dad --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/src/verification/tests/junit6/Test1.java b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/src/verification/tests/junit6/Test1.java new file mode 100644 index 00000000000..db8ac1c98e3 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/src/verification/tests/junit6/Test1.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2025 Julian Honnen + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Julian Honnen - initial API and implementation + *******************************************************************************/ +package verification.tests.junit6; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class Test1 { + + @Test + void test1() { + try { + Thread.currentThread().getContextClassLoader().loadClass("doesnt.exist"); + Assertions.fail("ClassNotFoundException expected"); + } catch (ClassNotFoundException e) { + // expected + } + } + + @Test + void test2() { + + } + +} diff --git a/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/src/verification/tests/junit6/Test2.java b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/src/verification/tests/junit6/Test2.java new file mode 100644 index 00000000000..2976eee1b76 --- /dev/null +++ b/ui/org.eclipse.pde.junit.runtime.tests/test-bundles/verification.tests.junit6/src/verification/tests/junit6/Test2.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Julian Honnen + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Julian Honnen - initial API and implementation + *******************************************************************************/ +package verification.tests.junit6; + +import org.junit.jupiter.api.Test; + +public class Test2 { + + @Test + void test() { + + } + +} diff --git a/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/Caller.java b/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/Caller.java index 25e47c35005..bf08e471162 100644 --- a/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/Caller.java +++ b/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/Caller.java @@ -28,26 +28,31 @@ public class Caller { private static final String JUNIT_PLATFORM_LAUNCHER = "org.junit.platform.launcher"; //$NON-NLS-1$ private static final Bundle BUNDLE = FrameworkUtil.getBundle(Caller.class); - private static final Bundle loaderBundle; + static final Bundle loaderBundle5; + static final Bundle loaderBundle6; static { - Bundle junit5RuntimeBundle = Platform.getBundle("org.eclipse.jdt.junit5.runtime"); //$NON-NLS-1$ - if (junit5RuntimeBundle == null) { + loaderBundle5 = findJUnitBundle("org.eclipse.jdt.junit5.runtime", 5); //$NON-NLS-1$ + loaderBundle6 = findJUnitBundle("org.eclipse.jdt.junit6.runtime", 6); //$NON-NLS-1$ + } + + private static Bundle findJUnitBundle(String bundleId, int junitVersion) { + Bundle junitRuntimeBundle = Platform.getBundle(bundleId); + if (junitRuntimeBundle == null) { Bundle junit4RuntimeBundle = Platform.getBundle("org.eclipse.jdt.junit4.runtime"); //$NON-NLS-1$ - loaderBundle = findJUnit5LauncherByRuntime(junit4RuntimeBundle); - } else { - loaderBundle = junit5RuntimeBundle; + return findJUnitLauncherByRuntime(junit4RuntimeBundle, junitVersion); } + return junitRuntimeBundle; } - protected static Bundle findJUnit5LauncherByRuntime(Bundle junit4RuntimeBundle) { + protected static Bundle findJUnitLauncherByRuntime(Bundle junit4RuntimeBundle, int majorVersion) { if (junit4RuntimeBundle == null) { return BUNDLE; } for (Bundle bundle : BUNDLE.getBundleContext().getBundles()) { BundleWiring bundleWiring = bundle.adapt(BundleWiring.class); List capabilities = bundleWiring.getCapabilities(JUNIT_PLATFORM_LAUNCHER); - if (!capabilities.isEmpty() && bundle.getVersion().getMajor() < 6) { + if (!capabilities.isEmpty() && bundle.getVersion().getMajor() == majorVersion) { return bundle; } } @@ -55,7 +60,7 @@ protected static Bundle findJUnit5LauncherByRuntime(Bundle junit4RuntimeBundle) return BUNDLE; } - static Bundle getBundle() { + static Bundle getBundle(Bundle loaderBundle) { StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); for (StackTraceElement element : stackTraceElements) { try { diff --git a/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/RemotePluginTestRunner.java b/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/RemotePluginTestRunner.java index eb1ee1541af..cdb780800b2 100644 --- a/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/RemotePluginTestRunner.java +++ b/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/RemotePluginTestRunner.java @@ -29,6 +29,7 @@ import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.VersionRange; import org.osgi.framework.wiring.BundleWiring; /** @@ -36,6 +37,10 @@ */ public class RemotePluginTestRunner extends RemoteTestRunner { + private static final String ORG_ECLIPSE_JDT_JUNIT5_RUNTIME = "org.eclipse.jdt.junit5.runtime"; //$NON-NLS-1$ + private static final String ORG_ECLIPSE_JDT_JUNIT6_RUNTIME = "org.eclipse.jdt.junit6.runtime"; //$NON-NLS-1$ + private static final VersionRange JUNIT5_VERSION_RANGE = new VersionRange("[1.0.0,6.0.0)"); //$NON-NLS-1$ + private static final VersionRange JUNIT6_VERSION_RANGE = new VersionRange("[6.0.0,7.0.0)"); //$NON-NLS-1$ private String fTestPluginName; private ClassLoader fLoaderClassLoader; @@ -102,13 +107,24 @@ public static void main(String[] args) { RemotePluginTestRunner testRunner = new RemotePluginTestRunner(); testRunner.init(args); ClassLoader currentTCCL = Thread.currentThread().getContextClassLoader(); - if (isJUnit5(args)) { - //change the classloader so that the test classes in testplugin are discoverable - //by junit5 framework see bug 520811 - Thread.currentThread().setContextClassLoader(createJUnit5PluginClassLoader(testRunner.getTestPluginName())); + boolean isJUnit5 = isJUnit5(args); + boolean isJUnit6 = !isJUnit5 && isJUnit6(args); + String junitRuntimeBundle = ORG_ECLIPSE_JDT_JUNIT6_RUNTIME; + VersionRange junitVersionRange = JUNIT6_VERSION_RANGE; + Bundle loaderBundle = Caller.loaderBundle6; + if (isJUnit5) { + junitRuntimeBundle = ORG_ECLIPSE_JDT_JUNIT5_RUNTIME; + junitVersionRange = JUNIT5_VERSION_RANGE; + loaderBundle = Caller.loaderBundle5; + } + boolean isJUnitJupiter = isJUnit5 || isJUnit6; + //change the classloader so that the test classes in testplugin are discoverable + //by junit5 framework see bug 520811 + if (isJUnitJupiter) { + Thread.currentThread().setContextClassLoader(createJUnitJupiterPluginClassLoader(testRunner.getTestPluginName(), junitRuntimeBundle, junitVersionRange, loaderBundle)); } testRunner.run(); - if (isJUnit5(args)) { + if (isJUnitJupiter) { Thread.currentThread().setContextClassLoader(currentTCCL); } } @@ -131,21 +147,21 @@ private static String getState(int state) { return Integer.toString(state); } - private static ClassLoader createJUnit5PluginClassLoader(String testPluginName) { + private static ClassLoader createJUnitJupiterPluginClassLoader(String testPluginName, String junitRuntimeBundle, VersionRange versionRange, Bundle loaderBundle) { Bundle testBundle = Platform.getBundle(testPluginName); if (testBundle == null) { 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$ } - Bundle junit5RuntimeBundle = Platform.getBundle("org.eclipse.jdt.junit5.runtime"); //$NON-NLS-1$ - List platformEngineBundles = findTestEngineBundles(); + Bundle junit5RuntimeBundle = Platform.getBundle(junitRuntimeBundle); + List platformEngineBundles = findTestEngineBundles(versionRange); platformEngineBundles.add(testBundle); if (junit5RuntimeBundle != null) { platformEngineBundles.add(junit5RuntimeBundle); } - return new SPIBundleClassLoader(platformEngineBundles); + return new SPIBundleClassLoader(platformEngineBundles, loaderBundle); } - private static List findTestEngineBundles() { + private static List findTestEngineBundles(VersionRange versionRange) { BundleContext bundleContext = FrameworkUtil.getBundle(RemotePluginTestRunner.class).getBundleContext(); return Arrays.stream(bundleContext.getBundles()).filter(RemotePluginTestRunner::providesTestEngine).collect(Collectors.toCollection(ArrayList::new)); } @@ -186,12 +202,20 @@ public ClassLoader getClassLoader(final String bundleId) { @Override public void init(String[] args) { readPluginArgs(args); - if (isJUnit5(args)) { - // changing the classloader to get the testengines for junit5 - // during initialization - see bug 520811 + // changing the classloader to get the testengines for junit5/junit6 + // during initialization - see bug 520811 + boolean isJUnit5 = isJUnit5(args); + boolean isJUnit6 = !isJUnit5 && isJUnit6(args); + VersionRange versionRange = JUNIT6_VERSION_RANGE; + Bundle loaderBundle = Caller.loaderBundle6; + if (isJUnit5) { + versionRange = JUNIT5_VERSION_RANGE; + loaderBundle = Caller.loaderBundle5; + } + if (isJUnit5 || isJUnit6) { ClassLoader currentTCCL = Thread.currentThread().getContextClassLoader(); try { - Thread.currentThread().setContextClassLoader(new SPIBundleClassLoader(findTestEngineBundles())); + Thread.currentThread().setContextClassLoader(new SPIBundleClassLoader(findTestEngineBundles(versionRange), loaderBundle)); defaultInit(args); } finally { Thread.currentThread().setContextClassLoader(currentTCCL); @@ -206,6 +230,11 @@ private static boolean isJUnit5(String[] args) { return indexOf(args, "-runasjunit5"::equalsIgnoreCase) > -1 || indexOf(args, "org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader"::equals) > -1; } + @SuppressWarnings("nls") + private static boolean isJUnit6(String[] args) { + return indexOf(args, "-runasjunit6"::equalsIgnoreCase) > -1 || indexOf(args, "org.eclipse.jdt.internal.junit6.runner.JUnit6TestLoader"::equals) > -1; + } + public void readPluginArgs(String[] args) { fTestPluginName = getArgumentValue(args, "-testpluginname"); //$NON-NLS-1$ String loaderPlugin = getArgumentValue(args, "-loaderpluginname"); //$NON-NLS-1$ diff --git a/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/SPIBundleClassLoader.java b/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/SPIBundleClassLoader.java index f4c7506da1f..0a64de527a9 100644 --- a/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/SPIBundleClassLoader.java +++ b/ui/org.eclipse.pde.junit.runtime/src/org/eclipse/pde/internal/junit/runtime/SPIBundleClassLoader.java @@ -35,18 +35,20 @@ class SPIBundleClassLoader extends ClassLoader { private static final String META_INF_SERVICES = "META-INF/services/"; //$NON-NLS-1$ private final List bundles; + private final Bundle loaderBundle; private final Map> mappings = new ConcurrentHashMap<>(); - SPIBundleClassLoader(List bundles) { + SPIBundleClassLoader(List bundles, Bundle loaderBundle) { super(null); this.bundles = bundles; + this.loaderBundle = loaderBundle; } @Override protected Class findClass(String name) throws ClassNotFoundException { Iterator spi = mappings.values().stream().flatMap(Collection::stream).filter(mapping -> mapping.hasService(name)).iterator(); if (spi.hasNext()) { - Bundle caller = Caller.getBundle(); + Bundle caller = Caller.getBundle(loaderBundle); while (spi.hasNext()) { SPIMapping mapping = spi.next(); if (mapping.isCompatible(caller)) { @@ -98,7 +100,7 @@ protected Enumeration findResources(String name) throws IOException { } return list; }); - Bundle caller = Caller.getBundle(); + Bundle caller = Caller.getBundle(loaderBundle); for (SPIMapping mapping : spis) { if (mapping.isCompatible(caller)) { result.add(mapping.getUrl()); diff --git a/ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/JUnitLaunchRequirements.java b/ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/JUnitLaunchRequirements.java index 6b0fc819f1e..284fa6f91ce 100644 --- a/ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/JUnitLaunchRequirements.java +++ b/ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/JUnitLaunchRequirements.java @@ -55,6 +55,7 @@ public class JUnitLaunchRequirements { private static final String PDE_JUNIT_RUNTIME = "org.eclipse.pde.junit.runtime"; //$NON-NLS-1$ private static final String JUNIT4_JDT_RUNTIME_PLUGIN = "org.eclipse.jdt.junit4.runtime"; //$NON-NLS-1$ private static final String JUNIT5_JDT_RUNTIME_PLUGIN = "org.eclipse.jdt.junit5.runtime"; //$NON-NLS-1$ + private static final String JUNIT6_JDT_RUNTIME_PLUGIN = "org.eclipse.jdt.junit6.runtime"; //$NON-NLS-1$ public static void addRequiredJunitRuntimePlugins(ILaunchConfiguration configuration, Map> collectedModels, Map startLevelMap) throws CoreException { Collection runtimeBundles = getEclipseJunitRuntimePlugins(configuration, collectedModels, startLevelMap); @@ -158,6 +159,9 @@ public static Collection getRequiredJunitRuntimeEclipsePlugins(ILaunchCo case org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT5_TEST_KIND_ID -> { return List.of(PDE_JUNIT_RUNTIME, JUNIT5_JDT_RUNTIME_PLUGIN); } + case org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT6_TEST_KIND_ID -> { + return List.of(PDE_JUNIT_RUNTIME, JUNIT6_JDT_RUNTIME_PLUGIN); + } default -> throw new IllegalArgumentException("Unsupported junit test kind: " + testKind.getId()); //$NON-NLS-1$ } } diff --git a/ui/org.eclipse.pde.unittest.junit/src/org/eclipse/pde/unittest/junit/launcher/JUnitPluginLaunchConfigurationDelegate.java b/ui/org.eclipse.pde.unittest.junit/src/org/eclipse/pde/unittest/junit/launcher/JUnitPluginLaunchConfigurationDelegate.java index b7569339830..9879c759bc2 100644 --- a/ui/org.eclipse.pde.unittest.junit/src/org/eclipse/pde/unittest/junit/launcher/JUnitPluginLaunchConfigurationDelegate.java +++ b/ui/org.eclipse.pde.unittest.junit/src/org/eclipse/pde/unittest/junit/launcher/JUnitPluginLaunchConfigurationDelegate.java @@ -234,7 +234,7 @@ private VMRunnerConfiguration getVMRunnerConfiguration(ILaunchConfiguration conf String[] classpath = classpathAndModulepath[0]; String[] modulepath = classpathAndModulepath[1]; - if (junitVersion == JUnitVersion.JUNIT5) { + if (junitVersion == JUnitVersion.JUNIT5 || junitVersion == JUnitVersion.JUNIT6) { if (!configuration.getAttribute( JUnitLaunchConfigurationConstants.ATTR_DONT_ADD_MISSING_JUNIT5_DEPENDENCY, false)) { if (!Arrays.stream(classpath).anyMatch( @@ -574,7 +574,8 @@ private void internalCollectExecutionArguments(ILaunchConfiguration configuratio boolean isModularProject = JavaRuntime.isModularProject(getJavaProject(configuration)); String addOpensTargets; if (isModularProject) { - if (getJUnitVersion(configuration) == JUnitVersion.JUNIT5) { + JUnitVersion jUnitVersion = getJUnitVersion(configuration); + if (jUnitVersion == JUnitVersion.JUNIT5 || jUnitVersion == JUnitVersion.JUNIT6) { if (isOnModulePath(getJavaProject(configuration), "org.junit.jupiter.api.Test")) { //$NON-NLS-1$ addOpensTargets = "junit-platform-commons,ALL-UNNAMED"; //$NON-NLS-1$ } else {