blob: d9f48d318da823c1d3999f50c9ae313b1e8b10a7 [file] [log] [blame]
/*
* 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";
}
}
}