From 0e34c3bbf517514f10ce328cf16eb08f673c1723 Mon Sep 17 00:00:00 2001 From: Henrik Lindberg Date: Tue, 1 Dec 2009 17:44:01 +0000 Subject: [294691] Applying patch with tests for p2ql (and friends declarations where needed). https://bugs.eclipse.org/bugs/attachment.cgi?id=153367 --- .../META-INF/MANIFEST.MF | 4 +- .../META-INF/MANIFEST.MF | 2 + .../eclipse/equinox/p2/tests/ql/EvaluatorTest.java | 419 +++++++++++++++++++++ .../equinox/p2/tests/ql/PerformanceTest.java | 187 +++++++++ .../p2/tests/ql/TestQueryReimplementation.java | 178 +++++++++ 5 files changed, 789 insertions(+), 1 deletion(-) create mode 100644 bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/EvaluatorTest.java create mode 100644 bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/PerformanceTest.java create mode 100644 bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/TestQueryReimplementation.java (limited to 'bundles') 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 c3399ccca..c469471a8 100644 --- a/bundles/org.eclipse.equinox.p2.metadata/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.p2.metadata/META-INF/MANIFEST.MF @@ -16,7 +16,7 @@ Export-Package: org.eclipse.equinox.internal.p2.metadata; org.eclipse.equinox.p2.operations, org.eclipse.equinox.p2.common, org.eclipse.equinox.p2.publisher, - org.eclipse.equinox.p2.director", + 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, @@ -38,6 +38,7 @@ Export-Package: org.eclipse.equinox.internal.p2.metadata; org.eclipse.equinox.p2.metadata.repository, org.eclipse.equinox.p2.operations, org.eclipse.equinox.p2.publisher, + org.eclipse.equinox.p2.ql, org.eclipse.equinox.p2.reconciler.dropins, org.eclipse.equinox.p2.touchpoint.eclipse, org.eclipse.equinox.p2.touchpoint.natives, @@ -69,6 +70,7 @@ Export-Package: org.eclipse.equinox.internal.p2.metadata; org.eclipse.equinox.p2.metadata.generator, org.eclipse.equinox.p2.metadata.repository, org.eclipse.equinox.p2.operations, + org.eclipse.equinox.p2.ql, org.eclipse.equinox.p2.reconciler.dropins, org.eclipse.equinox.p2.touchpoint.eclipse, org.eclipse.equinox.p2.touchpoint.natives, diff --git a/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF index c2a971ec6..f37ed5b6b 100644 --- a/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF @@ -26,6 +26,7 @@ Import-Package: javax.xml.parsers, org.eclipse.equinox.internal.p2.metadata.repository.io, org.eclipse.equinox.internal.p2.persistence, org.eclipse.equinox.internal.p2.publisher.eclipse, + org.eclipse.equinox.internal.p2.ql, org.eclipse.equinox.internal.p2.touchpoint.eclipse, org.eclipse.equinox.internal.p2.touchpoint.eclipse.actions, org.eclipse.equinox.internal.p2.touchpoint.natives, @@ -49,6 +50,7 @@ Import-Package: javax.xml.parsers, org.eclipse.equinox.p2.internal.repository.tools, org.eclipse.equinox.p2.metadata, org.eclipse.equinox.p2.metadata.query, + org.eclipse.equinox.p2.ql, org.eclipse.equinox.spi.p2.publisher, org.eclipse.internal.provisional.equinox.p2.jarprocessor, org.eclipse.osgi.service.datalocation, diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/EvaluatorTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/EvaluatorTest.java new file mode 100644 index 000000000..a2b044d14 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/EvaluatorTest.java @@ -0,0 +1,419 @@ +/******************************************************************************* + * Copyright (c) 2009 Cloudsmith Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Cloudsmith Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.tests.ql; + +import java.io.File; +import java.net.URI; +import java.util.*; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; +import org.eclipse.equinox.internal.p2.director.QueryableArray; +import org.eclipse.equinox.internal.p2.director.app.Activator; +import org.eclipse.equinox.internal.p2.ql.*; +import org.eclipse.equinox.internal.provisional.p2.metadata.*; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.*; +import org.eclipse.equinox.p2.metadata.IArtifactKey; +import org.eclipse.equinox.p2.metadata.query.IQuery; +import org.eclipse.equinox.p2.publisher.PublisherInfo; +import org.eclipse.equinox.p2.publisher.PublisherResult; +import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction; +import org.eclipse.equinox.p2.ql.ExpressionQuery; +import org.eclipse.equinox.p2.ql.PredicateQuery; +import org.eclipse.equinox.p2.repository.artifact.*; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; +import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; +import org.eclipse.equinox.p2.tests.TestActivator; +import org.osgi.framework.Filter; + +public class EvaluatorTest extends AbstractProvisioningTest { + private static final ExpressionParser parser = new ExpressionParser(); + private static final VariableScope dummyScope = new VariableScope(); + + public void testArguments() throws Exception { + Expression expr = parser.parsePredicate("'a' == $0 && 'b' == $1 && 'c' == $2"); + assertEquals(Boolean.TRUE, expr.evaluate(new ExpressionContext(null, new Object[] {"a", "b", "c"}, null), dummyScope)); + } + + public void testAnonymousMember() throws Exception { + Expression expr = parser.parsePredicate("$0.class == $1"); + assertEquals(Boolean.TRUE, expr.evaluate(new ExpressionContext(null, new Object[] {"a", String.class}, null), dummyScope)); + } + + public void testInstanceOf() throws Exception { + // Explicit instanceof when rhs is a class + Expression expr = parser.parsePredicate("$0 ~= $1"); + assertEquals(Boolean.TRUE, expr.evaluate(new ExpressionContext(null, new Object[] {new Integer(4), Number.class}, null), dummyScope)); + } + + public void testArray() throws Exception { + ExpressionContext ctx = new ExpressionContext(null, null, null); + Expression expr = parser.parsePredicate("['a', 'b', 'c'].exists(x | x == 'b') && ['a', 'b', 'c'].all(x | 'd' > x)"); + assertEquals(Boolean.TRUE, expr.evaluate(ctx, dummyScope)); + expr = parser.parsePredicate("['d', 'e', 'f'].exists(x | ['a', 'b', 'c'].exists(y | x > y))"); + assertEquals(Boolean.TRUE, expr.evaluate(ctx, dummyScope)); + expr = parser.parsePredicate("[['d', 'e', 'f'], ['h', 'i', 'j']].exists(x | x.all(y | ['a', 'b', 'c'].all(z | y > z)))"); + assertEquals(Boolean.TRUE, expr.evaluate(ctx, dummyScope)); + expr = parser.parsePredicate("[['d', 'e', 'f'], ['h', '3', 'j']].exists(x | x.all(y | ['a', 'b', 'c'].exists(z | y > z)))"); + assertEquals(Boolean.TRUE, expr.evaluate(ctx, dummyScope)); + expr = parser.parsePredicate("[['d', 'e', 'f'], ['h', 'i', 'j']].all(x | x.all(y | ['a', 'b', 'c'].all(z | y > z)))"); + assertEquals(Boolean.TRUE, expr.evaluate(ctx, dummyScope)); + expr = parser.parsePredicate("[['d', 'e', 'f'], ['h', '3', 'j']].all(x | x.all(y | ['a', 'b', 'c'].all(z | y > z)))"); + assertEquals(Boolean.FALSE, expr.evaluate(ctx, dummyScope)); // 3 < 'b' + } + + public void testLatest() throws Exception { + IMetadataRepository repo = getMDR("/testData/metadataRepo/multipleversions1"); + Collector result = repo.query(new ExpressionQuery("latest(x | x.id == $0)", "test.bundle"), new Collector(), new NullProgressMonitor()); + assertTrue(result.size() == 1); + } + + public void testRange() throws Exception { + IMetadataRepository repo = getMDR("/testData/metadataRepo/multipleversions1"); + Collector result = repo.query(new PredicateQuery("version ~= $0", new VersionRange("2.0.0")), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 2); + } + + public void testProperty() throws Exception { + IMetadataRepository repo = getMDR("/testData/metadataRepo/multipleversions1"); + + Collector result = repo.query(new PredicateQuery("properties.exists(p | p.value == $0)", "true"), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 3); + + result = repo.query(new PredicateQuery("properties['org.eclipse.equinox.p2.type.group'] == $0", "true"), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 3); + + Filter filter = TestActivator.context.createFilter("(org.eclipse.equinox.p2.type.group=true)"); + result = repo.query(new PredicateQuery("properties ~= $0", filter), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 3); + } + + public void testToString() throws Exception { + String exprString = "select(x | x.id == $0 && (x.version == $1 || x.version == $2)).traverse(set(), _, {requirementsCache, parent | select(" + // + "parent.requiredCapabilities.unique(requirementsCache).select(rc | rc.filter == null || $2 ~= filter(rc.filter)), _, " + // + "{rcs, child | rcs.exists(rc | child ~= rc)})}).limit(10)"; + + ContextExpression expr = parser.parseQuery(exprString); + System.out.println(expr.toString()); + assertEquals(exprString, expr.toString()); + } + + public void testSomeAPI() throws Exception { + // Create some expressions. Note the use of identifiers instead of + // indexes for the parameters + + Variable item = Variable.createEach("item"); + Expression cmp1 = new Equals(new Member(item, "id"), new KeyedParameter("id")); + Expression cmp2 = new Equals(new At(new Member(item, "properties"), new KeyedParameter("propKey")), new KeyedParameter("propValue")); + + Variable everything = Variable.EVERYTHING; + LambdaExpression lambda = new LambdaExpression(new And(new Expression[] {cmp1, cmp2}), item); + Expression latest = new Latest(new Select(everything, lambda)); + ContextExpression e3 = new ContextExpression(everything, latest); + + // Put the parameters in a map + Map args = new HashMap(); + args.put("id", "test.bundle"); + args.put("propKey", "org.eclipse.equinox.p2.type.group"); + args.put("propValue", "true"); + + // Create the query + IMetadataRepository repo = getMDR("/testData/metadataRepo/multipleversions1"); + Collector result = repo.query(new ExpressionQuery(e3, args), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 1); + } + + public void testMember() throws Exception { + IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo"); + IProvidedCapability pc = MetadataFactory.createProvidedCapability("org.eclipse.equinox.p2.eclipse.type", "source", null); + Collector result = repo.query(new PredicateQuery("fragment && host.exists(h | $0 ~= h)", pc), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 1); + } + + public void testPatch() throws Exception { + IRequiredCapability[][] applicability = new IRequiredCapability[2][2]; + applicability[0][0] = MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, "javax.wsdl", null, null, false, false); + applicability[0][1] = MetadataFactory.createRequiredCapability("org.eclipse.equinox.p2.eclipse.type", "bundle", null, null, false, false); + applicability[1][0] = MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, "tooling.source.default", null, null, false, false); + applicability[1][1] = MetadataFactory.createRequiredCapability("org.eclipse.equinox.p2.flavor", "tooling", null, null, false, false); + + IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo"); + Collector result = repo.query(new PredicateQuery("$0.exists(rcs | rcs.all(rc | item ~= rc))", applicability), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 3); + } + + public void testPattern() throws Exception { + IProvidedCapability pc = MetadataFactory.createProvidedCapability("org.eclipse.equinox.p2.eclipse.type", "source", null); + IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo"); + Collector result = repo.query(new PredicateQuery("id ~= /tooling.*.default/", pc), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 3); + } + + public void testLimit() throws Exception { + IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo"); + Collector result = repo.query(new ExpressionQuery("select(x | x.id ~= /tooling.*/).limit(1)"), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 1); + + result = repo.query(new ExpressionQuery("select(x | x.id ~= /tooling.*/).limit($0)", new Integer(2)), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 2); + } + + public void testNot() throws Exception { + IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo"); + Collector result = repo.query(new PredicateQuery("!(id ~= /tooling.*/)"), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 4); + } + + public void testArtifactQuery() throws Exception { + URI artifactRepo = getTestData("1.1", "/testData/artifactRepo/simple").toURI(); + + IArtifactRepositoryManager artifactManager = getArtifactRepositoryManager(); + assertNotNull(artifactManager); + + IArtifactRepository repo = artifactManager.loadRepository(artifactRepo, new NullProgressMonitor()); + Collector result = repo.query(new PredicateQuery(IArtifactKey.class, "classifier ~= /*/"), new Collector(), new NullProgressMonitor()); + assertTrue(result.size() > 1); + Iterator itor = result.iterator(); + while (itor.hasNext()) + assertTrue(itor.next() instanceof IArtifactKey); + + result = repo.query(new PredicateQuery(IArtifactDescriptor.class, "artifactKey.classifier ~= /*/"), new Collector(), new NullProgressMonitor()); + assertTrue(result.size() > 1); + itor = result.iterator(); + while (itor.hasNext()) + assertTrue(itor.next() instanceof IArtifactDescriptor); + } + + public void testClassConstructor() throws Exception { + IMetadataRepository repo = getMDR("/testData/metadataRepo/wsdlTestRepo"); + Collector result = repo.query(new ExpressionQuery(// + "select(x | x ~= class('org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnitFragment'))"), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 4); + repo = getMDR("/testData/galileoM7"); + } + + public void testTraverse() throws Exception { + IMetadataRepository repo = getMDR("/testData/galileoM7"); + Collector result = repo.query(new ExpressionQuery( // + "select(x | x.id == $0 && x.version == $1).traverse(parent | select(" + // + "child | parent.requiredCapabilities.exists(rc | child ~= rc)))", // + "org.eclipse.sdk.feature.group", Version.create("3.5.0.v20090423-7Q7bA7DPR-wM38__Q4iRsmx9z0KOjbpx3AbyvXd-Uq7J2")), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 463); + } + + public void testTraverseWithFilteredRequirements() throws Exception { + // Add some filtering of requirements + ContextExpression expr = parser.parseQuery(// + "select(x | x.id == $0 && x.version == $1).traverse(parent | select(" + // + "child | parent.requiredCapabilities.exists(rc | (rc.filter == null || $2 ~= filter(rc.filter)) && child ~= rc)))"); + + Map env = new Hashtable(); + env.put("osgi.os", "linux"); + env.put("osgi.ws", "gtk"); + env.put("osgi.arch", "x86"); + ExpressionQuery query = new ExpressionQuery(IInstallableUnit.class, expr, new Object[] {"org.eclipse.sdk.feature.group", Version.create("3.5.0.v20090423-7Q7bA7DPR-wM38__Q4iRsmx9z0KOjbpx3AbyvXd-Uq7J2"), env}); + + IMetadataRepository repo = getMDR("/testData/galileoM7"); + Collector result = repo.query(query, new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 411); + } + + public void testTraverseWithCurrying() throws Exception { + // Use currying to prevent that the filtering of requirements is done more then once + ContextExpression expr = parser.parseQuery(// + "select(x | x.id == $0 && x.version == $1).traverse({parent | select(" + // + "parent.requiredCapabilities.select(rc | rc.filter == null || $2 ~= filter(rc.filter)), _," + // + "{rcs, child | rcs.exists(rc | child ~= rc)})})"); + + Map env = new Hashtable(); + env.put("osgi.os", "linux"); + env.put("osgi.ws", "gtk"); + env.put("osgi.arch", "x86"); + ExpressionQuery query = new ExpressionQuery(IInstallableUnit.class, expr, new Object[] {"org.eclipse.sdk.feature.group", Version.create("3.5.0.v20090423-7Q7bA7DPR-wM38__Q4iRsmx9z0KOjbpx3AbyvXd-Uq7J2"), env}); + + IMetadataRepository repo = getMDR("/testData/galileoM7"); + Collector result = repo.query(query, new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 411); + } + + public void testTraverseWithCurryingAndCache() throws Exception { + // Add some filtering of requirements + ContextExpression expr = parser.parseQuery(// + "select(x | x.id == $0 && x.version == $1).traverse(set(), _, {requirementsCache, parent | select(" + // + "parent.requiredCapabilities.unique(requirementsCache).select(rc | rc.filter == null || $2 ~= filter(rc.filter)), _," + // + "{rcs, child | rcs.exists(rc | child ~= rc)})})"); + + Map env = new Hashtable(); + env.put("osgi.os", "linux"); + env.put("osgi.ws", "gtk"); + env.put("osgi.arch", "x86"); + + ExpressionQuery query = new ExpressionQuery(IInstallableUnit.class, expr, new Object[] {"org.eclipse.sdk.feature.group", Version.create("3.5.0.v20090423-7Q7bA7DPR-wM38__Q4iRsmx9z0KOjbpx3AbyvXd-Uq7J2"), env}); + + IMetadataRepository repo = getMDR("/testData/galileoM7"); + + long startTime = System.currentTimeMillis(); + Collector result = repo.query(query, new Collector(), new NullProgressMonitor()); + System.out.print("testTraverseWithCurryingAndCache: "); + System.out.println(System.currentTimeMillis() - startTime); + assertEquals(result.size(), 411); + } + + public void testCommonRequirements() throws Exception { + // Add some filtering of requirements + ContextExpression expr = parser.parseQuery(// + "" + // + "select(x | x.id == $0 && x.version == $1).traverse(set(), _, {requirementsCache, parent | select(" + // + "parent.requiredCapabilities.unique(requirementsCache).select(rc | rc.filter == null || $4 ~= filter(rc.filter)), _," + // + "{rcs, child | rcs.exists(rc | child ~= rc)})}) && " + // + "select(x | x.id == $2 && x.version == $3).traverse(set(), _, {requirementsCache, parent | select(" + // + "parent.requiredCapabilities.unique(requirementsCache).select(rc | rc.filter == null || $4 ~= filter(rc.filter)), _," + // + "{rcs, child | rcs.exists(rc | child ~= rc)})})"); + + Map env = new Hashtable(); + env.put("osgi.os", "linux"); + env.put("osgi.ws", "gtk"); + env.put("osgi.arch", "x86"); + + ExpressionQuery query = new ExpressionQuery(IInstallableUnit.class, expr, new Object[] { // + "org.eclipse.pde.feature.group", // + Version.create("3.5.0.v20090123-7Z7YF8NFE-z0VXhWU26Hu8gY"), // + "org.eclipse.gmf.feature.group", // + Version.create("1.1.1.v20090114-0940-7d8B0FXwkKwFanGNHeHHq8ymBgZ"), // + env}); + + IMetadataRepository repo = getMDR("/testData/galileoM7"); + Collector result = repo.query(query, new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 184); + } + + public void testMatchQueryInjectionInPredicate() throws Exception { + IMetadataRepository repo = getMDR("/testData/galileoM7"); + ItemExpression expr = parser.parsePredicate("iquery($0) || iquery($1)"); + MatchQuery q1 = new MatchQuery() { + @Override + public boolean isMatch(Object candidate) { + return "true".equals(((IInstallableUnit) candidate).getProperty("org.eclipse.equinox.p2.type.category")); + } + }; + MatchQuery q2 = new MatchQuery() { + @Override + public boolean isMatch(Object candidate) { + return "true".equals(((IInstallableUnit) candidate).getProperty("org.eclipse.equinox.p2.type.group")); + } + }; + Collector result = repo.query(new PredicateQuery(expr, new Object[] {q1, q2}), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 497); + } + + public void testMatchQueryInjectionInContext() throws Exception { + IMetadataRepository repo = getMDR("/testData/galileoM7"); + ContextExpression expr = parser.parseQuery("select(x | iquery($0, x) || iquery($1, x)).latest()"); + MatchQuery q1 = new MatchQuery() { + @Override + public boolean isMatch(Object candidate) { + return "true".equals(((IInstallableUnit) candidate).getProperty("org.eclipse.equinox.p2.type.category")); + } + }; + MatchQuery q2 = new MatchQuery() { + @Override + public boolean isMatch(Object candidate) { + return "true".equals(((IInstallableUnit) candidate).getProperty("org.eclipse.equinox.p2.type.group")); + } + }; + Collector result = repo.query(new ExpressionQuery(expr, new Object[] {q1, q2}), new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 497); + } + + public void testTranslationFragment() { + File foo_fragment = new File(TestActivator.getTestDataFolder(), "FragmentPublisherTest/foo.fragment");//$NON-NLS-1$ + File foo = new File(TestActivator.getTestDataFolder(), "FragmentPublisherTest/foo");//$NON-NLS-1$ + BundlesAction bundlesAction = new BundlesAction(new File[] {foo_fragment}); + PublisherInfo info = new PublisherInfo(); + PublisherResult results = new PublisherResult(); + + bundlesAction.perform(info, results, new NullProgressMonitor()); + Collection ius = results.getIUs(null, null); + assertEquals("1.0", 1, ius.size()); + + info = new PublisherInfo(); + results = new PublisherResult(); + bundlesAction = new BundlesAction(new File[] {foo}); + bundlesAction.perform(info, results, new NullProgressMonitor()); + + bundlesAction = new BundlesAction(new File[] {foo_fragment}); + bundlesAction.perform(info, results, new NullProgressMonitor()); + ius = results.getIUs(null, null); + assertEquals("2.0", 3, ius.size()); + QueryableArray queryableArray = new QueryableArray((IInstallableUnit[]) ius.toArray(new IInstallableUnit[ius.size()])); + Collector result = queryableArray.query(new InstallableUnitQuery("foo"), new Collector(), null); + assertEquals("2.1", 1, result.size()); + IInstallableUnit iu = (IInstallableUnit) result.iterator().next(); + + ContextExpression localePropertyQuery = parser.parseQuery("" + // + "[[select(f | f ~= class('org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnitFragment') && f.host.exists(h | $0 ~= h) && f.providedCapabilities.exists(pc | pc.namespace == 'org.eclipse.equinox.p2.localization' && pc.name ~= $2))" + // + ".collect(f | localizedKeys($2,$1).collect(lk | f.properties[lk])).flatten(), localizedKeys($2,$1).collect(lk | $0.properties[lk])].flatten().first(v | v != null)]");// + + IQuery lq = new ExpressionQuery(localePropertyQuery, new Object[] {iu, "foo", Locale.getDefault()}); + Collector c = queryableArray.query(lq, new Collector(), null); + Object[] pqr = c.toArray(Object.class); + assertTrue(pqr.length == 1); + assertEquals("3.2", "English Foo", pqr[0]); + + ContextExpression cacheQuery = parser.parseQuery("select(f | f ~= class('org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnitFragment') && f.host.exists(h | $0 ~= h) && f.providedCapabilities.exists(pc | pc.namespace == 'org.eclipse.equinox.p2.localization' && pc.name ~= $1))"); + IQuery fragsQuery = new ExpressionQuery(cacheQuery, new Object[] {iu, Locale.GERMAN}); + Collector frags = queryableArray.query(fragsQuery, new Collector(), null); + assertEquals(frags.size(), 1); + + localePropertyQuery = parser.parseQuery("[$0].collect(localizedKeys($2,$1), _, { lks, iu | " + // + "[$3.collect(f | lks.collect(lk | f.properties[lk])).flatten(), lks.collect(lk | iu.properties[lk])].flatten().first(v | v != null)})");// + + lq = new ExpressionQuery(localePropertyQuery, new Object[] {iu, "foo", Locale.GERMAN, frags}); + c = queryableArray.query(lq, new Collector(), null); + pqr = c.toArray(String.class); + assertTrue(pqr.length == 1); + assertEquals("2.2", "German Foo", pqr[0]); + + lq = new ExpressionQuery("localizedMap($0, $1).select(e | localizedKeys($0, $2).exists(k | k == e.key)).collect(k | k.value)", Locale.GERMAN, iu, "foo"); + c = queryableArray.query(lq, new Collector(), null); + pqr = c.toArray(String.class); + assertTrue(pqr.length == 2); + assertEquals("2.3", "German Foo", pqr[0]); + assertEquals("2.4", "English Foo", pqr[1]); // Default + + lq = new ExpressionQuery("localizedMap($0, $1).select(e | localizedKeys($0, $2).exists(k | k == e.key)).collect(k | k.value).limit(1)", Locale.GERMAN, iu, "foo"); + c = queryableArray.query(lq, new Collector(), null); + pqr = c.toArray(String.class); + assertTrue(pqr.length == 1); + assertEquals("2.5", "German Foo", pqr[0]); + + lq = new ExpressionQuery("[localizedProperty($0, $1, $2)]", Locale.GERMAN, iu, "foo"); + c = queryableArray.query(lq, new Collector(), null); + pqr = c.toArray(String.class); + assertTrue(pqr.length == 1); + assertEquals("2.6", "German Foo", pqr[0]); + + lq = new ExpressionQuery("select(x | localizedProperty($0, x, 'foo') ~= /German*/)", Locale.GERMAN); + c = queryableArray.query(lq, new Collector(), null); + pqr = c.toArray(IInstallableUnit.class); + assertTrue(pqr.length == 1); + assertEquals("2.7", "foo", ((IInstallableUnit) pqr[0]).getId()); + } + + private IMetadataRepository getMDR(String uri) throws Exception { + URI metadataRepo = getTestData("1.1", uri).toURI(); + + IMetadataRepositoryManager metadataManager = (IMetadataRepositoryManager) ServiceHelper.getService(Activator.getContext(), IMetadataRepositoryManager.SERVICE_NAME); + assertNotNull(metadataManager); + + return metadataManager.loadRepository(metadataRepo, new NullProgressMonitor()); + } +} diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/PerformanceTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/PerformanceTest.java new file mode 100644 index 000000000..abffa2af0 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/PerformanceTest.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (c) 2009 Cloudsmith Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Cloudsmith Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.tests.ql; + +import java.net.URI; +import java.util.Hashtable; +import java.util.Iterator; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; +import org.eclipse.equinox.internal.p2.director.Slicer; +import org.eclipse.equinox.internal.p2.director.app.Activator; +import org.eclipse.equinox.internal.provisional.p2.metadata.*; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.*; +import org.eclipse.equinox.p2.metadata.query.IQuery; +import org.eclipse.equinox.p2.ql.ExpressionQuery; +import org.eclipse.equinox.p2.ql.PredicateQuery; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; +import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; + +public class PerformanceTest extends AbstractProvisioningTest { + public void testCapabilityQueryPerformance() throws Exception { + + IMetadataRepository repo = getMDR("/testData/galileoM7"); + + IRequiredCapability capability = MetadataFactory.createRequiredCapability("org.eclipse.equinox.p2.eclipse.type", "feature", new VersionRange("[1.0.0,2.0.0)"), null, false, false); + CapabilityQuery capabilityQuery = new CapabilityQuery(capability); + PredicateQuery predicateQuery = new PredicateQuery("item ~= $0", capability); + Collector result; + long tradQueryMS = 0; + long exprQueryMS = 0; + + for (int i = 0; i < 10; ++i) { + long start = System.currentTimeMillis(); + for (int idx = 0; idx < 100; ++idx) { + result = repo.query(capabilityQuery, new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 487); + } + tradQueryMS += (System.currentTimeMillis() - start); + + start = System.currentTimeMillis(); + for (int idx = 0; idx < 100; ++idx) { + result = repo.query(predicateQuery, new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 487); + } + exprQueryMS += (System.currentTimeMillis() - start); + } + System.out.println("CapabilityQuery took: " + tradQueryMS + " milliseconds"); + System.out.println("PredicateQuery took: " + exprQueryMS + " milliseconds"); + + // Assert that expression query is not worse off then 4 / 3 ratio (should typically + // be better then that. + assertTrue(tradQueryMS * 4 > exprQueryMS * 3); + } + + public void testCapabilityQueryPerformance2() throws Exception { + + IMetadataRepository repo = getMDR("/testData/galileoM7"); + + IRequiredCapability[] capabilities = new IRequiredCapability[] {// + MetadataFactory.createRequiredCapability("org.eclipse.equinox.p2.eclipse.type", "feature", new VersionRange("[1.0.0,2.0.0)"), null, false, false), // + MetadataFactory.createRequiredCapability("org.eclipse.equinox.p2.localization", "df_LT", new VersionRange("[1.0.0,2.0.0)"), null, false, false)// + }; + CapabilityQuery capabilityQuery = new CapabilityQuery(capabilities); + PredicateQuery predicateQuery = new PredicateQuery("$0.all(rq | item ~= rq)", capabilities); + Collector result; + long tradQueryMS = 0; + long exprQueryMS = 0; + + for (int i = 0; i < 10; ++i) { + long start = System.currentTimeMillis(); + for (int idx = 0; idx < 100; ++idx) { + result = repo.query(capabilityQuery, new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 446); + } + tradQueryMS += (System.currentTimeMillis() - start); + + start = System.currentTimeMillis(); + for (int idx = 0; idx < 100; ++idx) { + result = repo.query(predicateQuery, new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 446); + } + exprQueryMS += (System.currentTimeMillis() - start); + } + System.out.println("CapabilityQuery took: " + tradQueryMS + " milliseconds"); + System.out.println("PredicateQuery took: " + exprQueryMS + " milliseconds"); + + // Assert that expression query is not worse off then 4 / 3 ratio (should typically + // be better then that. + assertTrue(tradQueryMS * 4 > exprQueryMS * 3); + } + + public void testIUPropertyQueryPerformance() throws Exception { + + IMetadataRepository repo = getMDR("/testData/galileoM7"); + + IUPropertyQuery propertyQuery = new IUPropertyQuery("df_LT.providerName", "Eclipse.org"); + PredicateQuery predicateQuery = new PredicateQuery("properties[$0] == $1", "df_LT.providerName", "Eclipse.org"); + Collector result; + long tradQueryMS = 0; + long exprQueryMS = 0; + + for (int i = 0; i < 10; ++i) { + long start = System.currentTimeMillis(); + for (int idx = 0; idx < 100; ++idx) { + result = repo.query(propertyQuery, new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 965); + } + tradQueryMS += (System.currentTimeMillis() - start); + + start = System.currentTimeMillis(); + for (int idx = 0; idx < 100; ++idx) { + result = repo.query(predicateQuery, new Collector(), new NullProgressMonitor()); + assertEquals(result.size(), 965); + } + exprQueryMS += (System.currentTimeMillis() - start); + } + System.out.println("IUPropertyQuery took: " + tradQueryMS + " milliseconds"); + System.out.println("PredicateQuery took: " + exprQueryMS + " milliseconds"); + + // Assert that expression query is not worse off then 4 / 3 ratio (should typically + // be better then that. + assertTrue(tradQueryMS * 4 > exprQueryMS * 3); + } + + public void testSlicerPerformance() throws Exception { + Hashtable env = new Hashtable(); + env.put("osgi.os", "linux"); + env.put("osgi.ws", "gtk"); + env.put("osgi.arch", "x86"); + + IMetadataRepository repo = getMDR("/testData/galileoM7"); + Collector c = repo.query(new InstallableUnitQuery("org.eclipse.sdk.feature.group", Version.create("3.5.0.v20090423-7Q7bA7DPR-wM38__Q4iRsmx9z0KOjbpx3AbyvXd-Uq7J2")), new Collector(), new NullProgressMonitor()); + Iterator itor = c.iterator(); + assertTrue(itor.hasNext()); + IInstallableUnit[] roots = new IInstallableUnit[] {(IInstallableUnit) itor.next()}; + Slicer slicer = new Slicer(repo, env, false); + + long startTime = System.currentTimeMillis(); + IQueryable slice = slicer.slice(roots, new NullProgressMonitor()); + + c = slice.query(new MatchQuery() { + public boolean isMatch(Object value) { + return true; + } + }, new Collector(), new NullProgressMonitor()); + long slicerTime = System.currentTimeMillis() - startTime; + + assertEquals(c.size(), 411); + System.out.print("Slicer took: "); + System.out.println(slicerTime); + + IQuery query = new ExpressionQuery(// + "$0.traverse(set(), _, {requirementsCache, parent | select(" + // + "parent.requiredCapabilities.unique(requirementsCache).select(rc | rc.filter == null || $1 ~= filter(rc.filter)), _," + // + "{rcs, child | rcs.exists(rc | child ~= rc)})})", roots, env); + + startTime = System.currentTimeMillis(); + c = repo.query(query, new Collector(), new NullProgressMonitor()); + long traverseTime = System.currentTimeMillis() - startTime; + + assertEquals(c.size(), 411); + System.out.print("Traverse expression took: "); + System.out.println(traverseTime); + + // Assert that expression query is at least 3/1 ratio ratio (should typically + // be better then that. + assertTrue(traverseTime * 3 < slicerTime); + } + + private IMetadataRepository getMDR(String uri) throws Exception { + URI metadataRepo = getTestData("1.1", uri).toURI(); + + IMetadataRepositoryManager metadataManager = (IMetadataRepositoryManager) ServiceHelper.getService(Activator.getContext(), IMetadataRepositoryManager.SERVICE_NAME); + assertNotNull(metadataManager); + + return metadataManager.loadRepository(metadataRepo, new NullProgressMonitor()); + } +} diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/TestQueryReimplementation.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/TestQueryReimplementation.java new file mode 100644 index 000000000..4099f6d32 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ql/TestQueryReimplementation.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2009 Cloudsmith Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Cloudsmith Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.p2.tests.ql; + +import org.eclipse.equinox.internal.p2.ql.ExpressionParser; +import org.eclipse.equinox.internal.p2.ql.ItemExpression; +import org.eclipse.equinox.internal.provisional.p2.metadata.*; +import org.eclipse.equinox.internal.provisional.p2.metadata.query.Collector; +import org.eclipse.equinox.p2.ql.PredicateQuery; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; +import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; + +public class TestQueryReimplementation extends AbstractProvisioningTest { + + public static class UpdateQuery extends PredicateQuery { + private static final ItemExpression expr1; + private static final ItemExpression expr2; + + static { + ExpressionParser parser = new ExpressionParser(); + + // This expression is used in case the updateFrom is an IInstallableUnitPatch + // + expr1 = parser.parsePredicate("$0 ~= updateDescriptor && ($0.id != id || $0.version < version)"); + + // When updateFrom is not an IInstallableUnitPatch, we need to do one of two things depending + // on if the current item is an InstallableUnitPatch or not. + // + expr2 = parser.parsePredicate("item ~= class('org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnitPatch')" + // + "? $0 ~= lifeCycle" + // + ": $0 ~= updateDescriptor && ($0.id != id || $0.version < version)"); + } + + public UpdateQuery(IInstallableUnit updateFrom) { + super(IInstallableUnit.class, updateFrom instanceof IInstallableUnitPatch ? expr1 : expr2, new Object[] {updateFrom, IInstallableUnitPatch.class}); + } + } + + public static class IUPropertyQuery extends PredicateQuery { + private static final ItemExpression expr = new ExpressionParser().parsePredicate("properties[$0] == $1"); + + public IUPropertyQuery(String propertyName, String propertyValue) { + super(IInstallableUnit.class, expr, new Object[] {propertyName, propertyValue}); + } + } + + public static class InstallableUnitQuery extends PredicateQuery { + /** + * A convenience query that will match any {@link IInstallableUnit} + * it encounters. + */ + public static final PredicateQuery ANY = new PredicateQuery(""); + + private static final ItemExpression idVersionQuery; + private static final ItemExpression idRangeQuery; + + static { + ExpressionParser parser = new ExpressionParser(); + idVersionQuery = parser.parsePredicate("($0 == null || $0 == id) && ($1 == null || $1 == version)"); + idRangeQuery = parser.parsePredicate("($0 == null || $0 == id) && ($1 == null || version ~= $1)"); + } + + /** + * Creates a query that will match any {@link IInstallableUnit} with the given + * id, regardless of version. + * + * @param id The installable unit id to match, or null to match any id + */ + public InstallableUnitQuery(String id) { + this(id, (Version) null); + } + + /** + * Creates a query that will match any {@link IInstallableUnit} with the given + * id, and whose version falls in the provided range. + * + * @param id The installable unit id to match, or null to match any id + * @param range The version range to match + */ + public InstallableUnitQuery(String id, VersionRange range) { + super(IInstallableUnit.class, idRangeQuery, new Object[] {id, range}); + } + + /** + * Creates a query that will match any {@link IInstallableUnit} with the given + * id and version. + * + * @param id The installable unit id to match, or null to match any id + * @param version The precise version that a matching unit must have + */ + public InstallableUnitQuery(String id, Version version) { + super(IInstallableUnit.class, idVersionQuery, new Object[] {id, version}); + } + + /** + * Creates a query that will match any {@link IInstallableUnit} with the given + * id and version. + * + * @param versionedId The precise id/version combination that a matching unit must have + */ + public InstallableUnitQuery(IVersionedId versionedId) { + this(versionedId.getId(), versionedId.getVersion()); + } + } + + /** + * A query that searches for {@link IInstallableUnit} instances that provide + * capabilities that match one or more required capabilities. + */ + public static class CapabilityQuery extends PredicateQuery { + private static final ItemExpression oneCapabilityQuery; + private static final ItemExpression anyCapabilityQuery; + + static { + ExpressionParser parser = new ExpressionParser(); + oneCapabilityQuery = parser.parsePredicate("item ~= $1"); + anyCapabilityQuery = parser.parsePredicate("$1.exists(x | item ~= x)"); + } + + /** + * Creates a new query on the given required capability. + * @param required The required capability + */ + public CapabilityQuery(IRequiredCapability required) { + super(oneCapabilityQuery, new Object[] {required}); + } + + /** + * Creates a new query on the given required capabilities. The installable + * unit must provide capabilities that match all of the given required capabilities + * for this query to be satisfied. + * @param required The required capabilities + */ + public CapabilityQuery(IRequiredCapability[] required) { + super(anyCapabilityQuery, new Object[] {required}); + } + } + + private IInstallableUnit a1; + private IInstallableUnit updateOfA; + private IInstallableUnit a11; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + a1 = createIU("A", Version.create("2.0.0")); + IUpdateDescriptor update = MetadataFactory.createUpdateDescriptor("A", new VersionRange("[2.0.0, 2.0.0]"), 0, "update description"); + updateOfA = createIU("UpdateA", Version.createOSGi(1, 0, 0), null, NO_REQUIRES, NO_PROVIDES, NO_PROPERTIES, null, NO_TP_DATA, false, update, NO_REQUIRES); + a11 = createIUUpdate(); + } + + public void testUpdateWithDifferentId() { + IMetadataRepository repo = createTestMetdataRepository(new IInstallableUnit[] {a1, updateOfA}); + Collector c = repo.query(new UpdateQuery(a1), new Collector(), null); + assertEquals(1, c.size()); + assertEquals(updateOfA, c.iterator().next()); + } + + public void testWithSuperiorVersion() { + IMetadataRepository repo2 = createTestMetdataRepository(new IInstallableUnit[] {a11, a1}); + Collector c2 = repo2.query(new UpdateQuery(a1), new Collector(), null); + assertEquals(1, c2.size()); + assertEquals(a11, c2.iterator().next()); + } + + private IInstallableUnit createIUUpdate() { + return createIU("A", Version.create("2.1.0"), null, NO_REQUIRES, NO_PROVIDES, NO_PROPERTIES, ITouchpointType.NONE, NO_TP_DATA, false, MetadataFactory.createUpdateDescriptor("A", new VersionRange("[2.0.0, 2.1.0]"), 0, "update description"), null); + } +} \ No newline at end of file -- cgit v1.2.3