Add test cases to verify configuration is not supplied twice in the
following scenario:

  * Register service with pids p1, p2
    -> Expect callbacks for p1 and p2
    
  * Update service registration with pids p2, p3
    -> Expect call for p3 only
       (p2 has already been supplied before)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1451589 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java b/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java
index 684f514..f35c0f0 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigurationBaseTest.java
@@ -915,7 +915,8 @@
         // 6. test bundle calls cm.getConfiguration(pid1)
         final Configuration get2 = getConfigurationAdmin().getConfiguration( pid );
         TestCase.assertEquals( bundle.getLocation(), get2.getBundleLocation() );
-}
+    }
+
 
     @Test
     public void test_ManagedService_change_pid() throws BundleException, IOException
@@ -963,6 +964,80 @@
 
 
     @Test
+    public void test_ManagedService_change_pid_overlap() throws BundleException, IOException
+    {
+        final String pid0 = "test_ManagedService_change_pid_0";
+        final String pid1 = "test_ManagedService_change_pid_1";
+        final String pid2 = "test_ManagedService_change_pid_2";
+
+        final Configuration config0 = configure( pid0, null, true );
+        final Configuration config1 = configure( pid1, null, true );
+        final Configuration config2 = configure( pid2, null, true );
+        delay();
+
+        // register ManagedService ms1 with pid from said locationA
+        bundle = installBundle( pid0 + "," + pid1, ManagedServiceTestActivator.class );
+        bundle.start();
+        delay();
+
+        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
+        TestCase.assertNotNull( tester.props );
+
+        TestCase.assertEquals( pid0, tester.configs.get( pid0 ).get( Constants.SERVICE_PID ) );
+        TestCase.assertNull( tester.configs.get( pid0 ).get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( tester.configs.get( pid0 ).get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, tester.configs.get( pid0 ).get( PROP_NAME ) );
+
+        TestCase.assertEquals( pid1, tester.configs.get( pid1 ).get( Constants.SERVICE_PID ) );
+        TestCase.assertNull( tester.configs.get( pid1 ).get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( tester.configs.get( pid1 ).get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, tester.configs.get( pid1 ).get( PROP_NAME ) );
+
+        // two pids, two calls
+        TestCase.assertEquals( 2, tester.numManagedServiceUpdatedCalls );
+
+        // change ManagedService PID
+        tester.changePid( pid1 + "," + pid2 );
+        delay();
+
+        TestCase.assertNotNull( tester.props );
+
+        // config pid0 is not "removed"
+        TestCase.assertEquals( pid0, tester.configs.get( pid0 ).get( Constants.SERVICE_PID ) );
+        TestCase.assertNull( tester.configs.get( pid0 ).get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( tester.configs.get( pid0 ).get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, tester.configs.get( pid0 ).get( PROP_NAME ) );
+
+        // config pid1 is retained
+        TestCase.assertEquals( pid1, tester.configs.get( pid1 ).get( Constants.SERVICE_PID ) );
+        TestCase.assertNull( tester.configs.get( pid1 ).get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( tester.configs.get( pid1 ).get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, tester.configs.get( pid1 ).get( PROP_NAME ) );
+
+        // config pid2 is added
+        TestCase.assertEquals( pid2, tester.configs.get( pid2 ).get( Constants.SERVICE_PID ) );
+        TestCase.assertNull( tester.configs.get( pid2 ).get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( tester.configs.get( pid2 ).get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, tester.configs.get( pid2 ).get( PROP_NAME ) );
+
+        // one "additional" pid, one additional call
+        TestCase.assertEquals( 3, tester.numManagedServiceUpdatedCalls );
+
+        // delete
+        config0.delete(); // ignored by MS
+        config1.delete();
+        config2.delete();
+        delay();
+
+        // ==> update with null
+        TestCase.assertNull( tester.props );
+
+        // two pids removed, two calls
+        TestCase.assertEquals( 5, tester.numManagedServiceUpdatedCalls );
+    }
+
+
+    @Test
     public void test_ManagedServiceFactory_change_pid() throws BundleException, IOException
     {
 
@@ -1028,6 +1103,96 @@
         TestCase.assertEquals( 1, tester.numManagedServiceFactoryDeleteCalls );
     }
 
+
+    @Test
+    public void test_ManagedServiceFactory_change_pid_overlap() throws BundleException, IOException
+    {
+
+        final String factoryPid0 = "test_ManagedServiceFactory_change_pid_0";
+        final String factoryPid1 = "test_ManagedServiceFactory_change_pid_1";
+        final String factoryPid2 = "test_ManagedServiceFactory_change_pid_2";
+
+        final Configuration config0 = createFactoryConfiguration( factoryPid0, null, true );
+        final String pid0 = config0.getPid();
+        final Configuration config1 = createFactoryConfiguration( factoryPid1, null, true );
+        final String pid1 = config1.getPid();
+        final Configuration config2 = createFactoryConfiguration( factoryPid2, null, true );
+        final String pid2 = config2.getPid();
+        delay();
+
+        bundle = installBundle( factoryPid0 + "," + factoryPid1, ManagedServiceFactoryTestActivator.class );
+        bundle.start();
+        delay();
+
+        // pid0 properties provided on registration
+        final ManagedServiceFactoryTestActivator tester = ManagedServiceFactoryTestActivator.INSTANCE;
+        Dictionary<?, ?> props0 = tester.configs.get( pid0 );
+        TestCase.assertNotNull( props0 );
+        TestCase.assertEquals( pid0, props0.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid0, props0.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props0.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props0.get( PROP_NAME ) );
+
+        Dictionary<?, ?> props1 = tester.configs.get( pid1 );
+        TestCase.assertNotNull( props1 );
+        TestCase.assertEquals( pid1, props1.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid1, props1.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props1.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props1.get( PROP_NAME ) );
+
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 2, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 0, tester.numManagedServiceFactoryDeleteCalls );
+
+        // change ManagedService PID
+        tester.changePid( factoryPid1 + "," + factoryPid2 );
+        delay();
+
+        // pid2 properties must have been added
+        Dictionary<?, ?> props2 = tester.configs.get( pid2 );
+        TestCase.assertNotNull( props2 );
+        TestCase.assertEquals( pid2, props2.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid2, props2.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props2.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props2.get( PROP_NAME ) );
+
+        // pid0 properties must still exist !
+        Dictionary<?, ?> props01 = tester.configs.get( pid0 );
+        TestCase.assertNotNull( props01 );
+        TestCase.assertEquals( pid0, props01.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid0, props01.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props01.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props01.get( PROP_NAME ) );
+
+        // pid1 properties must still exist !
+        Dictionary<?, ?> props11 = tester.configs.get( pid1 );
+        TestCase.assertNotNull( props11 );
+        TestCase.assertEquals( pid1, props11.get( Constants.SERVICE_PID ) );
+        TestCase.assertEquals( factoryPid1, props11.get( ConfigurationAdmin.SERVICE_FACTORYPID ) );
+        TestCase.assertNull( props11.get( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) );
+        TestCase.assertEquals( PROP_NAME, props11.get( PROP_NAME ) );
+
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 3, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 0, tester.numManagedServiceFactoryDeleteCalls );
+
+        // delete
+        config0.delete();
+        config1.delete();
+        config2.delete();
+        delay();
+
+        // only pid1 and pid2 properties removed because pid0 is not registered any longer
+        TestCase.assertNotNull( tester.configs.get( pid0 ) );
+        TestCase.assertNull( tester.configs.get( pid1 ) );
+        TestCase.assertNull( tester.configs.get( pid2 ) );
+
+        TestCase.assertEquals( 0, tester.numManagedServiceUpdatedCalls );
+        TestCase.assertEquals( 3, tester.numManagedServiceFactoryUpdatedCalls );
+        TestCase.assertEquals( 2, tester.numManagedServiceFactoryDeleteCalls );
+    }
+
+
     @Test
     public void test_factory_configuration_collision() throws IOException, InvalidSyntaxException, BundleException {
         final String factoryPid = "test_factory_configuration_collision";
diff --git a/configadmin/src/test/java/org/apache/felix/cm/integration/helper/BaseTestActivator.java b/configadmin/src/test/java/org/apache/felix/cm/integration/helper/BaseTestActivator.java
index 8d5dce6..9919960 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/integration/helper/BaseTestActivator.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/integration/helper/BaseTestActivator.java
@@ -53,6 +53,11 @@
     {
         numManagedServiceUpdatedCalls++;
         this.props = props;
+
+        if ( props != null )
+        {
+            this.configs.put( ( String ) props.get( Constants.SERVICE_PID ), props );
+        }
     }
 
 
@@ -86,21 +91,7 @@
             final Hashtable props = new Hashtable();
 
             // multi-value PID support
-            final String pid = ( String ) prop;
-            if ( pid.indexOf( ',' ) > 0 )
-            {
-                final String[] pids = pid.split( "," );
-                props.put( Constants.SERVICE_PID, pids );
-            }
-            else if ( pid.indexOf( ';' ) > 0 )
-            {
-                final String[] pids = pid.split( ";" );
-                props.put( Constants.SERVICE_PID, Arrays.asList( pids ) );
-            }
-            else
-            {
-                props.put( Constants.SERVICE_PID, pid );
-            }
+            props.put( Constants.SERVICE_PID, toServicePidObject( ( String ) prop ) );
 
             return props;
         }
@@ -109,4 +100,22 @@
         throw new Exception( "Missing " + HEADER_PID + " manifest header, cannot start" );
     }
 
+
+    protected Object toServicePidObject( final String pid )
+    {
+        if ( pid.indexOf( ',' ) > 0 )
+        {
+            final String[] pids = pid.split( "," );
+            return pids;
+        }
+        else if ( pid.indexOf( ';' ) > 0 )
+        {
+            final String[] pids = pid.split( ";" );
+            return Arrays.asList( pids );
+        }
+        else
+        {
+            return pid;
+        }
+    }
 }
diff --git a/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryTestActivator.java b/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryTestActivator.java
index 719281c..204d446 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryTestActivator.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryTestActivator.java
@@ -53,7 +53,7 @@
 
     public void changePid( final String newPid )
     {
-        this.registrationProps.put( Constants.SERVICE_PID, newPid );
+        this.registrationProps.put( Constants.SERVICE_PID, toServicePidObject( newPid ) );
         this.registration.setProperties( this.registrationProps );
     }
 }
diff --git a/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceTestActivator.java b/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceTestActivator.java
index f6d6675..962a435 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceTestActivator.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceTestActivator.java
@@ -51,7 +51,7 @@
 
     public void changePid( final String newPid )
     {
-        this.registrationProps.put( Constants.SERVICE_PID, newPid );
+        this.registrationProps.put( Constants.SERVICE_PID, toServicePidObject( newPid ) );
         this.registration.setProperties( this.registrationProps );
     }
 }