FELIX-3875 test for services bound/unbound on configuration change

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1439755 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java
index 55c118d..f807b12 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentConfigurationTest.java
@@ -36,7 +36,7 @@
     static
     {
         // uncomment to enable debugging of this test class
-        //  paxRunnerVmOption = DEBUG_VM_OPTION;
+//          paxRunnerVmOption = DEBUG_VM_OPTION;
     }
 
 
@@ -281,6 +281,7 @@
             TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
             TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
             TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE.m_singleRef );
 
             // reconfigure without target --> unsatisifed
             theConfig.remove( targetProp );
@@ -312,6 +313,99 @@
         }
     }
 
+    @Test
+    public void test_SimpleComponent_dynamic_configuration_with_optional_service() throws Exception
+    {
+        final String targetProp = "ref.target";
+        final String filterProp = "required";
+        final SimpleServiceImpl service = SimpleServiceImpl.create( bundleContext, "sample" ).setFilterProperty( filterProp );
+        try
+        {
+            final String pid = "DynamicConfigurationComponentWithOptionalReference";
+            final Component component = findComponentByName( pid );
+
+            deleteConfig( pid );
+            delay();
+
+            TestCase.assertNotNull( component );
+            TestCase.assertFalse( component.isDefaultEnabled() );
+
+            TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+            TestCase.assertNull( SimpleComponent.INSTANCE );
+
+            component.enable();
+            delay();
+
+            // optional ref missing --> component active
+            TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE );
+            final SimpleComponent instance = SimpleComponent.INSTANCE;
+
+            // dynamically configure without the correct target
+            configure( pid );
+            delay();
+
+            // optional ref missing --> component active
+            TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            // dynamically configure with correct target
+            theConfig.put( targetProp, "(filterprop=" + filterProp + ")" );
+            configure( pid );
+            delay();
+
+            TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+            TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            configure( pid );
+            delay();
+
+            // same instance after reconfiguration
+            TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
+            TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
+            TestCase.assertNotNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            // reconfigure without target --> active
+            theConfig.remove( targetProp );
+            configure( pid );
+            delay();
+
+            // optional ref missing --> component active
+            TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            deleteConfig( pid );
+            delay();
+
+            // optional ref missing --> component active
+            TestCase.assertEquals( Component.STATE_ACTIVE, component.getState() );
+            TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
+            TestCase.assertNull( SimpleComponent.INSTANCE.m_singleRef );
+
+            component.disable();
+            delay();
+
+            TestCase.assertEquals( Component.STATE_DISABLED, component.getState() );
+            TestCase.assertNull( SimpleComponent.INSTANCE );
+        }
+        finally
+        {
+//            Thread.sleep( 60000 );
+            theConfig.remove( targetProp );
+            if ( service != null )
+            {
+                service.drop();
+            }
+        }
+    }
+
 
     @Test
     public void test_SimpleComponent_factory_configuration()
diff --git a/scr/src/test/resources/integration_test_simple_components.xml b/scr/src/test/resources/integration_test_simple_components.xml
index 04f0f9d..905275d 100644
--- a/scr/src/test/resources/integration_test_simple_components.xml
+++ b/scr/src/test/resources/integration_test_simple_components.xml
@@ -60,8 +60,23 @@
             interface="org.apache.felix.scr.integration.components.SimpleService"
             cardinality="1..1"
             policy="dynamic"
-            bind="bindSimpleService"
-            unbind="unbindSimpleService"
+            bind="setSimpleService"
+            unbind="unsetSimpleService"
+            target="(filterprop=__nothing__)"
+        />
+    </scr:component>
+
+    <scr:component name="DynamicConfigurationComponentWithOptionalReference"
+        enabled="false" modified="configure" immediate="true">
+        <implementation class="org.apache.felix.scr.integration.components.SimpleComponent" />
+        <property name="service.pid" value="DynamicConfigurationComponentWithRequiredReference" />
+        <reference
+            name="ref"
+            interface="org.apache.felix.scr.integration.components.SimpleService"
+            cardinality="0..1"
+            policy="dynamic"
+            bind="setSimpleService"
+            unbind="unsetSimpleService"
             target="(filterprop=__nothing__)"
         />
     </scr:component>