/******************************************************************************* * Copyright (c) 2008, 2010 VMware Inc. * 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: * VMware Inc. - initial contribution *******************************************************************************/ package org.eclipse.virgo.kernel.userregion.internal.importexpansion; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Assert; import org.junit.Test; import org.eclipse.virgo.kernel.osgi.framework.ImportMergeException; import org.eclipse.virgo.kernel.userregion.internal.importexpansion.StandardTrackedPackageImportsFactory; import org.eclipse.virgo.kernel.userregion.internal.importexpansion.TrackedPackageImports; import org.eclipse.virgo.kernel.userregion.internal.importexpansion.TrackedPackageImportsFactory; import org.eclipse.virgo.util.osgi.manifest.VersionRange; import org.eclipse.virgo.util.osgi.manifest.BundleManifest; import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory; import org.eclipse.virgo.util.osgi.manifest.ImportedPackage; import org.eclipse.virgo.util.osgi.manifest.Resolution; /** */ public class TrackedPackageImportsTests { private static final String TEST_SOURCE = "test source"; private final TrackedPackageImportsFactory trackedPackageImportsFactory = new StandardTrackedPackageImportsFactory(); @Test public void testTrivialMerge() throws ImportMergeException, IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader("bundle-symbolicname: A\nimport-package: p")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader("bundle-symbolicname: B\nimport-package: p")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); TrackedPackageImports empty = this.trackedPackageImportsFactory.createEmpty(); Assert.assertTrue(empty.isEmpty()); Assert.assertFalse(tpiB.isEmpty()); Assert.assertTrue(tpiA.isEquivalent(tpiB)); Assert.assertFalse(tpiA.isEquivalent(empty)); tpiB.merge(tpiA); tpiB.merge(empty); Map<String, ImportedPackage> mergedImports = convertImportedPackageListToMap(tpiB.getMergedImports()); ImportedPackage pImport = mergedImports.get("p"); Assert.assertNotNull("Missing merged import", pImport); } @Test public void testOverlappingVersionRanges() throws ImportMergeException, IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;version=\"[1,3]\"")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;version=\"2\"")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); tpiB.merge(tpiA); Map<String, ImportedPackage> mergedImports = convertImportedPackageListToMap(tpiB.getMergedImports()); ImportedPackage pImport = mergedImports.get("p"); Assert.assertNotNull("Missing merged import", pImport); VersionRange v = new VersionRange(pImport.getAttributes().get("version")); Assert.assertTrue("Incorrectly merged version", v.isFloorInclusive() && v.isCeilingInclusive() && v.getFloor().getMajor() == 2 && v.getCeiling().getMajor() == 3); } @Test public void testDisjointVersionRanges() throws IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;version=\"[1,2]\"")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;version=\"[3,4]\"")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); try { tpiB.merge(tpiA); Assert.assertTrue("Exception should be thrown", false); } catch (ImportMergeException e) { System.out.println(e); Assert.assertEquals("Incorrect conflicting package name", "p", e.getConflictingPackageName()); Assert.assertEquals("Incorrect sources", "bundle B, bundle A", e.getSources()); } } @Test public void testOverlappingBundleVersionRanges() throws ImportMergeException, IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;bundle-version=\"[1,3]\"")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;bundle-version=\"2\"")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); tpiB.merge(tpiA); Map<String, ImportedPackage> mergedImports = convertImportedPackageListToMap(tpiB.getMergedImports()); ImportedPackage pImport = mergedImports.get("p"); Assert.assertNotNull("Missing merged import", pImport); VersionRange v = new VersionRange(pImport.getAttributes().get("bundle-version")); Assert.assertTrue("Incorrectly merged version", v.isFloorInclusive() && v.isCeilingInclusive() && v.getFloor().getMajor() == 2 && v.getCeiling().getMajor() == 3); } @Test public void testDisjointBundleVersionRanges() throws IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;bundle-version=\"[1,2]\"")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;bundle-version=\"[3,4]\"")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); try { tpiB.merge(tpiA); Assert.assertTrue("Exception should be thrown", false); } catch (ImportMergeException e) { System.out.println(e); Assert.assertEquals("Incorrect conflicting package name", "p", e.getConflictingPackageName()); Assert.assertEquals("Incorrect sources", "bundle B, bundle A", e.getSources()); } } @Test public void testResolution() throws ImportMergeException, IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;resolution:=optional")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;resolution:=mandatory")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); tpiB.merge(tpiA); Map<String, ImportedPackage> mergedImports = convertImportedPackageListToMap(tpiB.getMergedImports()); ImportedPackage pImport = mergedImports.get("p"); Assert.assertNotNull("Missing merged import", pImport); Assert.assertTrue("Incorrectly merged resolution", pImport.getResolution() == Resolution.MANDATORY); } @Test public void testConsistentAttributes() throws ImportMergeException, IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;a1=v1;a2=v2")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;a1=v1;a3=v3")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); tpiB.merge(tpiA); Map<String, ImportedPackage> mergedImports = convertImportedPackageListToMap(tpiB.getMergedImports()); ImportedPackage pImport = mergedImports.get("p"); Assert.assertNotNull("Missing merged import", pImport); Map<String, String> pAttrs = pImport.getAttributes(); Assert.assertEquals("Incorrectly merged attribute for a1", "v1", pAttrs.get("a1")); Assert.assertEquals("Incorrectly merged attribute for a2", "v2", pAttrs.get("a2")); Assert.assertEquals("Incorrectly merged attribute for a3", "v3", pAttrs.get("a3")); } @Test public void testInconsistentAttributes() throws ImportMergeException, IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader("bundle-symbolicname: A\nimport-package: p;a1=v1")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader("bundle-symbolicname: B\nimport-package: p;a1=v2")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); BundleManifest manifestC = BundleManifestFactory.createBundleManifest(new StringReader("bundle-symbolicname: C\nimport-package: q")); TrackedPackageImports tpiC = this.trackedPackageImportsFactory.create(manifestC); tpiB.merge(tpiC); try { tpiB.merge(tpiA); Assert.assertTrue("Exception should be thrown", false); } catch (ImportMergeException e) { System.out.println(e); Assert.assertEquals("Incorrect conflicting package name", "p", e.getConflictingPackageName()); Assert.assertEquals("Incorrect sources", "bundle B, bundle A", e.getSources()); } } @Test public void testTrivialAddition() throws ImportMergeException, IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader("bundle-symbolicname: A\nimport-package: p")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); ImportedPackage packageImport = BundleManifestFactory.createBundleManifest().getImportPackage().addImportedPackage("p"); List<ImportedPackage> packageImports = new ArrayList<ImportedPackage>(); packageImports.add(packageImport); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(packageImports, TEST_SOURCE); tpiA.merge(tpiB); Map<String, ImportedPackage> mergedImports = convertImportedPackageListToMap(tpiA.getMergedImports()); ImportedPackage pImport = mergedImports.get("p"); Assert.assertNotNull("Missing merged import", pImport); } @Test public void testClashingAddition() throws IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;attr=x")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); ImportedPackage packageImport = BundleManifestFactory.createBundleManifest().getImportPackage().addImportedPackage("p"); packageImport.getAttributes().put("attr", "y"); List<ImportedPackage> packageImports = new ArrayList<ImportedPackage>(); packageImports.add(packageImport); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(packageImports, TEST_SOURCE); try { tpiA.merge(tpiB); Assert.assertTrue("Exception should be thrown", false); } catch (ImportMergeException e) { System.out.println(e); Assert.assertEquals("Incorrect conflicting package name", "p", e.getConflictingPackageName()); Assert.assertEquals("Incorrect sources", "bundle A, " + TEST_SOURCE, e.getSources()); } } @Test public void testOverlappingVersionRangesInCollection() throws ImportMergeException, IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;version=\"[1,3]\"")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;version=\"2\"")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); TrackedPackageImports tpiC = this.trackedPackageImportsFactory.createCollector(); tpiC.merge(tpiB); tpiC.merge(tpiA); Map<String, ImportedPackage> mergedImports = convertImportedPackageListToMap(tpiC.getMergedImports()); ImportedPackage pImport = mergedImports.get("p"); Assert.assertNotNull("Missing merged import", pImport); VersionRange v = new VersionRange(pImport.getAttributes().get("version")); Assert.assertTrue("Incorrectly merged version", v.isFloorInclusive() && v.isCeilingInclusive() && v.getFloor().getMajor() == 2 && v.getCeiling().getMajor() == 3); } @Test public void testDisjointVersionRangesInCollection() throws IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;version=\"[1,2]\"")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;version=\"[3,4]\"")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); TrackedPackageImports tpiC = this.trackedPackageImportsFactory.createCollector(); try { tpiC.merge(tpiB); tpiC.merge(tpiA); Assert.assertTrue("Exception should be thrown", false); } catch (ImportMergeException e) { System.out.println(e); Assert.assertEquals("Incorrect conflicting package name", "p", e.getConflictingPackageName()); Assert.assertEquals("Incorrect sources", "bundle B, bundle A", e.getSources()); } } @Test public void testThreeWayClash() throws IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;version=\"[1,2]\"")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;version=\"[2,3]\"")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); TrackedPackageImports tpiC = this.trackedPackageImportsFactory.createCollector(); BundleManifest manifestD = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: D\nimport-package: p;version=\"[3,3]\"")); TrackedPackageImports tpiD = this.trackedPackageImportsFactory.create(manifestD); try { tpiC.merge(tpiB); tpiC.merge(tpiA); tpiD.merge(tpiC); Assert.assertTrue("Exception should be thrown", false); } catch (ImportMergeException e) { System.out.println(e); Assert.assertEquals("Incorrect conflicting package name", "p", e.getConflictingPackageName()); /* * Note that in a N-way clash of version ranges, there must be a pair of version ranges that clash, but the * current implementation simply reports all N. */ Assert.assertEquals("Incorrect sources", "bundle D, bundle B, bundle A", e.getSources()); } } @Test public void testThreeWayNestedClash() throws IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;version=\"[1,2]\"")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;version=\"[2,3]\"")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); BundleManifest manifestD = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: D\nimport-package: p;version=\"[3,3]\"")); TrackedPackageImports tpiD = this.trackedPackageImportsFactory.create(manifestD); TrackedPackageImports tpiContainer = this.trackedPackageImportsFactory.createContainer("container"); try { tpiContainer.merge(tpiA); tpiContainer.merge(tpiB); tpiD.merge(tpiContainer); Assert.assertTrue("Exception should be thrown", false); } catch (ImportMergeException e) { System.out.println(e); Assert.assertEquals("Incorrect conflicting package name", "p", e.getConflictingPackageName()); /* * Note that in a N-way clash of version ranges, there must be a pair of version ranges that clash, but the * current implementation simply reports all N. */ Assert.assertEquals("Incorrect sources", "bundle D, container(bundle A, bundle B)", e.getSources()); } } @Test public void testFourWayNestedClashInACollector() throws IOException { BundleManifest manifestA = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: A\nimport-package: p;version=\"[1,2]\"")); TrackedPackageImports tpiA = this.trackedPackageImportsFactory.create(manifestA); BundleManifest manifestB = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: B\nimport-package: p;version=\"[2,3]\"")); TrackedPackageImports tpiB = this.trackedPackageImportsFactory.create(manifestB); BundleManifest manifestC = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: C\nimport-package: p;version=\"[3,4]\"")); TrackedPackageImports tpiC = this.trackedPackageImportsFactory.create(manifestC); BundleManifest manifestD = BundleManifestFactory.createBundleManifest(new StringReader( "bundle-symbolicname: D\nimport-package: p;version=\"[4,5]\"")); TrackedPackageImports tpiD = this.trackedPackageImportsFactory.create(manifestD); TrackedPackageImports tpiContainerX = this.trackedPackageImportsFactory.createContainer("containerX"); TrackedPackageImports tpiContainerY = this.trackedPackageImportsFactory.createContainer("containerY"); TrackedPackageImports tpiCollector = this.trackedPackageImportsFactory.createCollector(); try { tpiContainerX.merge(tpiA); tpiContainerX.merge(tpiB); tpiContainerY.merge(tpiC); tpiContainerY.merge(tpiD); tpiCollector.merge(tpiContainerX); tpiCollector.merge(tpiContainerY); Assert.assertTrue("Exception should be thrown", false); } catch (ImportMergeException e) { System.out.println(e); Assert.assertEquals("Incorrect conflicting package name", "p", e.getConflictingPackageName()); /* * Note that in a N-way clash of version ranges, there must be a pair of version ranges that clash, but the * current implementation simply reports all N. */ Assert.assertEquals("Incorrect sources", "containerX(bundle A, bundle B), containerY(bundle C, bundle D)", e.getSources()); } } /** * Convert a given list of package imports with no duplicate package names to a map of package name to * {@link ImportedPackage}. * * @param importedPackages a list of <code>PackageImport</code> * @return a map of package name to <code>PackageImport</code> */ private static Map<String, ImportedPackage> convertImportedPackageListToMap(List<ImportedPackage> importedPackages) { Map<String, ImportedPackage> initialPackageImports = new HashMap<String, ImportedPackage>(); for (ImportedPackage importedPackage : importedPackages) { Assert.assertNull(initialPackageImports.put(importedPackage.getPackageName(), importedPackage)); } return initialPackageImports; } }