Added a new test that reveals an issue with life cycle listeners that are dynamically added.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1076267 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dm/test/ComponentLifeCycleTest.java b/dependencymanager/test/src/test/java/org/apache/felix/dm/test/ComponentLifeCycleTest.java
index 46f4cb1..dd24583 100644
--- a/dependencymanager/test/src/test/java/org/apache/felix/dm/test/ComponentLifeCycleTest.java
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dm/test/ComponentLifeCycleTest.java
@@ -21,8 +21,10 @@
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.provision;
+import junit.framework.Assert;
import org.apache.felix.dm.Component;
+import org.apache.felix.dm.ComponentStateListener;
import org.apache.felix.dm.DependencyManager;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -30,6 +32,8 @@
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
@RunWith(JUnit4TestRunner.class)
public class ComponentLifeCycleTest extends Base {
@@ -59,23 +63,6 @@
e.step(6);
}
- @Test
- public void testCustomComponentLifeCycleCallbacks(BundleContext context) {
- DependencyManager m = new DependencyManager(context);
- // helper class that ensures certain steps get executed in sequence
- Ensure e = new Ensure();
- // create a simple service component
- Component s = m.createComponent()
- .setImplementation(new CustomComponentInstance(e))
- .setCallbacks("a", "b", "c", "d");
- // add it, and since it has no dependencies, it should be activated immediately
- m.add(s);
- // remove it so it gets destroyed
- m.remove(s);
- // ensure we executed all steps inside the component instance
- e.step(6);
- }
-
static class ComponentInstance {
private final Ensure m_ensure;
public ComponentInstance(Ensure e) {
@@ -96,6 +83,23 @@
}
}
+ @Test
+ public void testCustomComponentLifeCycleCallbacks(BundleContext context) {
+ DependencyManager m = new DependencyManager(context);
+ // helper class that ensures certain steps get executed in sequence
+ Ensure e = new Ensure();
+ // create a simple service component
+ Component s = m.createComponent()
+ .setImplementation(new CustomComponentInstance(e))
+ .setCallbacks("a", "b", "c", "d");
+ // add it, and since it has no dependencies, it should be activated immediately
+ m.add(s);
+ // remove it so it gets destroyed
+ m.remove(s);
+ // ensure we executed all steps inside the component instance
+ e.step(6);
+ }
+
static class CustomComponentInstance {
private final Ensure m_ensure;
public CustomComponentInstance(Ensure e) {
@@ -115,4 +119,163 @@
m_ensure.step(5);
}
}
+
+
+
+ @Test
+ public void testComponentStateListingLifeCycle(BundleContext context) {
+ DependencyManager m = new DependencyManager(context);
+ // helper class that ensures certain steps get executed in sequence
+ Ensure e = new Ensure();
+ // create a simple service component
+ ComponentStateListeningInstance implementation = new ComponentStateListeningInstance(e);
+ Component s = m.createComponent()
+ .setInterface(MyInterface.class.getName(), null)
+ .setImplementation(implementation);
+ // add the state listener
+ s.addStateListener(implementation);
+ // add it, and since it has no dependencies, it should be activated immediately
+ m.add(s);
+ // remove it so it gets destroyed
+ m.remove(s);
+ // remove the state listener
+ s.removeStateListener(implementation);
+ // ensure we executed all steps inside the component instance
+ e.step(10);
+ }
+
+ public static interface MyInterface {}
+
+ static class ComponentStateListeningInstance implements MyInterface, ComponentStateListener {
+ volatile ServiceRegistration m_registration;
+ private final Ensure m_ensure;
+
+ public ComponentStateListeningInstance(Ensure e) {
+ m_ensure = e;
+ m_ensure.step(1);
+ }
+
+ private void debug() {
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ System.out.println("AT: " + stackTrace[2].getClassName() + "." + stackTrace[2].getMethodName() + "():" + stackTrace[2].getLineNumber());
+ }
+
+ public void init(Component c) {
+ debug();
+ m_ensure.step(2);
+ }
+
+ public void start(Component c) {
+ debug();
+ m_ensure.step(4);
+ }
+ public void stop(Component c) {
+ debug();
+ m_ensure.step(7);
+ }
+
+ public void destroy(Component c) {
+ debug();
+ m_ensure.step(9);
+ }
+
+ public void starting(Component component) {
+ debug();
+ m_ensure.step(3);
+ }
+
+ public void started(Component component) {
+ debug();
+ m_ensure.step(5);
+ ServiceReference reference = m_registration.getReference();
+ Assert.assertNotNull("Service not yet registered.", reference);
+ }
+
+ public void stopping(Component component) {
+ debug();
+ m_ensure.step(6);
+ }
+
+ public void stopped(Component component) {
+ debug();
+ m_ensure.step(8);
+ }
+ }
+
+
+
+ @Test
+ public void testDynamicComponentStateListingLifeCycle(BundleContext context) {
+ DependencyManager m = new DependencyManager(context);
+ // helper class that ensures certain steps get executed in sequence
+ Ensure e = new Ensure();
+ // create a simple service component
+ Component s = m.createComponent()
+ .setInterface(MyInterface.class.getName(), null)
+ .setImplementation(new DynamicComponentStateListeningInstance(e));
+ // add it, and since it has no dependencies, it should be activated immediately
+ m.add(s);
+ // remove it so it gets destroyed
+ m.remove(s);
+ // ensure we executed all steps inside the component instance
+ e.step(10);
+ }
+
+ static class DynamicComponentStateListeningInstance implements MyInterface, ComponentStateListener {
+ volatile ServiceRegistration m_registration;
+ private final Ensure m_ensure;
+
+ public DynamicComponentStateListeningInstance(Ensure e) {
+ m_ensure = e;
+ m_ensure.step(1);
+ }
+
+ private void debug() {
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ System.out.println("AT: " + stackTrace[2].getClassName() + "." + stackTrace[2].getMethodName() + "():" + stackTrace[2].getLineNumber());
+ }
+
+ public void init(Component c) {
+ debug();
+ m_ensure.step(2);
+ c.addStateListener(this);
+ }
+
+ public void start(Component c) {
+ debug();
+ m_ensure.step(4);
+ }
+ public void stop(Component c) {
+ debug();
+ m_ensure.step(7);
+ }
+
+ public void destroy(Component c) {
+ debug();
+ m_ensure.step(9);
+ c.removeStateListener(this);
+ }
+
+ public void starting(Component component) {
+ debug();
+ m_ensure.step(3);
+ }
+
+ public void started(Component component) {
+ debug();
+ m_ensure.step(5);
+ ServiceReference reference = m_registration.getReference();
+ Assert.assertNotNull("Service not yet registered.", reference);
+ }
+
+ public void stopping(Component component) {
+ debug();
+ m_ensure.step(6);
+ }
+
+ public void stopped(Component component) {
+ debug();
+ m_ensure.step(8);
+ }
+ }
}