diff --git a/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/ui/tests/classpathupdater/ClasspathUpdaterTest.java b/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/ui/tests/classpathupdater/ClasspathUpdaterTest.java new file mode 100644 index 00000000000..e56182575d0 --- /dev/null +++ b/ui/org.eclipse.pde.ui.tests/src/org/eclipse/pde/ui/tests/classpathupdater/ClasspathUpdaterTest.java @@ -0,0 +1,152 @@ +package org.eclipse.pde.ui.tests.classpathupdater; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.*; +import org.eclipse.pde.core.plugin.IPluginModelBase; +import org.eclipse.pde.core.plugin.PluginRegistry; +import org.eclipse.pde.internal.core.ClasspathComputer; +import org.eclipse.pde.internal.ui.wizards.tools.UpdateClasspathJob; +import org.eclipse.pde.ui.tests.util.ProjectUtils; +import org.junit.*; + +public class ClasspathUpdaterTest { + + private static IProject project; + private static IJavaProject jProject; + + private static IClasspathEntry[] originalClasspath; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + project = ProjectUtils.importTestProject("tests/projects/classpathupdater"); + jProject = JavaCore.create(project); + originalClasspath = jProject.getRawClasspath(); + } + + @After + public void restoreOriginalClasspath() throws Exception { + jProject.setRawClasspath(originalClasspath, null); + } + + @Test + public void testUpdateClasspath_PreserveAttributes() throws Exception { + assertTrue("Project was not created", project.exists()); + + runUpdateClasspathJob(); + assertClasspathAttribute("JavaSE-17", IClasspathAttribute.MODULE, true, Boolean::valueOf); + assertClasspathAttribute("library.jar", IClasspathAttribute.TEST, true, Boolean::valueOf); + assertClasspathProperty("library.jar", "exported=true", (e) -> e.isExported()); + assertClasspathProperty("library.jar", "no source", (e) -> e.getSourceAttachmentPath() == null); + assertClasspathAttribute("A.jar", IClasspathAttribute.TEST, null, Boolean::valueOf); + assertClasspathProperty("A.jar", "exported=false", (e) -> !e.isExported()); + assertClasspathProperty("A.jar", "default source", + (e) -> "Asrc.zip".equals(nullOr(e.getSourceAttachmentPath(), IPath::lastSegment))); + assertClasspathProperty("src", "exported=false", (e) -> !e.isExported()); + assertClasspathAttribute("src", IClasspathAttribute.IGNORE_OPTIONAL_PROBLEMS, true, Boolean::valueOf); + assertClasspathOrder("A.jar", "src", "org.eclipse.pde.core.requiredPlugins", "JavaSE-17", "SOMEVAR", + "library.jar"); + } + + @Test + public void testUpdateClasspath_CreateFromScratch() throws Exception { + assertTrue("Project was not created", project.exists()); + jProject.setRawClasspath(new IClasspathEntry[0], null); + + runUpdateClasspathJob(); + assertClasspathAttribute("JavaSE-17", IClasspathAttribute.MODULE, null, Boolean::valueOf); + assertClasspathAttribute("library.jar", IClasspathAttribute.TEST, null, Boolean::valueOf); + assertClasspathProperty("library.jar", "exported=true", (e) -> e.isExported()); + assertClasspathProperty("library.jar", "no source", (e) -> e.getSourceAttachmentPath() == null); + assertClasspathAttribute("A.jar", IClasspathAttribute.TEST, null, Boolean::valueOf); + assertClasspathProperty("A.jar", "exported=true", (e) -> e.isExported()); + assertClasspathProperty("A.jar", "default source", + (e) -> "Asrc.zip".equals(nullOr(e.getSourceAttachmentPath(), IPath::lastSegment))); + assertClasspathOrder("JavaSE-17", "org.eclipse.pde.core.requiredPlugins", "library.jar", "A.jar"); + } + + @Test + public void testClasspathComputer_ChangeSourceAttachment() throws Exception { + assertTrue("Project was not created", project.exists()); + + Map sourceMap = new HashMap<>(); + sourceMap.put("A.jar", new Path("library.jar")); + sourceMap.put("library.jar", new Path("A.jar")); + IPluginModelBase model = PluginRegistry.findModel(project.getProject()); + + IClasspathEntry[] cp = ClasspathComputer.getClasspath(project, model, sourceMap, false, false); + jProject.setRawClasspath(cp, null); + + assertClasspathAttribute("JavaSE-17", IClasspathAttribute.MODULE, true, Boolean::valueOf); + assertClasspathAttribute("library.jar", IClasspathAttribute.TEST, true, Boolean::valueOf); + assertClasspathProperty("library.jar", "exported=true", (e) -> e.isExported()); + assertClasspathProperty("library.jar", "overridden source", + (e) -> "A.jar".equals(nullOr(e.getSourceAttachmentPath(), IPath::lastSegment))); + assertClasspathAttribute("A.jar", IClasspathAttribute.TEST, null, Boolean::valueOf); + assertClasspathProperty("A.jar", "exported=false", (e) -> !e.isExported()); + assertClasspathProperty("A.jar", "overridden source", + (e) -> "library.jar".equals(nullOr(e.getSourceAttachmentPath(), IPath::lastSegment))); + assertClasspathProperty("src", "exported=false", (e) -> !e.isExported()); + assertClasspathAttribute("src", IClasspathAttribute.IGNORE_OPTIONAL_PROBLEMS, true, Boolean::valueOf); + assertClasspathOrder("A.jar", "src", "org.eclipse.pde.core.requiredPlugins", "JavaSE-17", "SOMEVAR", + "library.jar"); + } + + private void runUpdateClasspathJob() throws InterruptedException { + IPluginModelBase model = PluginRegistry.findModel(project.getProject()); + UpdateClasspathJob job = new UpdateClasspathJob(new IPluginModelBase[] { model }); + job.schedule(); + job.join(); + assertTrue("Update Classpath Job failed", job.getResult().isOK()); + } + + private void assertClasspathAttribute(String entryName, String attrName, T expectedValue, + Function parser) throws JavaModelException { + IClasspathEntry entry = findClasspathEntry(entryName); + assertNotNull("Classpath entry for " + entryName + " is missing", entry); + String attrValue = findClasspathAttributeValue(entry, attrName); + T current = attrValue != null ? parser.apply(attrValue) : null; // null: attribute not set + assertEquals("Classpath entry for '" + entry.getPath().lastSegment() + "': attribute '" + attrName + + "' is not '" + expectedValue + "'", expectedValue, current); + } + + private String findClasspathAttributeValue(IClasspathEntry entry, String name) { + return Arrays.stream(entry.getExtraAttributes()) // + .filter(a -> name.equals(a.getName())).map(IClasspathAttribute::getValue) // + .findFirst().orElse(null); + } + + private void assertClasspathProperty(String entryName, String expectedValue, Predicate checker) + throws JavaModelException { + String title = "Classpath entry for '" + entryName + "'"; + IClasspathEntry entry = findClasspathEntry(entryName); + assertTrue(title + " is missing", entry != null); + assertTrue(title + " has not set '" + expectedValue + "'", checker.test(entry)); + } + + private void assertClasspathOrder(String... names) throws Exception { + IClasspathEntry[] rawClasspath = jProject.getRawClasspath(); + assertEquals("Classpath has wrong number of entries", names.length, rawClasspath.length); + for (int i = 0; i < names.length; i++) { + assertEquals("Classpath has wrong order", names[i], rawClasspath[i].getPath().lastSegment()); + } + } + + private IClasspathEntry findClasspathEntry(String entryName) throws JavaModelException { + return Arrays.stream(jProject.getRawClasspath()) // + .filter(e -> entryName.equals(e.getPath().lastSegment())) // + .findFirst().orElse(null); + } + + private static R nullOr(T obj, Function f) { + return obj == null ? null : f.apply(obj); + } +} diff --git a/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/.classpath b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/.classpath new file mode 100644 index 00000000000..5bccae7fc10 --- /dev/null +++ b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/.classpath @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/.project b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/.project new file mode 100644 index 00000000000..1012ffa778b --- /dev/null +++ b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/.project @@ -0,0 +1,29 @@ + + + classpathupdater + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.pde.ui.tests.testNature + + diff --git a/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/.settings/org.eclipse.jdt.core.prefs b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..62ef3488cc0 --- /dev/null +++ b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/A.jar b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/A.jar new file mode 100644 index 00000000000..74d8b4490d2 Binary files /dev/null and b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/A.jar differ diff --git a/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/Asrc.zip b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/Asrc.zip new file mode 100644 index 00000000000..74d8b4490d2 Binary files /dev/null and b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/Asrc.zip differ diff --git a/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..4c43d2fba8e --- /dev/null +++ b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/META-INF/MANIFEST.MF @@ -0,0 +1,9 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Classpathupdater +Bundle-SymbolicName: classpathupdater +Bundle-Version: 1.0.0.qualifier +Bundle-ClassPath: library.jar, + A.jar, + . +Require-Bundle: org.eclipse.pde.core diff --git a/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/build.properties b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/build.properties new file mode 100644 index 00000000000..e7b9dc306f7 --- /dev/null +++ b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/build.properties @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (c) 2012 IBM Corporation and others. +# +# 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: +# IBM Corporation - initial API and implementation +############################################################################### +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + library.jar, \ + A.jar diff --git a/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/library.jar b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/library.jar new file mode 100644 index 00000000000..74d8b4490d2 Binary files /dev/null and b/ui/org.eclipse.pde.ui.tests/tests/projects/classpathupdater/library.jar differ