/******************************************************************************* * Copyright (c) 2013, 2014 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.osgi.tests.container; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.*; import org.eclipse.osgi.container.Module; import org.eclipse.osgi.container.ModuleContainer; import org.eclipse.osgi.report.resolution.ResolutionReport; import org.eclipse.osgi.tests.container.dummys.*; import org.junit.Test; import org.osgi.framework.Constants; import org.osgi.framework.namespace.PackageNamespace; import org.osgi.framework.wiring.BundleRevision; import org.osgi.framework.wiring.FrameworkWiring; import org.osgi.resource.*; public class ResolutionReportTest extends AbstractTest { // TODO Add test for dynamic resolution in conjunction with UNRESOLVED_PROVIDER entries. @Test public void testResolutionReportListenerService() throws Exception { DummyResolverHook hook = new DummyResolverHook(); registerService(org.osgi.framework.hooks.resolver.ResolverHookFactory.class, new DummyResolverHookFactory(hook)); getSystemBundle().adapt(FrameworkWiring.class).resolveBundles(Collections.singleton(getSystemBundle())); assertEquals("No resolution report listener callback", 1, hook.getResolutionReports().size()); assertNotNull("Resolution report was null", hook.getResolutionReports().get(0)); } @Test public void testResolutionReportListenerModule() throws Exception { DummyResolverHook hook = new DummyResolverHook(); DummyContainerAdaptor adaptor = createDummyAdaptor(hook); ModuleContainer container = adaptor.getContainer(); Module systemBundle = installDummyModule("system.bundle.MF", Constants.SYSTEM_BUNDLE_LOCATION, container); container.resolve(Arrays.asList(systemBundle), true); assertEquals("No resolution report listener callback", 1, hook.getResolutionReports().size()); assertNotNull("Resolution report was null", hook.getResolutionReports().get(0)); } @Test public void testResolutionReportEntryFilteredByResolverHook() throws Exception { DummyResolverHook hook = new DummyResolverHook() { @Override public void filterResolvable(Collection<BundleRevision> candidates) { candidates.clear(); } }; DummyContainerAdaptor adaptor = createDummyAdaptor(hook); ModuleContainer container = adaptor.getContainer(); Module module = installDummyModule("resolution.report.a.MF", "resolution.report.a", container); assertResolutionDoesNotSucceed(container, Arrays.asList(module)); ResolutionReport report = hook.getResolutionReports().get(0); Map<Resource, List<ResolutionReport.Entry>> resourceToEntries = report.getEntries(); assertResolutionReportEntriesSize(resourceToEntries, 1); List<ResolutionReport.Entry> entries = resourceToEntries.get(module.getCurrentRevision()); assertResolutionReportEntriesSize(entries, 1); ResolutionReport.Entry entry = entries.get(0); assertResolutionReportEntryTypeFilteredByResolverHook(entry.getType()); assertResolutionReportEntryDataNull(entry.getData()); } @Test public void testResolutionReportEntrySingletonSelectionNoneResolved() throws Exception { DummyResolverHook hook = new DummyResolverHook(); DummyContainerAdaptor adaptor = createDummyAdaptor(hook); ModuleContainer container = adaptor.getContainer(); Module resolutionReporta = installDummyModule("resolution.report.a.MF", "resolution.report.a", container); Module resolutionReportaV1 = installDummyModule("resolution.report.a.v1.MF", "resolution.report.a.v1", container); assertResolutionDoesNotSucceed(container, Arrays.asList(resolutionReporta, resolutionReportaV1)); ResolutionReport report = hook.getResolutionReports().get(0); Map<Resource, List<ResolutionReport.Entry>> resourceToEntries = report.getEntries(); assertResolutionReportEntriesSize(resourceToEntries, 1); List<ResolutionReport.Entry> entries = resourceToEntries.get(resolutionReporta.getCurrentRevision()); assertResolutionReportEntriesSize(entries, 1); ResolutionReport.Entry entry = entries.get(0); assertResolutionReportEntryTypeSingletonSelection(entry.getType()); assertResolutionReportEntryDataNotNull(entry.getData()); } @Test public void testResolutionReportEntrySingletonSelectionHighestVersionResolved() throws Exception { DummyResolverHook hook = new DummyResolverHook(); DummyContainerAdaptor adaptor = createDummyAdaptor(hook); ModuleContainer container = adaptor.getContainer(); Module resolutionReporta = installDummyModule("resolution.report.a.MF", "resolution.report.a", container); Module resolutionReportaV1 = installDummyModule("resolution.report.a.v1.MF", "resolution.report.a.v1", container); container.resolve(Arrays.asList(resolutionReportaV1), true); clearResolutionReports(hook); assertResolutionDoesNotSucceed(container, Arrays.asList(resolutionReporta)); ResolutionReport report = hook.getResolutionReports().get(0); Map<Resource, List<ResolutionReport.Entry>> resourceToEntries = report.getEntries(); assertResolutionReportEntriesSize(resourceToEntries, 1); List<ResolutionReport.Entry> entries = resourceToEntries.get(resolutionReporta.getCurrentRevision()); assertResolutionReportEntriesSize(entries, 1); ResolutionReport.Entry entry = entries.get(0); assertResolutionReportEntryTypeSingletonSelection(entry.getType()); assertResolutionReportEntryDataNotNull(entry.getData()); } @Test public void testResolutionReportEntrySingletonSelectionLowestVersionResolved() throws Exception { DummyResolverHook hook = new DummyResolverHook(); DummyContainerAdaptor adaptor = createDummyAdaptor(hook); ModuleContainer container = adaptor.getContainer(); Module resolutionReporta = installDummyModule("resolution.report.a.MF", "resolution.report.a", container); container.resolve(Arrays.asList(resolutionReporta), true); clearResolutionReports(hook); Module resolutionReportaV1 = installDummyModule("resolution.report.a.v1.MF", "resolution.report.a.v1", container); assertResolutionDoesNotSucceed(container, Arrays.asList(resolutionReportaV1)); ResolutionReport report = hook.getResolutionReports().get(0); Map<Resource, List<ResolutionReport.Entry>> resourceToEntries = report.getEntries(); assertResolutionReportEntriesSize(resourceToEntries, 1); List<ResolutionReport.Entry> entries = resourceToEntries.get(resolutionReportaV1.getCurrentRevision()); assertResolutionReportEntriesSize(entries, 1); ResolutionReport.Entry entry = entries.get(0); assertResolutionReportEntryTypeSingletonSelection(entry.getType()); assertResolutionReportEntryDataNotNull(entry.getData()); } @Test public void testResolutionReportEntryMissingCapability() throws Exception { DummyResolverHook hook = new DummyResolverHook(); DummyContainerAdaptor adaptor = createDummyAdaptor(hook); ModuleContainer container = adaptor.getContainer(); Module resolutionReportB = installDummyModule("resolution.report.b.MF", "resolution.report.b", container); assertResolutionDoesNotSucceed(container, Arrays.asList(resolutionReportB)); ResolutionReport report = hook.getResolutionReports().get(0); Map<Resource, List<ResolutionReport.Entry>> resourceToEntries = report.getEntries(); assertResolutionReportEntriesSize(resourceToEntries, 1); List<ResolutionReport.Entry> entries = resourceToEntries.get(resolutionReportB.getCurrentRevision()); assertResolutionReportEntriesSize(entries, 1); ResolutionReport.Entry entry = entries.get(0); assertResolutionReportEntryTypeMissingCapability(entry.getType()); assertResolutionReportEntryDataMissingCapability(entry.getData(), "osgi.wiring.package", "resolution.report.a"); } @Test public void testResolutionReportEntryUnresolvedProvider01() throws Exception { DummyResolverHook hook = new DummyResolverHook(); DummyContainerAdaptor adaptor = createDummyAdaptor(hook); ModuleContainer container = adaptor.getContainer(); Module resolutionReportC = installDummyModule("resolution.report.c.MF", "resolution.report.c", container); Module resolutionReportD = installDummyModule("resolution.report.d.MF", "resolution.report.d", container); assertResolutionDoesNotSucceed(container, Arrays.asList(resolutionReportC, resolutionReportD)); ResolutionReport report = hook.getResolutionReports().get(0); Map<Resource, List<ResolutionReport.Entry>> resourceToEntries = report.getEntries(); assertResolutionReportEntriesSize(resourceToEntries, 2); List<ResolutionReport.Entry> entries = resourceToEntries.get(resolutionReportC.getCurrentRevision()); assertResolutionReportEntriesSize(entries, 1); ResolutionReport.Entry entry = entries.get(0); assertResolutionReportEntryTypeUnresolvedProvider(entry.getType()); assertResolutionReportEntryDataUnresolvedProvider(entry.getData(), new UnresolvedProviderEntryBuilder().requirement(resolutionReportC.getCurrentRevision().getRequirements("resolution.report.d").get(0)).capability(resolutionReportD.getCurrentRevision().getCapabilities("resolution.report.d").get(0)).build()); entries = resourceToEntries.get(resolutionReportD.getCurrentRevision()); assertResolutionReportEntriesSize(entries, 1); entry = entries.get(0); assertResolutionReportEntryTypeMissingCapability(entry.getType()); assertResolutionReportEntryDataMissingCapability(entry.getData(), "does.not.exist", null); } @Test public void testResolutionReportEntryUnresolvedProvider02() throws Exception { DummyResolverHook hook = new DummyResolverHook(); DummyContainerAdaptor adaptor = createDummyAdaptor(hook); ModuleContainer container = adaptor.getContainer(); Module resolutionReportE = installDummyModule("resolution.report.e.MF", "resolution.report.e", container); Module resolutionReportF = installDummyModule("resolution.report.f.MF", "resolution.report.f", container); Module resolutionReportG = installDummyModule("resolution.report.g.MF", "resolution.report.g", container); assertResolutionSucceeds(container, Arrays.asList(resolutionReportG, resolutionReportE, resolutionReportF)); ResolutionReport report = hook.getResolutionReports().get(0); Map<Resource, List<ResolutionReport.Entry>> resourceToEntries = report.getEntries(); assertResolutionReportEntriesSize(resourceToEntries, 2); List<ResolutionReport.Entry> entries = resourceToEntries.get(resolutionReportG.getCurrentRevision()); assertResolutionReportEntriesSize(entries, 1); ResolutionReport.Entry entry = entries.get(0); assertResolutionReportEntryTypeUnresolvedProvider(entry.getType()); assertResolutionReportEntryDataUnresolvedProvider(entry.getData(), new UnresolvedProviderEntryBuilder().requirement(resolutionReportG.getCurrentRevision().getRequirements(PackageNamespace.PACKAGE_NAMESPACE).get(1)).capability(resolutionReportF.getCurrentRevision().getCapabilities(PackageNamespace.PACKAGE_NAMESPACE).get(0)).build()); entries = resourceToEntries.get(resolutionReportF.getCurrentRevision()); assertResolutionReportEntriesSize(entries, 1); entry = entries.get(0); assertResolutionReportEntryTypeMissingCapability(entry.getType()); assertResolutionReportEntryDataMissingCapability(entry.getData(), "does.not.exist", null); } private void clearResolutionReports(DummyResolverHook hook) { hook.getResolutionReports().clear(); } // TODO Need to test both mandatory and optional triggers. private void assertResolutionDoesNotSucceed(ModuleContainer container, Collection<Module> modules) { ResolutionReport report = container.resolve(modules, true); assertNotNull("Resolution should not have succeeded", report.getResolutionException()); } private void assertResolutionSucceeds(ModuleContainer container, Collection<Module> modules) { ResolutionReport report = container.resolve(modules, false); assertNull("Unexpected resolution exception", report.getResolutionException()); } private void assertResolutionReportEntriesNotNull(Map<Resource, List<ResolutionReport.Entry>> entries) { assertNotNull("Resolution report entries was null", entries); } private void assertResolutionReportEntriesSize(Map<Resource, List<ResolutionReport.Entry>> entries, int expected) { assertResolutionReportEntriesNotNull(entries); assertEquals("Wrong number of total resolution report entries", expected, entries.size()); } private void assertResolutionReportEntriesNotNull(List<ResolutionReport.Entry> entries) { assertNotNull("Resolution report entries for resource was null", entries); } private void assertResolutionReportEntriesSize(List<ResolutionReport.Entry> entries, int expected) { assertResolutionReportEntriesNotNull(entries); assertEquals("Wrong number of resolution report entries", expected, entries.size()); } private void assertResolutionReportEntryDataNotNull(Object data) { assertNotNull("No resolution report entry data", data); } private void assertResolutionReportEntryDataNull(Object data) { assertEquals("Unexpected resolution report entry data", null, data); } private void assertResolutionReportEntryTypeFilteredByResolverHook(ResolutionReport.Entry.Type type) { assertResolutionReportEntryType(ResolutionReport.Entry.Type.FILTERED_BY_RESOLVER_HOOK, type); } private void assertResolutionReportEntryTypeSingletonSelection(ResolutionReport.Entry.Type type) { assertResolutionReportEntryType(ResolutionReport.Entry.Type.SINGLETON_SELECTION, type); } private void assertResolutionReportEntryTypeUnresolvedProvider(ResolutionReport.Entry.Type type) { assertResolutionReportEntryType(ResolutionReport.Entry.Type.UNRESOLVED_PROVIDER, type); } private void assertResolutionReportEntryDataMissingCapability(Object data, String namespace, String namespaceValue) { assertResolutionReportEntryDataNotNull(data); assertTrue("Wrong resolution report entry data type", data instanceof Requirement); Requirement requirement = (Requirement) data; assertEquals("Wrong requirement namespace", namespace, requirement.getNamespace()); if (namespaceValue == null) return; assertTrue("Wrong requirement namespace value", requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE).contains(namespace + "=" + namespaceValue)); } @SuppressWarnings("unchecked") private void assertResolutionReportEntryDataUnresolvedProvider(Object data, Map<Requirement, List<Capability>> expected) { assertResolutionReportEntryDataNotNull(data); assertTrue("Wrong resolution report entry data type", data instanceof Map); Map<Requirement, Set<Capability>> unresolvedProviders = (Map<Requirement, Set<Capability>>) data; assertEquals("Wrong number of unresolved providers", expected.size(), unresolvedProviders.size()); for (Map.Entry<Requirement, List<Capability>> entry : expected.entrySet()) { Set<Capability> actualCapabilities = unresolvedProviders.get(entry.getKey()); assertEquals("Wrong number of capabilities", entry.getValue().size(), actualCapabilities.size()); for (Capability c : entry.getValue()) { assertTrue("Capability not found", actualCapabilities.contains(c)); } } } private void assertResolutionReportEntryTypeMissingCapability(ResolutionReport.Entry.Type type) { assertResolutionReportEntryType(ResolutionReport.Entry.Type.MISSING_CAPABILITY, type); } private void assertResolutionReportEntryType(ResolutionReport.Entry.Type expected, ResolutionReport.Entry.Type actual) { assertEquals("Wrong resolution report entry type", expected, actual); } }