/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.karaf.features.internal.region; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.felix.resolver.ResolverImpl; import org.apache.karaf.features.FeaturesService; import org.apache.karaf.features.internal.resolver.Slf4jResolverLog; import org.apache.karaf.features.internal.service.RepositoryImpl; import org.apache.karaf.features.internal.support.TestDownloadManager; import org.junit.Test; import org.osgi.framework.namespace.IdentityNamespace; import org.osgi.framework.wiring.BundleRevision; import org.osgi.resource.Capability; import org.osgi.resource.Resource; import org.osgi.resource.Wire; import org.osgi.service.resolver.Resolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.apache.karaf.features.internal.util.MapUtils.addToMapSet; import static org.junit.Assert.assertEquals; public class FeaturesDependenciesTest { Logger logger = LoggerFactory.getLogger(FeaturesDependenciesTest.class);; Resolver resolver = new ResolverImpl(new Slf4jResolverLog(logger)); @Test public void testFeatureDependency1() throws Exception { doTestFeatureDependency( new String[] { "f1" }, new String[] { "a1/1.0.0", "b/2.0.0" } ); } @Test public void testFeatureDependency1b() throws Exception { doTestFeatureDependency( new String[] { "f1", "dep/[1.0,2.0)"}, new String[] { "a1/1.0.0", "b/1.0.0" } ); } @Test public void testFeatureDependency2() throws Exception { doTestFeatureDependency( new String[] { "f2" }, new String[] { "a1/1.0.0", "b/2.0.0" } ); } @Test public void testFeatureDependency2b() throws Exception { doTestFeatureDependency( new String[] { "f2", "dep/[1.0,2.0)"}, new String[] { "a1/1.0.0", "b/1.0.0" } ); } @Test public void testFeatureDependency3() throws Exception { doTestFeatureDependency( new String[] { "f3" }, new String[] { "a2/1.0.0" } ); } @Test public void testFeatureDependency3b() throws Exception { doTestFeatureDependency( new String[] { "f3", "dep/[1.0,2.0)"}, new String[] { "a2/1.0.0", "b/1.0.0" } ); } @Test public void testFeatureDependency4() throws Exception { doTestFeatureDependency( new String[] { "f4" }, new String[] { "a2/1.0.0", "b/2.0.0" } ); } @Test public void testFeatureDependency4b() throws Exception { doTestFeatureDependency( new String[] { "f4", "dep/[1.0,2.0)"}, new String[] { "a2/1.0.0", "b/1.0.0" } ); } @Test public void testSpring() throws Exception { doTestFeatureDependency( new String[] { "spring-dm-web"}, new String[] { "spring-osgi-core/1.2.1", "spring-core/3.2.14" } ); } @Test public void testFeatureDependencyLevel() throws Exception { doTestFeatureDependency( new String[] { "tf1" }, new String[] { "a2/1.0.0" } ); } private void doTestFeatureDependency(String[] features, String[] bundles) throws Exception { RepositoryImpl repo = new RepositoryImpl(getClass().getResource("data8/features.xml").toURI()); Map<String, Set<String>> requirements = new HashMap<String, Set<String>>(); for (String feature : features) { addToMapSet(requirements, "root", feature); } Map<String, Set<String>> expected = new HashMap<String, Set<String>>(); for (String bundle : bundles) { addToMapSet(expected, "root", bundle); } SubsystemResolver resolver = new SubsystemResolver(this.resolver, new TestDownloadManager(getClass(), "data8")); resolver.prepare(Arrays.asList(repo.getFeatures()), requirements, Collections.<String, Set<BundleRevision>>emptyMap()); resolver.resolve(Collections.<String>emptySet(), FeaturesService.DEFAULT_FEATURE_RESOLUTION_RANGE, null, null, null); verify(resolver, expected); } private void verify(SubsystemResolver resolver, Map<String, Set<String>> expected) { Map<String, Set<String>> mapping = getBundleNamesPerRegions(resolver); if (!expected.equals(mapping)) { dumpBundles(resolver); dumpWiring(resolver); assertEquals("Resolution failed", expected, mapping); } } private void dumpBundles(SubsystemResolver resolver) { System.out.println("Bundle mapping"); Map<String, Set<Resource>> bundles = resolver.getBundlesPerRegions(); for (Map.Entry<String, Set<Resource>> entry : bundles.entrySet()) { System.out.println(" " + entry.getKey()); for (Resource b : entry.getValue()) { System.out.println(" " + b); } } } private Map<String, Set<String>> getBundleNamesPerRegions(SubsystemResolver resolver) { Map<String, Set<String>> mapping = new HashMap<String, Set<String>>(); Map<String, Set<Resource>> bundles = resolver.getBundlesPerRegions(); for (Map.Entry<String,Set<Resource>> entry : bundles.entrySet()) { for (Resource r : entry.getValue()) { addToMapSet(mapping, entry.getKey(), r.toString()); } } return mapping; } private void dumpWiring(SubsystemResolver resolver) { System.out.println("Wiring"); Map<Resource, List<Wire>> wiring = resolver.getWiring(); List<Resource> resources = new ArrayList<Resource>(wiring.keySet()); Collections.sort(resources, new Comparator<Resource>() { @Override public int compare(Resource o1, Resource o2) { return getName(o1).compareTo(getName(o2)); } }); for (Resource resource : resources) { System.out.println(" " + getName(resource)); for (Wire wire : wiring.get(resource)) { System.out.println(" " + wire); } } } private String getName(Resource resource) { Capability cap = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0); return cap.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE) + ": " + cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE) + "/" + cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE); } }