Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*******************************************************************************
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* 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:
* See git history
*******************************************************************************/
package org.eclipse.pde.junit.runtime.tests;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertNotNull;

import java.net.URL;
import java.util.Collections;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.junit.model.ITestElement.Result;
import org.eclipse.jdt.junit.model.ITestRunSession;
import org.eclipse.pde.ui.tests.util.ProjectUtils;
import org.eclipse.pde.ui.tests.util.TargetPlatformUtil;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;

/**
* Test for issue #2082: Host bundles (even org.eclipse.osgi) leak into test
* launch config
* <p>
* This test verifies that when launching a JUnit plugin test without
* org.eclipse.pde.feature.group in the target platform, the system bundle
* (org.eclipse.osgi) from the host is not exposed to avoid conflicts with the
* target platform's system bundle.
*/
public class Issue2082LaunchTest {

@ClassRule
public static final TestRule CLEAR_WORKSPACE = ProjectUtils.DELETE_ALL_WORKSPACE_PROJECTS_BEFORE_AND_AFTER;

@BeforeClass
public static void setupProjects() throws Exception {
// Set up a target platform similar to issue #2082 scenario:
// - Include Eclipse platform bundles
// - Exclude org.eclipse.pde.feature.group to reproduce the issue scenario
// - Filter out PDE bundles (except core bundles needed for the test to run)
Pattern pdeIDs = Pattern.compile("org\\.eclipse\\.pde\\.(ui|build|launching|junit).*");
TargetPlatformUtil.setRunningPlatformSubSetAsTarget("Issue2082_target", b -> {
// Exclude PDE UI/build/launching bundles but keep PDE core and test infrastructure
return !pdeIDs.matcher(b.getSymbolicName()).find();
});

Bundle bundle = FrameworkUtil.getBundle(Issue2082LaunchTest.class);

IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
for (URL resource : Collections.list(bundle.findEntries("test-bundles", "verification.tests.issue2082", false))) {
ProjectUtils.importTestProject(FileLocator.toFileURL(resource));
}
workspaceRoot.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
}

@Test
public void testIssue2082_systemBundleNotDuplicated() throws Exception {
// Test for https://github.com/eclipse-pde/eclipse.pde/issues/2082
// Verify that launching a JUnit plugin test without org.eclipse.pde.feature.group
// in the target platform does not cause the host's org.eclipse.osgi to leak
// into the launch configuration, which would result in duplicate system bundles
// and launch errors.

IJavaProject project = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot().getProject("verification.tests.issue2082"));
IType testClass = project.findType("verification.tests", "Test");
assertNotNull("Test class should exist", testClass);
Assert.assertTrue("Test class should be valid", testClass.exists());

// Launch the test - this should succeed without errors
ITestRunSession session = TestExecutionUtil.runTest(testClass);

// The test is expected to fail (as per the test code), but the important
// part is that the launch itself succeeds without duplicate bundle errors
assertThat(session.getChildren()).hasSize(1);
Result testResult = session.getTestResult(true);
// We expect FAILURE because the test code calls fail(), but we do NOT
// expect ERROR which would indicate a launch problem
assertThat(testResult).isIn(Result.FAILURE, Result.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({ JUnitExecutionTest.class, JUnit5SuiteExecutionTest.class })
@SuiteClasses({ JUnitExecutionTest.class, JUnit5SuiteExecutionTest.class, Issue2082LaunchTest.class })
public class JUnitRuntimeTests {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>verification.tests.issue2082</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Issue 2082 Test
Bundle-SymbolicName: verification.tests.issue2082
Bundle-Version: 1.0.0.qualifier
Automatic-Module-Name: verification.tests.issue2082
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Require-Bundle: junit-jupiter-api;bundle-version="[5.4.0,6.0.0)"
Export-Package: verification.tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*******************************************************************************
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* 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:
* See git history
*******************************************************************************/
package verification.tests;

import static org.junit.jupiter.api.Assertions.*;

class Test {

@org.junit.jupiter.api.Test
void test() {
fail("Not yet implemented");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,36 @@ public void testWriteBundleEntry_startLevelAndAutoStart() throws Exception {
assertEquals("plugin.a*1.0.0@:false", BundleLauncherHelper.formatBundleEntry(plugin, null, "false"));
}

// --- test cases for system bundle exclusion (issue #2082) ---

@Test
public void testGetMergedBundleMap_systemBundleNotExposedFromHost() throws Exception {
// Test for https://github.com/eclipse-pde/eclipse.pde/issues/2082
// When launching a JUnit plugin test without org.eclipse.pde.feature.group
// in the target platform, the system bundle (org.eclipse.osgi) from the
// host should NOT be exposed to avoid conflicts with the target platform's
// system bundle. Before the fix, this would cause duplicate system bundles
// and result in launch errors.
var workspacePlugins = ofEntries( //
bundle("plugin.a", "1.0.0", //
entry(REQUIRE_BUNDLE, IPDEBuildConstants.BUNDLE_OSGI)));
var targetPlatformBundles = ofEntries( //
bundle(IPDEBuildConstants.BUNDLE_OSGI, "3.18.0"));

Consumer<ILaunchConfigurationWorkingCopy> launchConfigSetup = wc -> {
wc.setAttribute(IPDELauncherConstants.SELECTED_WORKSPACE_BUNDLES, Set.of("plugin.a*1.0.0"));
wc.setAttribute(IPDELauncherConstants.AUTOMATIC_INCLUDE_REQUIREMENTS, true);
};

// Expected: Only the system bundle from the target platform should be included.
// The system bundle from the host must NOT be included to avoid conflicts.
Set<BundleLocationDescriptor> expectedBundles = Set.of( //
workspaceBundle("plugin.a", "1.0.0"), //
targetBundle(IPDEBuildConstants.BUNDLE_OSGI, "3.18.0"));

assertGetMergedBundleMap(workspacePlugins, targetPlatformBundles, launchConfigSetup, expectedBundles);
}

// --- utilities ---

private void assertGetMergedBundleMap(Map<NameVersionDescriptor, Map<String, String>> workspacePlugins,
Expand Down