blob: 14e98c9d4ceea0b7be3aafd88e83aebda0672044 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2014 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* 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);
}
}