/* * 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.felix.dm.itest.api; import java.util.List; import java.util.Properties; import org.apache.felix.dm.Component; import org.apache.felix.dm.ComponentDeclaration; import org.apache.felix.dm.ConfigurationDependency; import org.apache.felix.dm.Dependency; import org.apache.felix.dm.DependencyManager; import org.apache.felix.dm.ServiceDependency; import org.apache.felix.dm.context.AbstractDependency; import org.apache.felix.dm.context.DependencyContext; import org.apache.felix.dm.diagnostics.CircularDependency; import org.apache.felix.dm.diagnostics.DependencyGraph; import org.apache.felix.dm.diagnostics.DependencyGraph.ComponentState; import org.apache.felix.dm.diagnostics.DependencyGraph.DependencyState; import org.apache.felix.dm.diagnostics.MissingDependency; import org.apache.felix.dm.itest.util.TestBase; public class DiagnosticsTest extends TestBase { // there are two components (TestComponent and HelloWorldServiceFactory) created by // org.apache.felix.dm.itest.bundle // These component is always registered, so we only need to take them into // account when we build the graph with ALL components private static final int InitialComponentCount = 2; private boolean checkComponentCount(int expected, int count) { return count == expected + InitialComponentCount; } public void testWithoutComponents() throws Exception { DependencyGraph graph = DependencyGraph.getGraph( ComponentState.ALL, DependencyState.ALL); assertTrue(checkComponentCount(0, graph.getAllComponents().size())); assertTrue(graph.getAllDependencies().isEmpty()); } public void testSingleComponent() throws Exception { DependencyManager dm = getDM(); Component component = dm.createComponent() .setImplementation(Object.class); dm.add(component); DependencyGraph graph = DependencyGraph.getGraph( ComponentState.ALL, DependencyState.ALL); assertTrue(checkComponentCount(1, graph.getAllComponents().size())); assertTrue(graph.getAllDependencies().isEmpty()); graph = DependencyGraph.getGraph( ComponentState.UNREGISTERED, DependencyState.ALL_UNAVAILABLE); assertTrue(graph.getAllComponents().isEmpty()); assertTrue(graph.getAllDependencies().isEmpty()); } public void testServiceDependencyMissing() throws Exception { DependencyManager dm = getDM(); ServiceDependency serviceDependency1 = dm.createServiceDependency() .setService(S1.class) .setRequired(true); ServiceDependency serviceDependency2 = dm.createServiceDependency() .setService(S2.class) .setRequired(true); Component component1 = dm.createComponent() .setImplementation(C0.class) .add(serviceDependency1); Component component2 = dm.createComponent() .setImplementation(S1Impl1.class) .setInterface(S1.class.getName(), null) .add(serviceDependency2); dm.add(component1); dm.add(component2); DependencyGraph graph = DependencyGraph.getGraph( ComponentState.UNREGISTERED, DependencyState.REQUIRED_UNAVAILABLE); assertEquals(2, graph.getAllComponents().size()); assertEquals(2, graph.getAllDependencies().size()); List<MissingDependency> missingDependencies = graph.getMissingDependencies("service"); assertEquals(1, missingDependencies.size()); assertEquals(S2.class.getName(), missingDependencies.get(0).getName()); assertTrue(graph.getMissingDependencies("configuration").isEmpty()); assertTrue(graph.getMissingDependencies("bundle").isEmpty()); assertTrue(graph.getMissingDependencies("resource").isEmpty()); } public void testConfigurationDependencyMissing() throws Exception { DependencyManager dm = getDM(); ConfigurationDependency configurationDependency1 = dm.createConfigurationDependency() .setPid("missing.configuration.pid"); Component component1 = dm.createComponent() .setImplementation(Object.class) .add(configurationDependency1); m_dm.add(component1); DependencyGraph graph = DependencyGraph.getGraph(ComponentState.UNREGISTERED, DependencyState.REQUIRED_UNAVAILABLE); assertEquals(1, graph.getAllComponents().size()); assertEquals(1, graph.getAllDependencies().size()); List<MissingDependency> missingServiceDependencies = graph.getMissingDependencies("service"); assertTrue(missingServiceDependencies.isEmpty()); List<MissingDependency> missingConfigDependencies = graph.getMissingDependencies("configuration"); assertEquals(1, missingConfigDependencies.size()); MissingDependency missingConfigDependency = missingConfigDependencies.get(0); assertEquals("missing.configuration.pid", missingConfigDependency.getName()); } public void testProvidersWithoutProperties() throws Exception { DependencyManager dm = getDM(); ServiceDependency serviceDependency1 = dm.createServiceDependency() .setService(S1.class) .setRequired(true); Component component1 = dm.createComponent() .setImplementation(C0.class) .add(serviceDependency1); Component component2 = dm.createComponent() .setImplementation(S1Impl1.class) .setInterface(S1.class.getName(), null); Component component3 = dm.createComponent() .setImplementation(S1Impl2.class) .setInterface(S1.class.getName(), null); dm.add(component1); dm.add(component2); dm.add(component3); DependencyGraph graph = DependencyGraph.getGraph(ComponentState.ALL, DependencyState.ALL); List<ComponentDeclaration> providers = graph.getProviders(serviceDependency1); assertEquals(2, providers.size()); assertTrue(providers.contains(component2)); assertTrue(providers.contains(component3)); } public void testProvidersWithProperties() throws Exception { DependencyManager dm = getDM(); ServiceDependency serviceDependency1 = dm.createServiceDependency() .setService(S1.class, "(key=value)") .setRequired(true); Component component1 = dm.createComponent() .setImplementation(C0.class) .add(serviceDependency1); Properties component2Properties = new Properties(); component2Properties.put("key", "value"); Properties component4Properties = new Properties(); component4Properties.put("key", "otherValue"); Component component2 = dm.createComponent() .setImplementation(S1Impl1.class) .setInterface(S1.class.getName(), component2Properties); Component component3 = dm.createComponent() .setImplementation(S1Impl2.class) .setInterface(S1.class.getName(), null); Component component4 = dm.createComponent() .setImplementation(S1Impl3.class) .setInterface(S1.class.getName(), component4Properties); m_dm.add(component1); m_dm.add(component2); m_dm.add(component3); m_dm.add(component4); DependencyGraph graph = DependencyGraph.getGraph(ComponentState.ALL, DependencyState.ALL); List<ComponentDeclaration> providers = graph.getProviders(serviceDependency1); assertEquals(1, providers.size()); assertTrue(providers.contains(component2)); assertFalse(providers.contains(component3)); assertFalse(providers.contains(component4)); } public void testCircularDependencies() throws Exception { DependencyManager dm = getDM(); Component component0 = dm.createComponent() .setImplementation(C0.class) .add(dm.createServiceDependency() .setService(S1.class) .setRequired(true)); Component component1 = dm.createComponent() .setImplementation(S1Impl1.class) .setInterface(S1.class.getName(), null) .add(dm.createServiceDependency() .setService(S2.class) .setRequired(true)); Component component2 = dm.createComponent() .setImplementation(S2Impl1.class) .setInterface(S2.class.getName(), null) .add(dm.createServiceDependency() .setService(S1.class) .setRequired(true)); m_dm.add(component0); m_dm.add(component1); m_dm.add(component2); DependencyGraph graph = DependencyGraph.getGraph(ComponentState.UNREGISTERED,DependencyState.REQUIRED_UNAVAILABLE); List<CircularDependency> circularDependencies = graph.getCircularDependencies(); assertEquals(1, circularDependencies.size()); List<ComponentDeclaration> circularDependencyComponents = circularDependencies.get(0).getComponents(); assertTrue(circularDependencyComponents.contains(component1)); assertTrue(circularDependencyComponents.contains(component2)); assertFalse(circularDependencyComponents.contains(component0)); } public void testWithTwoProvidersOneUnavailable() { DependencyManager dm = getDM(); Component component0 = dm.createComponent() .setImplementation(C0.class) .add(dm.createServiceDependency() .setService(S1.class) .setRequired(true)); Component component1 = dm.createComponent() .setImplementation(S1Impl1.class) .setInterface(S1.class.getName(), null); Component component2 = dm.createComponent() .setImplementation(S1Impl2.class) .setInterface(S1.class.getName(), null) .add(dm.createServiceDependency() .setService(S2.class) .setRequired(true)); dm.add(component0); dm.add(component1); dm.add(component2); DependencyGraph graph = DependencyGraph.getGraph(ComponentState.UNREGISTERED, DependencyState.REQUIRED_UNAVAILABLE); assertEquals(1, graph.getAllComponents().size()); List<MissingDependency> missingDependencies = graph.getMissingDependencies("service"); assertEquals(1, missingDependencies.size()); MissingDependency missingDependency = missingDependencies.get(0); assertTrue(missingDependency.getName().equals(S2.class.getName())); } public void testGraphsWithSeveralComponentDependencyCombinations() throws Exception { DependencyManager dm = getDM(); Component component0 = dm.createComponent() .setImplementation(C0.class) .add(dm.createServiceDependency() .setService(S1.class) .setRequired(true)) .add(dm.createServiceDependency() .setService(S3.class) .setRequired(true)) .add(dm.createServiceDependency() .setService(S4.class) .setRequired(true)); Component component1 = dm.createComponent() .setImplementation(C1.class) .add(dm.createServiceDependency() .setService(S5.class) .setRequired(true)) .add(dm.createServiceDependency() .setService(S6.class) .setRequired(true)) .add(dm.createServiceDependency() .setService(S7.class) .setRequired(true)); Component s1Impl1 = dm.createComponent() .setImplementation(S1Impl1.class) .setInterface(S1.class.getName(), null) .add(dm.createServiceDependency() .setService(S2.class) .setRequired(true)); Component s1Impl2 = dm.createComponent() .setImplementation(S1Impl2.class) .setInterface(S1.class.getName(), null); Component s3Impl1 = dm.createComponent() .setImplementation(S3Impl1.class) .setInterface(S3.class.getName(), null) .add(dm.createConfigurationDependency() .setPid("missing.config.pid")); Component s3s4Impl = dm.createComponent() .setImplementation(S3S4Impl.class) .setInterface( new String[] {S3.class.getName(), S4.class.getName()}, null); Component s4Impl1 = dm.createComponent() .setImplementation(S4Impl1.class) .setInterface(S4.class.getName(), null); Component s5Impl1 = dm.createComponent() .setImplementation(S5Impl1.class) .setInterface(S5.class.getName(), null); Component s6s7Impl = dm.createComponent() .setImplementation(S6S7Impl.class) .setInterface( new String[] {S6.class.getName(), S7.class.getName()}, null) .add(dm.createServiceDependency() .setService(S8.class) .setRequired(true)); Component s8Impl1 = dm.createComponent() .setImplementation(S8Impl1.class) .setInterface(S8.class.getName(), null) .add(dm.createServiceDependency() .setService(S6.class) .setRequired(true)); dm.add(component0); dm.add(component1); dm.add(s1Impl1); dm.add(s1Impl2); dm.add(s3Impl1); dm.add(s3s4Impl); dm.add(s4Impl1); dm.add(s5Impl1); dm.add(s6s7Impl); dm.add(s8Impl1); // graph containing all components and dependencies DependencyGraph graph = DependencyGraph.getGraph(ComponentState.ALL, DependencyState.ALL); List<ComponentDeclaration> allComponents = graph.getAllComponents(); assertTrue(checkComponentCount(10, allComponents.size())); List<MissingDependency> missingDependencies = graph.getMissingDependencies("service"); assertEquals(1, missingDependencies.size()); missingDependencies = graph.getMissingDependencies("configuration"); assertEquals(1, missingDependencies.size()); List<CircularDependency> circularDependencies = graph.getCircularDependencies(); assertEquals(1, circularDependencies.size()); CircularDependency circularDependency = circularDependencies.get(0); assertEquals(3, circularDependency.getComponents().size()); assertTrue(circularDependency.getComponents().contains(s6s7Impl)); assertTrue(circularDependency.getComponents().contains(s8Impl1)); // graph containing unregistered components and unavailable required dependencies graph = null; graph = DependencyGraph.getGraph(ComponentState.UNREGISTERED, DependencyState.REQUIRED_UNAVAILABLE); List<ComponentDeclaration> unregComponents = graph.getAllComponents(); assertEquals(5, unregComponents.size()); assertTrue(unregComponents.contains(s1Impl1)); assertTrue(unregComponents.contains(s3Impl1)); assertTrue(unregComponents.contains(component1)); assertTrue(unregComponents.contains(s6s7Impl)); assertTrue(unregComponents.contains(s8Impl1)); assertFalse(unregComponents.contains(component0)); circularDependencies = graph.getCircularDependencies(); assertEquals(1, circularDependencies.size()); circularDependency = circularDependencies.get(0); assertEquals(3, circularDependency.getComponents().size()); assertTrue(circularDependency.getComponents().contains(s6s7Impl)); assertTrue(circularDependency.getComponents().contains(s8Impl1)); missingDependencies = graph.getMissingDependencies("service"); assertEquals(1, missingDependencies.size()); missingDependencies = graph.getMissingDependencies("configuration"); assertEquals(1, missingDependencies.size()); // call getCircularDependencies again on the same graph circularDependencies = graph.getCircularDependencies(); assertEquals(1, circularDependencies.size()); circularDependency = circularDependencies.get(0); assertEquals(3, circularDependency.getComponents().size()); assertTrue(circularDependency.getComponents().contains(s6s7Impl)); assertTrue(circularDependency.getComponents().contains(s8Impl1)); List<MissingDependency> allMissingDependencies = graph.getMissingDependencies(null); assertEquals(2, allMissingDependencies.size()); } public void testMissingCustomDependencies() { DependencyManager dm = getDM(); Component component0 = dm.createComponent() .setImplementation(C0.class) .add(dm.createServiceDependency() .setService(S1.class) .setRequired(true)) .add(dm.createServiceDependency() .setService(S2.class) .setRequired(true)); Component component1 = dm.createComponent() .setImplementation(S1Impl1.class) .setInterface(S1.class.getName(), null) .add(ToggleDependency.create()); m_dm.add(component0); m_dm.add(component1); DependencyGraph graph = DependencyGraph.getGraph(ComponentState.UNREGISTERED,DependencyState.REQUIRED_UNAVAILABLE); List<MissingDependency> missingCustomDependencies = graph.getMissingCustomDependencies(); assertEquals(1, missingCustomDependencies.size()); MissingDependency missingCustomeDependency = missingCustomDependencies.get(0); assertTrue(missingCustomeDependency.getType().equals("toggle")); assertTrue(missingCustomeDependency.getName().equals("false")); List<MissingDependency> missingDependencies = graph.getMissingDependencies("service"); assertEquals(1, missingDependencies.size()); } static interface S1 {} static interface S2 {} static interface S3 {} static interface S4 {} static interface S5 {} static interface S6 {} static interface S7 {} static interface S8 {} static class C0 { public C0() {} } static class C1 { public C1() {} } static class S1Impl1 implements S1 { public S1Impl1(){} } static class S1Impl2 implements S1 { public S1Impl2() {} } static class S1Impl3 implements S1 { public S1Impl3() {} } static class S2Impl1 implements S2 { public S2Impl1() {} } static class S3Impl1 implements S3 { public S3Impl1() {} } static class S3S4Impl implements S3, S4 { public S3S4Impl() {} } static class S4Impl1 implements S4 { public S4Impl1() {} } static class S5Impl1 implements S5 { public S5Impl1() {} } static class S6S7Impl implements S6, S7 { public S6S7Impl() {} } static class S8Impl1 implements S8 { public S8Impl1() {} } static class CA { public CA(){} } static interface ToggleDependency extends Dependency { static ToggleDependency create() { return new ToggleDependencyImpl(); } } static class ToggleDependencyImpl extends AbstractDependency<ToggleDependencyImpl> implements ToggleDependency { public ToggleDependencyImpl() { setRequired(true); } public ToggleDependencyImpl(ToggleDependencyImpl prototype) { super(prototype); } @Override public Class<?> getAutoConfigType() { return null; } @Override public DependencyContext createCopy() { return new ToggleDependencyImpl(this); } @Override public String getSimpleName() { return "" + isAvailable(); } @Override public String getType() { return "toggle"; } } }