@RunWith(PaxExam.class)
public class ServiceDependencyComponentLifeCycleTest extends TestBase {
@Test
public void testComponentLifeCycleWhenAddingAndRemovingDependencies() throws Exception {
DependencyManager m = new DependencyManager(context);
// helper class that ensures certain steps get executed in sequence
Ensure e = new Ensure();
// create a resource provider
Component component = m.createComponent().setInterface(MyService2.class.getName(), null).setImplementation(new MyComponent(e));
ServiceDependency dependency = m.createServiceDependency().setService(MyService.class).setRequired(true);
ServiceDependency dependency2 = m.createServiceDependency().setService(MyService.class).setRequired(true);
ServiceTracker st = new ServiceTracker(context, MyService2.class.getName(), null);
st.open();
Component component2 = m.createComponent().setInterface(MyService.class.getName(), null).setImplementation(new MyImpl(e));
// add the component: it has no dependencies so it should be activated immediately
m.add(component);
Assert.assertNotNull("service should be available", st.getService());
// add a required dependency that is not available, so the component should be deactivated
component.add(dependency);
Assert.assertNull("service should no longer be available", st.getService());
// remove the dependency again, so the component should be activated again
component.remove(dependency);
Assert.assertNotNull("service should be available", st.getService());
// make the dependency instance bound
dependency.setInstanceBound(true);
// add it again, the component was already active so even though the dependency
// is required, the component will *NOT* go through the destroy life cycle methods
component.add(dependency);
Assert.assertNull("service should no longer be available", st.getService());
component.remove(dependency);
Assert.assertNotNull("service should be available", st.getService());
// make the second dependency instance bound too
dependency2.setInstanceBound(true);
// activate the service we depend on
m.add(component2);
// init and start should be invoked here, so wait for them to complete
e.waitForStep(10, 5000);
component.add(dependency);
Assert.assertNotNull("service should be available", st.getService());
component.add(dependency2);
Assert.assertNotNull("service should be available", st.getService());
component.remove(dependency);
Assert.assertNotNull("service should be available", st.getService());
e.step(11);
// remove the service again, the component still has an instance bound
// dependency on it, so stop() should be invoked, but the component
// should not be destroyed
m.remove(component2);
e.step(15);
Assert.assertNull("service should no longer be available", st.getService());
component.remove(dependency2);
Assert.assertNotNull("service should be available", st.getService());
m.remove(component);
e.step(19);
}