diff options
12 files changed, 687 insertions, 22 deletions
diff --git a/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF index bcc8038ca..1f6e8a56c 100644 --- a/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF @@ -37,4 +37,5 @@ Bundle-RequiredExecutionEnvironment: CDC-1.1/Foundation-1.1, Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.5.0,4.0.0)", org.sat4j.core;bundle-version="2.1.0", org.sat4j.pb;bundle-version="2.1.0", - org.eclipse.core.jobs;bundle-version="3.4.100" + org.eclipse.core.jobs;bundle-version="3.4.100", + org.eclipse.equinox.p2.metadata diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java index 254c2d2d0..20575be58 100644 --- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java +++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java @@ -11,19 +11,15 @@ ******************************************************************************/ package org.eclipse.equinox.internal.p2.director; -import org.eclipse.equinox.internal.provisional.p2.metadata.query.Collector; - -import org.eclipse.equinox.internal.provisional.p2.metadata.query.IQueryable; - import java.math.BigInteger; import java.util.*; import java.util.Map.Entry; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.equinox.internal.p2.core.helpers.Tracing; +import org.eclipse.equinox.internal.p2.metadata.NotRequirement; import org.eclipse.equinox.internal.provisional.p2.metadata.*; -import org.eclipse.equinox.internal.provisional.p2.metadata.query.CapabilityQuery; -import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.*; import org.eclipse.osgi.util.NLS; import org.osgi.framework.InvalidSyntaxException; import org.sat4j.pb.IPBSolver; @@ -318,7 +314,33 @@ public class Projector { } } + private void expandNegatedRequirement(IRequiredCapability req, IInstallableUnit iu, List optionalAbstractRequirements, boolean isRootIu) throws ContradictionException { + IRequiredCapability negatedReq = ((NotRequirement) req).getRequirement(); + if (!isApplicable(negatedReq)) + return; + List matches = getApplicableMatches(negatedReq); + if (matches.isEmpty()) { + return; + } + Explanation explanation; + if (isRootIu) { + IInstallableUnit reqIu = (IInstallableUnit) matches.iterator().next(); + if (alreadyInstalledIUs.contains(reqIu)) { + explanation = new Explanation.IUInstalled(reqIu); + } else { + explanation = new Explanation.IUToInstall(reqIu); + } + } else { + explanation = new Explanation.HardRequirement(iu, req); + } + createNegationImplication(iu, matches, explanation); + } + private void expandRequirement(IRequiredCapability req, IInstallableUnit iu, List optionalAbstractRequirements, boolean isRootIu) throws ContradictionException { + if (req.isNegation()) { + expandNegatedRequirement(req, iu, optionalAbstractRequirements, isRootIu); + return; + } if (!isApplicable(req)) return; List matches = getApplicableMatches(req); @@ -630,6 +652,17 @@ public class Projector { createImplication(iu, optionalRequirements, Explanation.OPTIONAL_REQUIREMENT); } + //This will create as many implication as there is element in the right argument + private void createNegationImplication(Object left, List right, Explanation name) throws ContradictionException { + if (DEBUG) { + Tracing.debug(name + ": " + left + "->" + right); //$NON-NLS-1$ //$NON-NLS-2$ + } + for (Iterator iterator = right.iterator(); iterator.hasNext();) { + dependencyHelper.implication(new Object[] {left}).impliesNot(iterator.next()).named(name); + } + + } + private void createImplication(Object left, List right, Explanation name) throws ContradictionException { if (DEBUG) { Tracing.debug(name + ": " + left + "->" + right); //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/QueryableArray.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/QueryableArray.java index 0b5b36420..80f500296 100644 --- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/QueryableArray.java +++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/QueryableArray.java @@ -12,6 +12,7 @@ package org.eclipse.equinox.internal.p2.director; import java.util.*; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.equinox.internal.p2.metadata.ORRequirement; import org.eclipse.equinox.internal.provisional.p2.metadata.*; import org.eclipse.equinox.internal.provisional.p2.metadata.query.*; @@ -45,6 +46,10 @@ public class QueryableArray implements IQueryable { IRequiredCapability[] requiredCapabilities = query.getRequiredCapabilities(); Collection resultIUs = null; for (int i = 0; i < requiredCapabilities.length; i++) { + if (requiredCapabilities[i] instanceof ORRequirement) { + query.perform(dataSet.iterator(), collector); + continue; + } Collection matchingIUs = findMatchingIUs(requiredCapabilities[i]); if (matchingIUs == null) return collector; @@ -54,8 +59,9 @@ public class QueryableArray implements IQueryable { resultIUs.retainAll(matchingIUs); } - for (Iterator iterator = resultIUs.iterator(); iterator.hasNext();) - collector.accept(iterator.next()); + if (resultIUs != null) + for (Iterator iterator = resultIUs.iterator(); iterator.hasNext();) + collector.accept(iterator.next()); return collector; } diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Slicer.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Slicer.java index de5aa14ed..ab629af91 100644 --- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Slicer.java +++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Slicer.java @@ -10,16 +10,12 @@ *******************************************************************************/ package org.eclipse.equinox.internal.p2.director; -import org.eclipse.equinox.internal.provisional.p2.metadata.query.Collector; - -import org.eclipse.equinox.internal.provisional.p2.metadata.query.IQueryable; - import java.util.*; import org.eclipse.core.runtime.*; import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; import org.eclipse.equinox.internal.p2.core.helpers.Tracing; import org.eclipse.equinox.internal.provisional.p2.metadata.*; -import org.eclipse.equinox.internal.provisional.p2.metadata.query.CapabilityQuery; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.*; import org.eclipse.osgi.util.NLS; import org.osgi.framework.InvalidSyntaxException; @@ -161,6 +157,8 @@ public class Slicer { } private void expandRequirement(IInstallableUnit iu, IRequiredCapability req) { + if (req.isNegation()) + return; Collector matches = possibilites.query(new CapabilityQuery(req), new Collector(), null); int validMatches = 0; for (Iterator iterator = matches.iterator(); iterator.hasNext();) { diff --git a/bundles/org.eclipse.equinox.p2.metadata/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.metadata/META-INF/MANIFEST.MF index 59d76f933..bb446cbe9 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.p2.metadata/META-INF/MANIFEST.MF @@ -13,7 +13,8 @@ Export-Package: org.eclipse.equinox.internal.p2.metadata; org.eclipse.equinox.p2.artifact.optimizers, org.eclipse.equinox.p2.artifact.processors, org.eclipse.equinox.p2.ui, - org.eclipse.equinox.p2.publisher", + org.eclipse.equinox.p2.publisher, + org.eclipse.equinox.p2.director", org.eclipse.equinox.internal.provisional.p2.metadata; x-friends:="org.eclipse.equinox.p2.artifact.optimizers, org.eclipse.equinox.p2.artifact.processors, diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/NotRequirement.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/NotRequirement.java new file mode 100644 index 000000000..752d5444e --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/NotRequirement.java @@ -0,0 +1,69 @@ +package org.eclipse.equinox.internal.p2.metadata; + +import org.eclipse.equinox.internal.provisional.p2.metadata.*; + +public class NotRequirement implements IRequiredCapability { + private IRequiredCapability negatedRequirement; + + public NotRequirement(IRequiredCapability iRequiredCapabilities) { + negatedRequirement = iRequiredCapabilities; + } + + public IRequiredCapability getRequirement() { + return negatedRequirement; + } + + public String getFilter() { + return negatedRequirement.getFilter(); + } + + public String getName() { + return negatedRequirement.getName(); + } + + public String getNamespace() { + return negatedRequirement.getNamespace(); + } + + public VersionRange getRange() { + return negatedRequirement.getRange(); + } + + public String[] getSelectors() { + return negatedRequirement.getSelectors(); + } + + public boolean isGreedy() { + return negatedRequirement.isGreedy(); + } + + public boolean isMultiple() { + return negatedRequirement.isMultiple(); + } + + public boolean isOptional() { + return negatedRequirement.isOptional(); + } + + public void setFilter(String filter) { + // TODO Auto-generated method stub + + } + + public void setSelectors(String[] selectors) { + // TODO Auto-generated method stub + + } + + public boolean isNegation() { + return true; + } + + public String toString() { + return "NOT(" + negatedRequirement.toString() + ')'; //$NON-NLS-1$ + } + + public boolean satisfiedBy(IProvidedCapability cap) { + return !negatedRequirement.satisfiedBy(cap); + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ORRequirement.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ORRequirement.java new file mode 100644 index 000000000..3aab2c9ff --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ORRequirement.java @@ -0,0 +1,85 @@ +package org.eclipse.equinox.internal.p2.metadata; + +import org.eclipse.equinox.internal.provisional.p2.metadata.*; + +public class ORRequirement implements IRequiredCapability { + private IRequiredCapability[] oredRequirements; + + public ORRequirement(IRequiredCapability[] reqs) { + oredRequirements = reqs; + } + + public IRequiredCapability[] getRequirements() { + return oredRequirements; + } + + public String getFilter() { + // TODO Auto-generated method stub + return null; + } + + public String getName() { + // TODO Auto-generated method stub + return null; + } + + public String getNamespace() { + // TODO Auto-generated method stub + return null; + } + + public VersionRange getRange() { + // TODO Auto-generated method stub + return null; + } + + public String[] getSelectors() { + // TODO Auto-generated method stub + return null; + } + + public boolean isGreedy() { + // TODO Auto-generated method stub + return true; + } + + public boolean isMultiple() { + // TODO Auto-generated method stub + return false; + } + + public boolean isOptional() { + return false; + } + + public void setFilter(String filter) { + // TODO Auto-generated method stub + + } + + public void setSelectors(String[] selectors) { + // TODO Auto-generated method stub + + } + + public boolean isNegation() { + return false; + } + + public String toString() { + String result = "OR("; + for (int i = 0; i < oredRequirements.length; i++) { + result += oredRequirements[i].toString(); + } + return result + ")"; + } + + public boolean satisfiedBy(IProvidedCapability cap) { + for (int i = 0; i < oredRequirements.length; i++) { + boolean result = oredRequirements[i].satisfiedBy(cap); + if (result) + return true; + } + return false; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java index 38f678fbb..1d8ed6dfa 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java @@ -65,11 +65,7 @@ public class ProvidedCapability implements IProvidedCapability { * capability, and <code>false</code> otherwise. */ public boolean satisfies(IRequiredCapability candidate) { - if (getName() == null || !getName().equals(candidate.getName())) - return false; - if (getNamespace() == null || !getNamespace().equals(candidate.getNamespace())) - return false; - return candidate.getRange().isIncluded(version); + return candidate.satisfiedBy(this); } public String toString() { diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java index 6fbad3d80..690c9e1ba 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java @@ -180,4 +180,16 @@ public class RequiredCapability implements IRequiredCapability { result.append(range); return result.toString(); } + + public boolean isNegation() { + return false; + } + + public boolean satisfiedBy(IProvidedCapability cap) { + if (getName() == null || !getName().equals(cap.getName())) + return false; + if (getNamespace() == null || !getNamespace().equals(cap.getNamespace())) + return false; + return getRange().isIncluded(cap.getVersion()); + } } diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/provisional/p2/metadata/IRequiredCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/provisional/p2/metadata/IRequiredCapability.java index 32b5eac97..9e0b652e6 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/provisional/p2/metadata/IRequiredCapability.java +++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/provisional/p2/metadata/IRequiredCapability.java @@ -9,8 +9,6 @@ ******************************************************************************/ package org.eclipse.equinox.internal.provisional.p2.metadata; - - /** * A required capability represents some external constraint on an {@link IInstallableUnit}. * Each capability represents something an {@link IInstallableUnit} needs that @@ -85,4 +83,8 @@ public interface IRequiredCapability { */ public boolean equals(Object other); + public boolean isNegation(); + + public boolean satisfiedBy(IProvidedCapability cap); + }
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/NegationTesting.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/NegationTesting.java new file mode 100644 index 000000000..a2e498c6f --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/NegationTesting.java @@ -0,0 +1,312 @@ +package org.eclipse.equinox.p2.tests.planner; + +import java.util.*; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.p2.director.Slicer; +import org.eclipse.equinox.internal.p2.metadata.*; +import org.eclipse.equinox.internal.provisional.p2.director.*; +import org.eclipse.equinox.internal.provisional.p2.engine.IProfile; +import org.eclipse.equinox.internal.provisional.p2.metadata.*; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.*; +import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository; +import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; + +public class NegationTesting extends AbstractProvisioningTest { + private static final String NS = "theNamespace"; + private static final String N = "theName"; + + public void testNot1() { + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 1.2.0)"), null, false, false); + NotRequirement req = new NotRequirement(req1); + ProvidedCapability prov = new ProvidedCapability(NS, N, new Version(1, 5, 0)); + assertTrue(prov.satisfies(req)); + } + + public void testNot2() { + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 1.2.0)"), null, false, false); + NotRequirement req = new NotRequirement(req1); + ProvidedCapability prov = new ProvidedCapability(NS, N, new Version(1, 1, 0)); + assertFalse(prov.satisfies(req)); + } + + public void testNot3() { + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 1.2.0)"), null, false, false); + // RequiredCapability req2 = new RequiredCapability(NS, N, new VersionRange("[1.5.0, 2.0.0)"), null, false, false); + NotRequirement req = new NotRequirement(req1); + ProvidedCapability prov = new ProvidedCapability("foo", "bar", new Version(1, 5, 0)); + assertTrue(prov.satisfies(req)); + } + + //Test the slicer and the resolver. + public void testNot4() { + MetadataFactory.InstallableUnitDescription iud1 = new MetadataFactory.InstallableUnitDescription(); + iud1.setId("TestNegation4"); + iud1.setVersion(Version.create("1.0.0")); + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.1.0, 1.2.0)"), null, false, false); + NotRequirement req = new NotRequirement(req1); + RequiredCapability req2 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 2.0.0)"), null, false, false); + Collection requirements = new ArrayList(); + requirements.add(req); + requirements.add(req2); + iud1.addRequiredCapabilities(requirements); + Collection capabilities = new ArrayList(); + capabilities.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "TestNegation4", Version.create("1.0.0"))); + iud1.addProvidedCapabilities(capabilities); + IInstallableUnit iu1 = MetadataFactory.createInstallableUnit(iud1); + + MetadataFactory.InstallableUnitDescription iud2 = new MetadataFactory.InstallableUnitDescription(); + iud2.setId("ProviderOf1"); + iud2.setVersion(Version.create("1.0.0")); + Collection capabilities2 = new ArrayList(); + capabilities2.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.0.0"))); + iud2.addProvidedCapabilities(capabilities2); + IInstallableUnit iu2 = MetadataFactory.createInstallableUnit(iud2); + + MetadataFactory.InstallableUnitDescription iud3 = new MetadataFactory.InstallableUnitDescription(); + iud3.setId("ProviderOf1_1_1"); + iud3.setVersion(Version.create("1.0.0")); + Collection capabilities3 = new ArrayList(); + capabilities3.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.1.1"))); + capabilities3.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "ProviderOf1_1_1", Version.create("1.0.0"))); + iud3.addProvidedCapabilities(capabilities3); + IInstallableUnit iu3 = MetadataFactory.createInstallableUnit(iud3); + + IMetadataRepository repo = createTestMetdataRepository(new IInstallableUnit[] {iu1, iu2, iu3}); + + // Verify that the slice includes iu3 because the requirement from iu1 is a range including the provided capability of iu3. + Slicer slicer = new Slicer(repo, new Properties(), false); + IQueryable slice = slicer.slice(new IInstallableUnit[] {iu1}, new NullProgressMonitor()); + assertEquals(3, slice.query(InstallableUnitQuery.ANY, new Collector(), new NullProgressMonitor()).size()); + + //Verify that the resolution succeeds and does not return iu3 since it is excluded by the requirement of iu1 + IProfile profile = createProfile("TestProfile." + getName()); + IPlanner planner = createPlanner(); + ProfileChangeRequest changeRequest = new ProfileChangeRequest(profile); + changeRequest.addInstallableUnits(new IInstallableUnit[] {iu1}); + ProvisioningPlan plan = planner.getProvisioningPlan(changeRequest, null, null); + assertEquals(0, plan.getCompleteState().query(new InstallableUnitQuery("ProviderOf1_1_1"), new Collector(), null).size()); + assertEquals(2, plan.getCompleteState().query(InstallableUnitQuery.ANY, new Collector(), null).size()); + + //Verify that the installing iu1 and iu3 will result in a conflict since iu3 is excluded by the requirement of iu1 + ProfileChangeRequest changeRequest2 = new ProfileChangeRequest(profile); + changeRequest2.addInstallableUnits(new IInstallableUnit[] {iu1, iu3}); + ProvisioningPlan plan2 = planner.getProvisioningPlan(changeRequest2, null, null); + assertNotOK("The resolution should be failing because of the negation requirement.", plan2.getStatus()); + } + + public void testNot5() { + MetadataFactory.InstallableUnitDescription iud1 = new MetadataFactory.InstallableUnitDescription(); + iud1.setId("TestNegation4"); + iud1.setVersion(Version.create("1.0.0")); + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.1.0, 1.2.0)"), null, false, false); + NotRequirement req = new NotRequirement(req1); + RequiredCapability req2 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 1.1.0)"), null, false, false); + Collection requirements = new ArrayList(); + requirements.add(req); + requirements.add(req2); + iud1.addRequiredCapabilities(requirements); + Collection capabilities = new ArrayList(); + capabilities.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "TestNegation4", Version.create("1.0.0"))); + iud1.addProvidedCapabilities(capabilities); + IInstallableUnit iu1 = MetadataFactory.createInstallableUnit(iud1); + + MetadataFactory.InstallableUnitDescription iud2 = new MetadataFactory.InstallableUnitDescription(); + iud2.setId("ProviderOf1"); + iud2.setVersion(Version.create("1.0.0")); + Collection capabilities2 = new ArrayList(); + capabilities2.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.0.0"))); + iud2.addProvidedCapabilities(capabilities2); + IInstallableUnit iu2 = MetadataFactory.createInstallableUnit(iud2); + + MetadataFactory.InstallableUnitDescription iud3 = new MetadataFactory.InstallableUnitDescription(); + iud3.setId("ProviderOf1_1_1"); + iud3.setVersion(Version.create("1.0.0")); + Collection capabilities3 = new ArrayList(); + capabilities3.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.1.1"))); + capabilities3.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "ProviderOf1_1_1", Version.create("1.0.0"))); + iud3.addProvidedCapabilities(capabilities3); + IInstallableUnit iu3 = MetadataFactory.createInstallableUnit(iud3); + + IMetadataRepository repo = createTestMetdataRepository(new IInstallableUnit[] {iu1, iu2, iu3}); + + //Test the slicer. The slice will not contain iu3 because none of the range of iu1 cause it to be brought in. + Slicer slicer = new Slicer(repo, new Properties(), false); + IQueryable slice = slicer.slice(new IInstallableUnit[] {iu1}, new NullProgressMonitor()); + assertEquals(0, slice.query(new InstallableUnitQuery("ProviderOf1_1_1"), new Collector(), new NullProgressMonitor()).size()); + assertEquals(2, slice.query(InstallableUnitQuery.ANY, new Collector(), new NullProgressMonitor()).size()); + } + + public void testNot6() { + MetadataFactory.InstallableUnitDescription iud1 = new MetadataFactory.InstallableUnitDescription(); + iud1.setId("TestNegation4"); + iud1.setVersion(Version.create("1.0.0")); + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.1.0, 1.2.0)"), null, false, false); + NotRequirement req = new NotRequirement(req1); + RequiredCapability req2 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 1.1.0)"), null, false, false); + Collection requirements = new ArrayList(); + requirements.add(req); + requirements.add(req2); + iud1.addRequiredCapabilities(requirements); + Collection capabilities = new ArrayList(); + capabilities.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "TestNegation4", Version.create("1.0.0"))); + iud1.addProvidedCapabilities(capabilities); + IInstallableUnit iu1 = MetadataFactory.createInstallableUnit(iud1); + + MetadataFactory.InstallableUnitDescription iud2 = new MetadataFactory.InstallableUnitDescription(); + iud2.setId("ProviderOf1"); + iud2.setVersion(Version.create("1.0.0")); + Collection capabilities2 = new ArrayList(); + capabilities2.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.0.0"))); + iud2.addProvidedCapabilities(capabilities2); + IInstallableUnit iu2 = MetadataFactory.createInstallableUnit(iud2); + + IMetadataRepository repo = createTestMetdataRepository(new IInstallableUnit[] {iu1, iu2}); + + //Test the slicer. The slice will not contain iu3 because none of the range of iu1 cause it to be brought in. + Slicer slicer = new Slicer(repo, new Properties(), false); + IQueryable slice = slicer.slice(new IInstallableUnit[] {iu1}, new NullProgressMonitor()); + assertEquals(0, slice.query(new InstallableUnitQuery("ProviderOf1_1_1"), new Collector(), new NullProgressMonitor()).size()); + assertEquals(2, slice.query(InstallableUnitQuery.ANY, new Collector(), new NullProgressMonitor()).size()); + + //Verify that the negation can not fail the resolution when the IUs satisfying the negative requirement are not there + IProfile profile = createProfile("TestProfile." + getName()); + IPlanner planner = createPlanner(); + ProfileChangeRequest changeRequest = new ProfileChangeRequest(profile); + changeRequest.addInstallableUnits(new IInstallableUnit[] {iu1}); + ProvisioningPlan plan = planner.getProvisioningPlan(changeRequest, null, null); + assertEquals(0, plan.getCompleteState().query(new InstallableUnitQuery("ProviderOf1_1_1"), new Collector(), null).size()); + assertEquals(2, plan.getCompleteState().query(InstallableUnitQuery.ANY, new Collector(), null).size()); + } + + //Test the slicer and the resolver. + public void testNot7() { + MetadataFactory.InstallableUnitDescription iud1 = new MetadataFactory.InstallableUnitDescription(); + iud1.setId("TestNegation4"); + iud1.setVersion(Version.create("1.0.0")); + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.1.0, 1.2.0)"), null, false, false); + NotRequirement req = new NotRequirement(req1); + RequiredCapability req2 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 2.0.0)"), null, false, false); + Collection requirements = new ArrayList(); + requirements.add(req); + requirements.add(req2); + iud1.addRequiredCapabilities(requirements); + Collection capabilities = new ArrayList(); + capabilities.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "TestNegation4", Version.create("1.0.0"))); + iud1.addProvidedCapabilities(capabilities); + IInstallableUnit iu1 = MetadataFactory.createInstallableUnit(iud1); + + MetadataFactory.InstallableUnitDescription iud2 = new MetadataFactory.InstallableUnitDescription(); + iud2.setId("ProviderOf1"); + iud2.setVersion(Version.create("1.0.0")); + Collection capabilities2 = new ArrayList(); + capabilities2.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.0.0"))); + iud2.addProvidedCapabilities(capabilities2); + IInstallableUnit iu2 = MetadataFactory.createInstallableUnit(iud2); + + MetadataFactory.InstallableUnitDescription iud3 = new MetadataFactory.InstallableUnitDescription(); + iud3.setId("ProviderOf1_1_1"); + iud3.setVersion(Version.create("1.0.0")); + Collection capabilities3 = new ArrayList(); + capabilities3.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.1.1"))); + capabilities3.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "ProviderOf1_1_1", Version.create("1.0.0"))); + iud3.addProvidedCapabilities(capabilities3); + Collection requirements3 = new ArrayList(); + requirements3.add(MetadataFactory.createRequiredCapability("DOES-NOT-EXIST", "NEVER", new VersionRange("[1.0.0, 2.0.0)"), null, false, false)); + iud3.addRequiredCapabilities(requirements3); + IInstallableUnit iu3 = MetadataFactory.createInstallableUnit(iud3); + + IMetadataRepository repo = createTestMetdataRepository(new IInstallableUnit[] {iu1, iu2, iu3}); + + // Verify that the slice includes iu3 because the requirement from iu1 is a range including the provided capability of iu3. + Slicer slicer = new Slicer(repo, new Properties(), false); + IQueryable slice = slicer.slice(new IInstallableUnit[] {iu1}, new NullProgressMonitor()); + assertEquals(3, slice.query(InstallableUnitQuery.ANY, new Collector(), new NullProgressMonitor()).size()); + + //Verify that the resolution succeeds and does not return iu3 since it is excluded by the requirement of iu1 + IProfile profile = createProfile("TestProfile." + getName()); + IPlanner planner = createPlanner(); + ProfileChangeRequest changeRequest = new ProfileChangeRequest(profile); + changeRequest.addInstallableUnits(new IInstallableUnit[] {iu1}); + ProvisioningPlan plan = planner.getProvisioningPlan(changeRequest, null, null); + assertEquals(0, plan.getCompleteState().query(new InstallableUnitQuery("ProviderOf1_1_1"), new Collector(), null).size()); + assertEquals(2, plan.getCompleteState().query(InstallableUnitQuery.ANY, new Collector(), null).size()); + + //Verify that the installing iu1 and iu3 will result in a conflict since iu3 is excluded by the requirement of iu1 + ProfileChangeRequest changeRequest2 = new ProfileChangeRequest(profile); + changeRequest2.addInstallableUnits(new IInstallableUnit[] {iu1, iu3}); + ProvisioningPlan plan2 = planner.getProvisioningPlan(changeRequest2, null, null); + assertNotOK("The resolution should be failing because of the negation requirement.", plan2.getStatus()); + } + + public void testNot8() { + MetadataFactory.InstallableUnitDescription iud1 = new MetadataFactory.InstallableUnitDescription(); + iud1.setId("TestNegation4"); + iud1.setVersion(Version.create("1.0.0")); + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.1.0, 1.2.0)"), null, false, false); + NotRequirement req = new NotRequirement(req1); + RequiredCapability req2 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 2.0.0)"), null, false, false); + Collection requirements = new ArrayList(); + requirements.add(req); + requirements.add(req2); + iud1.addRequiredCapabilities(requirements); + Collection capabilities = new ArrayList(); + capabilities.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "TestNegation4", Version.create("1.0.0"))); + iud1.addProvidedCapabilities(capabilities); + IInstallableUnit iu1 = MetadataFactory.createInstallableUnit(iud1); + + MetadataFactory.InstallableUnitDescription iud2 = new MetadataFactory.InstallableUnitDescription(); + iud2.setId("ProviderOf1"); + iud2.setVersion(Version.create("1.0.0")); + Collection capabilities2 = new ArrayList(); + capabilities2.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.0.0"))); + iud2.addProvidedCapabilities(capabilities2); + IInstallableUnit iu2 = MetadataFactory.createInstallableUnit(iud2); + + MetadataFactory.InstallableUnitDescription iud3 = new MetadataFactory.InstallableUnitDescription(); + iud3.setId("ProviderOf1_1_1"); + iud3.setVersion(Version.create("1.0.0")); + Collection capabilities3 = new ArrayList(); + capabilities3.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.1.1"))); + capabilities3.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "ProviderOf1_1_1", Version.create("1.0.0"))); + iud3.addProvidedCapabilities(capabilities3); + IInstallableUnit iu3 = MetadataFactory.createInstallableUnit(iud3); + + MetadataFactory.InstallableUnitDescription iud4 = new MetadataFactory.InstallableUnitDescription(); + iud4.setId("AnotherRoot"); + iud4.setVersion(Version.create("1.0.0")); + Collection capabilities4 = new ArrayList(); + capabilities4.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "AnotherRoot", Version.create("1.0.0"))); + iud4.addProvidedCapabilities(capabilities4); + Collection reqs4 = new ArrayList(); + reqs4.add(new RequiredCapability(NS, N, new VersionRange("[1.1.1, 1.1.1]"), null, false, false)); + iud4.addRequiredCapabilities(reqs4); + IInstallableUnit iu4 = MetadataFactory.createInstallableUnit(iud4); + + IMetadataRepository repo = createTestMetdataRepository(new IInstallableUnit[] {iu1, iu2, iu3, iu4}); + + // Verify that the slice includes iu3 + Slicer slicer = new Slicer(repo, new Properties(), false); + IQueryable slice = slicer.slice(new IInstallableUnit[] {iu1, iu4}, new NullProgressMonitor()); + assertEquals(4, slice.query(InstallableUnitQuery.ANY, new Collector(), new NullProgressMonitor()).size()); + + // Verify that the slice includes iu3 + Slicer slicer2 = new Slicer(repo, new Properties(), false); + IQueryable slice2 = slicer2.slice(new IInstallableUnit[] {iu4}, new NullProgressMonitor()); + assertEquals(2, slice2.query(InstallableUnitQuery.ANY, new Collector(), new NullProgressMonitor()).size()); + + //Verify that the resolution succeeds and does not return iu3 since it is excluded by the requirement of iu1 + IProfile profile = createProfile("TestProfile." + getName()); + IPlanner planner = createPlanner(); + ProfileChangeRequest changeRequest = new ProfileChangeRequest(profile); + changeRequest.addInstallableUnits(new IInstallableUnit[] {iu1}); + ProvisioningPlan plan = planner.getProvisioningPlan(changeRequest, null, null); + assertEquals(0, plan.getCompleteState().query(new InstallableUnitQuery("ProviderOf1_1_1"), new Collector(), null).size()); + assertEquals(2, plan.getCompleteState().query(InstallableUnitQuery.ANY, new Collector(), null).size()); + + //Verify that the installing iu1 and iu4 will result in a conflict since iu3 is excluded by the requirement of iu1 + ProfileChangeRequest changeRequest2 = new ProfileChangeRequest(profile); + changeRequest2.addInstallableUnits(new IInstallableUnit[] {iu1, iu4}); + ProvisioningPlan plan2 = planner.getProvisioningPlan(changeRequest2, null, null); + assertNotOK("The resolution should be failing because of the negation requirement.", plan2.getStatus()); + } +} diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/ORTesting.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/ORTesting.java new file mode 100644 index 000000000..2b391867a --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/ORTesting.java @@ -0,0 +1,150 @@ +package org.eclipse.equinox.p2.tests.planner; + +import java.util.ArrayList; +import java.util.Collection; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.p2.director.Slicer; +import org.eclipse.equinox.internal.p2.metadata.*; +import org.eclipse.equinox.internal.provisional.p2.director.*; +import org.eclipse.equinox.internal.provisional.p2.engine.IProfile; +import org.eclipse.equinox.internal.provisional.p2.metadata.*; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.*; +import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository; +import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; + +public class ORTesting extends AbstractProvisioningTest { + //A[1.0] v A[1.1] + //!A[1.0.2] + + //A v C v !D[1.0.0, 1.1.0] <-- What is the semantics of negation on a range? + + private static final String NS = "theNamespace"; + private static final String N = "theName"; + + //A v C v C[1.0.0] + public void testOR() { + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 1.2.0)"), null, false, false); + // RequiredCapability req2 = new RequiredCapability(NS, N, new VersionRange("[1.5.0, 2.0.0)"), null, false, false); + ORRequirement req = new ORRequirement(new IRequiredCapability[] {req1}); + ProvidedCapability prov = new ProvidedCapability(NS, N, new Version(1, 5, 0)); + assertFalse(prov.satisfies(req)); + } + + public void testOR2() { + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.0.0, 1.2.0)"), null, false, false); + RequiredCapability req2 = new RequiredCapability(NS, N, new VersionRange("[1.5.0, 2.0.0)"), null, false, false); + ORRequirement req = new ORRequirement(new IRequiredCapability[] {req1, req2}); + ProvidedCapability prov = new ProvidedCapability(NS, N, new Version(1, 5, 0)); + assertTrue(prov.satisfies(req)); + } + + public void testOR3() { + MetadataFactory.InstallableUnitDescription iud1 = new MetadataFactory.InstallableUnitDescription(); + iud1.setId("TestOr"); + iud1.setVersion(Version.create("1.0.0")); + RequiredCapability req1 = new RequiredCapability(NS, N, new VersionRange("[1.1.0, 1.2.0)"), null, false, false); + RequiredCapability req2 = new RequiredCapability(NS, N, new VersionRange("[1.3.0, 1.4.0)"), null, false, false); + Collection requirements = new ArrayList(); + requirements.add(new ORRequirement(new IRequiredCapability[] {req1, req2})); + iud1.addRequiredCapabilities(requirements); + Collection capabilities = new ArrayList(); + capabilities.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "TestOr", Version.create("1.0.0"))); + iud1.addProvidedCapabilities(capabilities); + IInstallableUnit iu1 = MetadataFactory.createInstallableUnit(iud1); + + MetadataFactory.InstallableUnitDescription iud2 = new MetadataFactory.InstallableUnitDescription(); + iud2.setId("ProviderOf1_0_0"); + iud2.setVersion(Version.create("1.0.0")); + Collection capabilities2 = new ArrayList(); + capabilities2.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.0.0"))); + iud2.addProvidedCapabilities(capabilities2); + IInstallableUnit iu2 = MetadataFactory.createInstallableUnit(iud2); + + MetadataFactory.InstallableUnitDescription iud3 = new MetadataFactory.InstallableUnitDescription(); + iud3.setId("ProviderOf1_1_1"); + iud3.setVersion(Version.create("1.0.0")); + Collection capabilities3 = new ArrayList(); + capabilities3.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.1.1"))); + capabilities3.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "ProviderOf1_1_1", Version.create("1.0.0"))); + iud3.addProvidedCapabilities(capabilities3); + IInstallableUnit iu3 = MetadataFactory.createInstallableUnit(iud3); + + MetadataFactory.InstallableUnitDescription iud4 = new MetadataFactory.InstallableUnitDescription(); + iud4.setId("ProviderOf1_3_0"); + iud4.setVersion(Version.create("1.0.0")); + Collection capabilities4 = new ArrayList(); + capabilities4.add(MetadataFactory.createProvidedCapability(NS, N, Version.create("1.3.0"))); + capabilities4.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "ProviderOf1_3_0", Version.create("1.0.0"))); + iud4.addProvidedCapabilities(capabilities4); + IInstallableUnit iu4 = MetadataFactory.createInstallableUnit(iud4); + + IMetadataRepository repo = createTestMetdataRepository(new IInstallableUnit[] {iu1, iu2, iu3, iu4}); + + Slicer slicer = new Slicer(repo, null, false); + IQueryable slice = slicer.slice(new IInstallableUnit[] {iu1}, new NullProgressMonitor()); + Collector c = slice.query(InstallableUnitQuery.ANY, new Collector(), null); + assertEquals(3, c.size()); + + IPlanner planner = createPlanner(); + IProfile profile = createProfile("testOR3"); + ProfileChangeRequest changeRequest = new ProfileChangeRequest(profile); + changeRequest.addInstallableUnits(new IInstallableUnit[] {iu1}); + ProvisioningPlan plan = planner.getProvisioningPlan(changeRequest, null, null); + assertOK("Plan OK", plan.getStatus()); + // assertEquals(1, plan.getCompleteState().query(new InstallableUnitQuery(id), collector, monitor)) + } + + public void testOR4() { + IInstallableUnit a1 = createIU("A", Version.create("1.0.0"), true); + IInstallableUnit a2 = createIU("A", Version.create("2.0.0"), true); + + MetadataFactory.InstallableUnitDescription iud1 = new MetadataFactory.InstallableUnitDescription(); + iud1.setId("TestOr"); + iud1.setVersion(Version.create("1.0.0")); + RequiredCapability req1 = new RequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, "A", new VersionRange("[1.0.0, 1.2.0)"), null, false, false); + RequiredCapability req2 = new RequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, "A", new VersionRange("[2.0.0, 2.2.0)"), null, false, false); + + Collection requirements = new ArrayList(); + requirements.add(new ORRequirement(new IRequiredCapability[] {req1, req2})); + iud1.addRequiredCapabilities(requirements); + Collection capabilities = new ArrayList(); + capabilities.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "TestOr", Version.create("1.0.0"))); + iud1.addProvidedCapabilities(capabilities); + IInstallableUnit iu1 = MetadataFactory.createInstallableUnit(iud1); + + createTestMetdataRepository(new IInstallableUnit[] {iu1, a2, a1}); + + IPlanner planner = createPlanner(); + IProfile profile = createProfile("TestOr4"); + ProfileChangeRequest changeRequest = new ProfileChangeRequest(profile); + changeRequest.addInstallableUnits(new IInstallableUnit[] {iu1}); + ProvisioningPlan plan = planner.getProvisioningPlan(changeRequest, null, null); + assertOK("Plan OK", plan.getStatus()); + // assertEquals(1, plan.getCompleteState().query(new InstallableUnitQuery(id), collector, monitor)) + } + + public void testOR5() { + MetadataFactory.InstallableUnitDescription iud1 = new MetadataFactory.InstallableUnitDescription(); + iud1.setId("TestOr"); + iud1.setVersion(Version.create("1.0.0")); + RequiredCapability req1 = new RequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, "A", new VersionRange("[1.0.0, 1.2.0)"), null, false, false); + RequiredCapability req2 = new RequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, "A", new VersionRange("[2.0.0, 2.2.0)"), null, false, false); + Collection requirements = new ArrayList(); + requirements.add(new ORRequirement(new IRequiredCapability[] {req1, req2})); + iud1.addRequiredCapabilities(requirements); + Collection capabilities = new ArrayList(); + capabilities.add(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, "TestOr", Version.create("1.0.0"))); + iud1.addProvidedCapabilities(capabilities); + IInstallableUnit iu1 = MetadataFactory.createInstallableUnit(iud1); + + createTestMetdataRepository(new IInstallableUnit[] {iu1}); + + IPlanner planner = createPlanner(); + IProfile profile = createProfile("TestOr4"); + ProfileChangeRequest changeRequest = new ProfileChangeRequest(profile); + changeRequest.addInstallableUnits(new IInstallableUnit[] {iu1}); + ProvisioningPlan plan = planner.getProvisioningPlan(changeRequest, null, null); + assertNotOK("Plan Not OK", plan.getStatus()); + // assertEquals(1, plan.getCompleteState().query(new InstallableUnitQuery(id), collector, monitor)) + } +} |