| /******************************************************************************* |
| * Copyright (c) 2008, 2017 Code 9 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: |
| * Code 9 - initial API and implementation |
| * IBM - ongoing development |
| * SAP AG - ongoing development |
| ******************************************************************************/ |
| package org.eclipse.equinox.p2.tests.publisher.actions; |
| |
| import static org.eclipse.equinox.p2.tests.publisher.actions.StatusMatchers.errorStatus; |
| import static org.eclipse.equinox.p2.tests.publisher.actions.StatusMatchers.okStatus; |
| import static org.eclipse.equinox.p2.tests.publisher.actions.StatusMatchers.statusWithMessageWhich; |
| import static org.hamcrest.CoreMatchers.containsString; |
| import static org.hamcrest.CoreMatchers.hasItem; |
| import static org.hamcrest.CoreMatchers.is; |
| import static org.hamcrest.CoreMatchers.not; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.URI; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability; |
| import org.eclipse.equinox.internal.p2.metadata.InstallableUnit; |
| import org.eclipse.equinox.internal.p2.metadata.RequiredCapability; |
| import org.eclipse.equinox.internal.p2.publisher.eclipse.ProductFile; |
| import org.eclipse.equinox.p2.metadata.IInstallableUnit; |
| import org.eclipse.equinox.p2.metadata.IInstallableUnitFragment; |
| import org.eclipse.equinox.p2.metadata.IRequirement; |
| import org.eclipse.equinox.p2.metadata.ITouchpointData; |
| import org.eclipse.equinox.p2.metadata.IUpdateDescriptor; |
| import org.eclipse.equinox.p2.metadata.Version; |
| import org.eclipse.equinox.p2.publisher.AbstractPublisherAction; |
| import org.eclipse.equinox.p2.publisher.IPublisherInfo; |
| import org.eclipse.equinox.p2.publisher.IPublisherResult; |
| import org.eclipse.equinox.p2.publisher.PublisherInfo; |
| import org.eclipse.equinox.p2.publisher.actions.JREAction; |
| import org.eclipse.equinox.p2.publisher.actions.QueryableFilterAdvice; |
| import org.eclipse.equinox.p2.publisher.eclipse.IConfigAdvice; |
| import org.eclipse.equinox.p2.publisher.eclipse.ProductAction; |
| import org.eclipse.equinox.p2.query.IQueryResult; |
| import org.eclipse.equinox.p2.query.QueryUtil; |
| import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; |
| import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; |
| import org.eclipse.equinox.p2.tests.TestData; |
| import org.eclipse.equinox.p2.tests.publisher.TestArtifactRepository; |
| |
| public class ProductActionTest extends ActionTest { |
| |
| private static final String WIN_FILTER = "(& (osgi.ws=win32)(osgi.os=win32)(osgi.arch=x86))"; |
| private static final String LINUX_FILTER = "(& (osgi.ws=gtk)(osgi.os=linux)(osgi.arch=x86))"; |
| |
| private static final String WIN_CONFIG_SPEC = AbstractPublisherAction.createConfigSpec("win32", "win32", "x86"); |
| private static final String LINUX_CONFIG_SPEC = AbstractPublisherAction.createConfigSpec("gtk", "linux", "x86"); |
| |
| File executablesFeatureLocation = null; |
| String productLocation = ""; |
| String source = ""; |
| protected TestArtifactRepository artifactRepository = new TestArtifactRepository(getAgent()); |
| |
| @Override |
| public void setUp() throws Exception { |
| setupPublisherInfo(); |
| setupPublisherResult(); |
| } |
| |
| @Override |
| public void setupPublisherInfo() { |
| PublisherInfo publisherInfoImpl = new PublisherInfo(); |
| publisherInfoImpl.setArtifactRepository(artifactRepository); |
| publisherInfoImpl.setArtifactOptions(IPublisherInfo.A_PUBLISH); |
| publisherInfoImpl.setConfigurations(new String[] { configSpec }); |
| |
| publisherInfo = publisherInfoImpl; |
| } |
| |
| /** |
| * Tests publishing a product containing a branded application with a custom |
| * splash screen, icon, etc. |
| */ |
| public void testBrandedApplication() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "brandedProduct/branded.product").toString()); |
| addContextIU("org.eclipse.platform.feature.group", "1.2.3"); |
| |
| performProductAction(productFile); |
| Collection<IInstallableUnit> ius = publisherResult.getIUs("branded.product", IPublisherResult.NON_ROOT); |
| assertEquals("1.0", 1, ius.size()); |
| |
| // TODO assert branding was done correctly |
| } |
| |
| public void testLicense() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "productWithLicense.product").toString()); |
| performProductAction(productFile); |
| Collection<IInstallableUnit> ius = publisherResult.getIUs("licenseIU.product", IPublisherResult.NON_ROOT); |
| assertEquals("1.0", 1, ius.size()); |
| IInstallableUnit iu = ius.iterator().next(); |
| assertEquals("1.1", "http://www.example.com", iu.getLicenses().iterator().next().getLocation().toString()); |
| assertEquals("1.2", "This is the liCenSE.", iu.getLicenses().iterator().next().getBody().trim()); |
| } |
| |
| public void testLicenseNoURL() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "licenseNoURL.product").toString()); |
| performProductAction(productFile); |
| Collection<IInstallableUnit> ius = publisherResult.getIUs("licenseIU.product", IPublisherResult.NON_ROOT); |
| assertEquals("1.0", 1, ius.size()); |
| IInstallableUnit iu = ius.iterator().next(); |
| assertEquals("1.1", "", iu.getLicenses().iterator().next().getLocation().toString()); |
| assertEquals("1.2", "This is the liCenSE.", iu.getLicenses().iterator().next().getBody().trim()); |
| } |
| |
| public void testLicenseNoText() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "licenseNoText.product").toString()); |
| performProductAction(productFile); |
| Collection<IInstallableUnit> ius = publisherResult.getIUs("licenseIU.product", IPublisherResult.NON_ROOT); |
| assertEquals("1.0", 1, ius.size()); |
| IInstallableUnit iu = ius.iterator().next(); |
| assertEquals("1.1", "http://www.example.com", iu.getLicenses().iterator().next().getLocation().toString()); |
| assertEquals("1.2", "", iu.getLicenses().iterator().next().getBody().trim()); |
| } |
| |
| public void testMissingLicense() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "productWithNoLicense.product").toString()); |
| performProductAction(productFile); |
| Collection<IInstallableUnit> ius = publisherResult.getIUs("licenseIU.product", IPublisherResult.NON_ROOT); |
| assertEquals("1.0", 1, ius.size()); |
| IInstallableUnit iu = ius.iterator().next(); |
| assertEquals(0, iu.getLicenses().size()); |
| } |
| |
| public void testMultiProductPublishing() throws Exception { |
| ProductFile productFile1 = new ProductFile( |
| TestData.getFile("ProductActionTest", "boundedVersionConfigurations.product").toString()); |
| ProductFile productFile2 = new ProductFile( |
| TestData.getFile("ProductActionTest", "unboundedVersionConfigurations.product").toString()); |
| |
| addContextIU("org.eclipse.core.runtime", "4.0.0"); |
| performProductAction(productFile1); |
| |
| setupPublisherResult(); |
| addContextIU("org.eclipse.core.runtime", "4.0.0"); |
| performProductAction(productFile2); |
| assertThat(publisherResult, containsUniqueIU(flavorArg + configSpec + "org.eclipse.core.runtime")); |
| } |
| |
| public void testMultiPlatformCUs_DifferentPlatforms() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "unboundedVersionConfigurations.product").toString()); |
| setConfiguration(LINUX_CONFIG_SPEC); |
| addContextIU("org.eclipse.core.runtime", "0.0.0", WIN_FILTER); |
| |
| performProductAction(productFile); |
| |
| assertThat(publisherResult, not(containsIU(flavorArg + LINUX_CONFIG_SPEC + "org.eclipse.core.runtime"))); |
| assertThat(publisherResult, not(containsIU(flavorArg + WIN_CONFIG_SPEC + "org.eclipse.core.runtime"))); |
| } |
| |
| public void testMultiPlatformCUs_SamePlatforms() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "unboundedVersionConfigurations.product").toString()); |
| setConfiguration(LINUX_CONFIG_SPEC); |
| addContextIU("org.eclipse.core.runtime", "0.0.0", LINUX_FILTER); |
| |
| performProductAction(productFile); |
| |
| assertThat(publisherResult, containsUniqueIU(flavorArg + LINUX_CONFIG_SPEC + "org.eclipse.core.runtime")); |
| assertThat(publisherResult, not(containsIU(flavorArg + WIN_CONFIG_SPEC + "org.eclipse.core.runtime"))); |
| } |
| |
| public void testMultiPlatformCUs_SamePlatforms_NoVersion() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "unboundedVersionConfigurations.product").toString()); |
| setConfiguration(LINUX_CONFIG_SPEC); |
| addContextIU("org.eclipse.core.runtime", null, LINUX_FILTER); |
| |
| performProductAction(productFile); |
| |
| assertThat(publisherResult, containsUniqueIU(flavorArg + LINUX_CONFIG_SPEC + "org.eclipse.core.runtime")); |
| assertThat(publisherResult, not(containsIU(flavorArg + WIN_CONFIG_SPEC + "org.eclipse.core.runtime"))); |
| } |
| |
| public void testMultiPlatformCUs_SamePlatforms_BoundedVersions() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "unboundedVersionConfigurations.product").toString()); |
| setConfiguration(LINUX_CONFIG_SPEC); |
| |
| // Set a specific version number, the one in the .product file uses 0.0.0. Let's |
| // see if it binds properly |
| // filter is different from linuxConfigSpec, but will still match |
| addContextIU("org.eclipse.core.runtime", "4.0.0", "(osgi.os=linux)"); |
| |
| performProductAction(productFile); |
| |
| assertThat(publisherResult, containsUniqueIU(flavorArg + LINUX_CONFIG_SPEC + "org.eclipse.core.runtime")); |
| assertThat(publisherResult, not(containsIU(flavorArg + WIN_CONFIG_SPEC + "org.eclipse.core.runtime"))); |
| } |
| |
| public void testCUsHost() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "unboundedVersionConfigurations.product").toString()); |
| setConfiguration(LINUX_CONFIG_SPEC); |
| |
| // Set a specific version number, the one in the .product file uses 0.0.0. Let's |
| // see if it binds properly |
| // filter is different from linuxConfigSpec, but will still match |
| addContextIU("org.eclipse.core.runtime", "4.0.0", "(osgi.os=linux)"); |
| |
| performProductAction(productFile); |
| |
| IInstallableUnitFragment fragment = (IInstallableUnitFragment) getUniquePublishedIU( |
| flavorArg + LINUX_CONFIG_SPEC + "org.eclipse.core.runtime"); |
| assertEquals("1.1", "org.eclipse.core.runtime", |
| RequiredCapability.extractName(fragment.getHost().iterator().next().getMatches())); |
| assertEquals("1.2", Version.create("4.0.0"), |
| RequiredCapability.extractRange(fragment.getHost().iterator().next().getMatches()).getMinimum()); |
| assertEquals("1.3", Version.create("1.0.0"), fragment.getVersion()); |
| |
| } |
| |
| public void testMultiConfigspecProductPublishing() throws IOException, Exception { |
| ProductFile productFile = new ProductFile(TestData.getFile("ProductActionTest", "platform.product").toString()); |
| ((PublisherInfo) publisherInfo).setConfigurations(new String[] { "carbon.macos.x86", "cocoa.macos.x86" }); |
| addContextIU("org.eclipse.platform.feature.group", "1.2.3"); |
| |
| performProductAction(productFile); |
| |
| Collection<IConfigAdvice> advice = publisherInfo.getAdvice("carbon.macos.x86", false, null, null, |
| IConfigAdvice.class); |
| assertEquals("1.0", 1, advice.size()); |
| } |
| |
| public void testANYConfigSpecPublishing_GeneralBundle() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "unboundedVersionConfigurations.product").toString()); |
| String configSpecANY = AbstractPublisherAction.createConfigSpec("ANY", "ANY", "ANY"); // configuration spec to |
| // create CUs without |
| // filters |
| setConfiguration(configSpecANY); |
| |
| addContextIU("org.eclipse.core.runtime", "4.0.0"); |
| |
| performProductAction(productFile); |
| |
| // there is a CU for the IU because it applies to all platforms |
| IInstallableUnitFragment fragment = (IInstallableUnitFragment) getUniquePublishedIU( |
| flavorArg + configSpecANY + "org.eclipse.core.runtime"); |
| assertEquals("1.1", "org.eclipse.core.runtime", |
| RequiredCapability.extractName(fragment.getHost().iterator().next().getMatches())); |
| assertEquals("1.2", Version.create("4.0.0"), |
| RequiredCapability.extractRange(fragment.getHost().iterator().next().getMatches()).getMinimum()); |
| assertEquals("1.3", Version.create("1.0.0"), fragment.getVersion()); |
| assertNull("1.3", fragment.getFilter()); |
| } |
| |
| public void testANYConfigSpecPublishing_PlatformSpecificBundle() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "unboundedVersionConfigurations.product").toString()); |
| String configSpecANY = AbstractPublisherAction.createConfigSpec("ANY", "ANY", "ANY"); // configuration spec to |
| // create CUs without |
| // filters |
| setConfiguration(configSpecANY); |
| |
| addContextIU("org.eclipse.core.runtime", "4.0.0", WIN_FILTER); // any valid filter can be set here |
| |
| performProductAction(productFile); |
| |
| // there is no CU for the IU because it is platform specific |
| assertThat(publisherResult, not(containsIU(flavorArg + configSpecANY + "org.eclipse.core.runtime"))); |
| } |
| |
| public void testProductFileWithRepoAdvice() throws Exception { |
| URI location; |
| try { |
| location = TestData.getFile("ProductActionTest", "contextRepos").toURI(); |
| } catch (Exception e) { |
| fail("0.99", e); |
| return; |
| } |
| ProductFile productFile = new ProductFile(TestData.getFile("ProductActionTest", "platform.product").toString()); |
| IMetadataRepositoryManager metadataRepositoryManager = getMetadataRepositoryManager(); |
| IMetadataRepository repository = metadataRepositoryManager.loadRepository(location, new NullProgressMonitor()); |
| testAction = new ProductAction(source, productFile, flavorArg, executablesFeatureLocation); |
| PublisherInfo info = new PublisherInfo(); |
| info.setContextMetadataRepository(repository); |
| // TODO this line doesn't have any effect -> is this a bug in the |
| // implementation? |
| info.addAdvice(new QueryableFilterAdvice(info.getContextMetadataRepository())); |
| |
| IStatus status = testAction.perform(info, publisherResult, null); |
| assertThat(status, is(okStatus())); |
| |
| IQueryResult<IInstallableUnit> results = publisherResult |
| .query(QueryUtil.createIUQuery("org.eclipse.platform.ide", Version.create("3.5.0.I20081118")), null); |
| assertEquals("1.0", 1, queryResultSize(results)); |
| IInstallableUnit unit = results.iterator().next(); |
| Collection<IRequirement> requiredCapabilities = unit.getRequirements(); |
| |
| IRequiredCapability capability = null; |
| for (IRequirement iRequirement : requiredCapabilities) { |
| IRequiredCapability req = (IRequiredCapability) iRequirement; |
| if (req.getName().equals("org.eclipse.platform.feature.group")) { |
| capability = req; |
| break; |
| } |
| } |
| assertTrue("1.1", capability != null); |
| assertEquals("1.2", InstallableUnit.parseFilter("(org.eclipse.update.install.features=true)"), |
| capability.getFilter()); |
| } |
| |
| public void testProductWithAdviceFile() throws Exception { |
| // product file that has a corresponding advice file (p2.inf). |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest/productWithAdvice", "productWithAdvice.product").toString()); |
| testAction = new ProductAction(source, productFile, flavorArg, executablesFeatureLocation); |
| IStatus status = testAction.perform(new PublisherInfo(), publisherResult, null); |
| assertThat(status, is(okStatus())); |
| |
| IInstallableUnit product = getUniquePublishedIU("productWithAdvice.product"); |
| Collection<ITouchpointData> data = product.getTouchpointData(); |
| assertEquals("1.1", 1, data.size()); |
| String configure = data.iterator().next().getInstruction("configure").getBody(); |
| assertEquals("1.2", |
| "addRepository(type:0,location:http${#58}//download.eclipse.org/releases/fred);addRepository(type:1,location:http${#58}//download.eclipse.org/releases/fred);", |
| configure); |
| |
| // update.id = com.zoobar |
| // update.range = [4.0,4.3) |
| // update.severity = 0 |
| // update.description = This is the description |
| IUpdateDescriptor update = product.getUpdateDescriptor(); |
| assertEquals("2.0", 0, update.getSeverity()); |
| assertEquals("2.1", "This is the description", update.getDescription()); |
| // unit that fits in range |
| assertTrue("2.2", update.isUpdateOf(createIU("com.zoobar", Version.createOSGi(4, 1, 0)))); |
| // unit that is too old for range |
| assertFalse("2.3", update.isUpdateOf(createIU("com.zoobar", Version.createOSGi(3, 1, 0)))); |
| // version that is too new and outside of range |
| assertFalse("2.4", update.isUpdateOf(createIU("com.zoobar", Version.createOSGi(6, 1, 0)))); |
| // unit with matching version but not matching id |
| assertFalse("2.6", update.isUpdateOf(createIU("com.other", Version.createOSGi(4, 1, 0)))); |
| } |
| |
| public void testFiltersOfInclusions() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "productIncludingFragments.product").toString()); |
| addContextIU("generalbundle", "1.0.1"); |
| addContextIU("fragment.win", "1.0.2", WIN_FILTER); |
| // no fragment.linux in the context |
| |
| IStatus status = performProductActionAndReturnStatus(productFile); |
| |
| IInstallableUnit productIU = getUniquePublishedIU("productIncludingFragments.uid"); |
| assertThat(productIU.getRequirements(), |
| hasItem(createIURequirement("generalbundle", createStrictVersionRange("1.0.1")))); |
| assertThat(productIU.getRequirements(), |
| hasItem(createIURequirement("fragment.win", createStrictVersionRange("1.0.2"), WIN_FILTER))); |
| |
| // this is bug 390361: the Linux fragment is required without filter, so the |
| // product cannot be installed for Windows ... |
| assertThat(productIU.getRequirements(), hasItem(createIURequirement("fragment.linux", ANY_VERSION))); |
| |
| // ... therefore the action shall report an error |
| assertThat(status, is(errorStatus())); |
| assertThat(Arrays.asList(status.getChildren()), |
| hasItem(statusWithMessageWhich(containsString("Included element fragment.linux 0.0.0 is missing")))); |
| } |
| |
| public void testMessageForProductWithIgnoredContent() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "mixedContentIgnored.product").toString()); |
| IStatus status = performProductActionAndReturnStatus(productFile); |
| |
| // expect a warning about redundant, ignored content in product file -> |
| // requested in bug 325611 |
| assertThat(Arrays.asList(status.getChildren()), hasItem(statusWithMessageWhich(containsString("are ignored")))); |
| // TODO the message should have a code identifying it |
| } |
| |
| public void testJREIncluded() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "brandedProduct/branded.product").toString()); |
| addContextIU("org.eclipse.platform.feature.group", "1.2.3"); |
| |
| performProductAction(productFile); |
| Collection<IInstallableUnit> ius = publisherResult.getIUs("branded.product", IPublisherResult.NON_ROOT); |
| assertEquals(1, ius.size()); |
| assertEquals("Missing a.jre.javase", 1, publisherResult.getIUs("a.jre.javase", IPublisherResult.ROOT).size()); |
| assertEquals("Missing config.a.jre.javase", 1, |
| publisherResult.getIUs("config.a.jre.javase", IPublisherResult.ROOT).size()); |
| } |
| |
| public void testRequiredEEAsSpecified() throws Exception { |
| ProductFile productFile = new ProductFile( |
| TestData.getFile("ProductActionTest", "productFileActionTest.product").toString()); |
| addContextIU("org.eclipse.core.commands", "5.0.0"); |
| |
| performProductAction(productFile); |
| Collection<IInstallableUnit> ius = publisherResult.getIUs("SampleProduct", IPublisherResult.NON_ROOT); |
| assertEquals(1, ius.size()); |
| IInstallableUnit productIU = ius.iterator().next(); |
| IInstallableUnit aJre = publisherResult.getIUs("a.jre.javase", IPublisherResult.ROOT).iterator().next(); |
| boolean found = false; |
| for (IRequirement req : productIU.getRequirements()) { |
| if (req instanceof RequiredCapability) { |
| RequiredCapability required = (RequiredCapability) req; |
| if (JREAction.NAMESPACE_OSGI_EE.equals(required.getNamespace())) { |
| found = true; |
| assertEquals("OSGi/Minimum", required.getName()); |
| assertEquals("1.0.0", required.getRange().getMinimum().toString()); |
| assertEquals("1.0.0", required.getRange().getMaximum().toString()); |
| assertTrue(req.isMatch(aJre)); |
| } else if (required.getName().contains("a.jre")) { |
| fail("instead of unit requirement, should use a osgi.ee requirement"); |
| } |
| } |
| } |
| assertTrue(found); |
| } |
| |
| private void performProductAction(ProductFile productFile) { |
| IStatus status = performProductActionAndReturnStatus(productFile); |
| assertThat(status, is(okStatus())); |
| } |
| |
| private IStatus performProductActionAndReturnStatus(ProductFile productFile) { |
| testAction = new ProductAction(source, productFile, flavorArg, executablesFeatureLocation); |
| return testAction.perform(publisherInfo, publisherResult, null); |
| } |
| |
| private void setConfiguration(String configSpec) { |
| ((PublisherInfo) publisherInfo).setConfigurations(new String[] { configSpec }); |
| } |
| |
| } |