/*
 * 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.cm.integration;


import java.io.IOException;
import java.util.Hashtable;
import junit.framework.TestCase;

import org.apache.felix.cm.integration.helper.ManagedServiceFactoryTestActivator;
import org.apache.felix.cm.integration.helper.ManagedServiceFactoryTestActivator2;
import org.apache.felix.cm.integration.helper.ManagedServiceTestActivator;
import org.apache.felix.cm.integration.helper.ManagedServiceTestActivator2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.service.cm.Configuration;


@RunWith(JUnit4TestRunner.class)
public class ConfigurationBindingTest extends ConfigurationTestBase
{

    static
    {
        // uncomment to enable debugging of this test class
        // paxRunnerVmOption = DEBUG_VM_OPTION;
    }


     @Test
    public void test_configuration_unbound_on_uninstall() throws BundleException
    {
        String pid = "test_configuration_unbound_on_uninstall";
        configure( pid );

        // ensure configuration is unbound
        final Configuration beforeInstall = getConfiguration( pid );
        TestCase.assertNull( beforeInstall.getBundleLocation() );

        bundle = installBundle( pid );

        // ensure no configuration bound before start
        final Configuration beforeStart = getConfiguration( pid );
        TestCase.assertNull( beforeInstall.getBundleLocation() );
        TestCase.assertNull( beforeStart.getBundleLocation() );

        bundle.start();
        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( "Activator not started !!", tester );

        // give cm time for distribution
        delay();

        // assert activater has configuration
        TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
        TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );

        // ensure a freshly retrieved object also has the location
        final Configuration beforeStop = getConfiguration( pid );
        TestCase.assertEquals( beforeStop.getBundleLocation(), bundle.getLocation() );

        // check whether bundle context is set on first configuration
        TestCase.assertEquals( beforeInstall.getBundleLocation(), bundle.getLocation() );
        TestCase.assertEquals( beforeStart.getBundleLocation(), bundle.getLocation() );

        bundle.stop();

        delay();

        // ensure configuration still bound
        TestCase.assertEquals( beforeInstall.getBundleLocation(), bundle.getLocation() );
        TestCase.assertEquals( beforeStart.getBundleLocation(), bundle.getLocation() );
        TestCase.assertEquals( beforeStop.getBundleLocation(), bundle.getLocation() );

        // ensure a freshly retrieved object also has the location
        final Configuration beforeUninstall = getConfiguration( pid );
        TestCase.assertEquals( beforeUninstall.getBundleLocation(), bundle.getLocation() );

        bundle.uninstall();
        bundle = null;

        delay();

        // ensure configuration is not bound any more
        TestCase.assertNull( beforeInstall.getBundleLocation() );
        TestCase.assertNull( beforeStart.getBundleLocation() );
        TestCase.assertNull( beforeStop.getBundleLocation() );
        TestCase.assertNull( beforeUninstall.getBundleLocation() );

        // ensure a freshly retrieved object also does not have the location
        final Configuration atEnd = getConfiguration( pid );
        TestCase.assertNull( atEnd.getBundleLocation() );

        // remove the configuration for good
        deleteConfig( pid );
    }


     @Test
    public void test_configuration_unbound_on_uninstall_with_cm_restart() throws BundleException
    {
        final String pid = "test_configuration_unbound_on_uninstall_with_cm_restart";
        configure( pid );
        final Bundle cmBundle = getCmBundle();

        // ensure configuration is unbound
        final Configuration beforeInstall = getConfiguration( pid );
        TestCase.assertNull( beforeInstall.getBundleLocation() );

        bundle = installBundle( pid );

        // ensure no configuration bound before start
        final Configuration beforeStart = getConfiguration( pid );
        TestCase.assertNull( beforeInstall.getBundleLocation() );
        TestCase.assertNull( beforeStart.getBundleLocation() );

        bundle.start();
        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( "IOActivator not started !!", tester );

        // give cm time for distribution
        delay();

        // assert activater has configuration
        TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
        TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );

        // ensure a freshly retrieved object also has the location
        final Configuration beforeStop = getConfiguration( pid );
        TestCase.assertEquals( beforeStop.getBundleLocation(), bundle.getLocation() );

        // check whether bundle context is set on first configuration
        TestCase.assertEquals( beforeInstall.getBundleLocation(), bundle.getLocation() );
        TestCase.assertEquals( beforeStart.getBundleLocation(), bundle.getLocation() );

        bundle.stop();

        // ensure configuration still bound
        TestCase.assertEquals( beforeInstall.getBundleLocation(), bundle.getLocation() );
        TestCase.assertEquals( beforeStart.getBundleLocation(), bundle.getLocation() );
        TestCase.assertEquals( beforeStop.getBundleLocation(), bundle.getLocation() );

        // ensure a freshly retrieved object also has the location
        final Configuration beforeUninstall = getConfiguration( pid );
        TestCase.assertEquals( beforeUninstall.getBundleLocation(), bundle.getLocation() );

        // stop cm bundle now before uninstalling configured bundle
        cmBundle.stop();
        delay();

        // assert configuration admin service is gone
        TestCase.assertNull( configAdminTracker.getService() );

        // uninstall bundle while configuration admin is stopped
        bundle.uninstall();
        bundle = null;

        // start cm bundle again after uninstallation
        cmBundle.start();
        delay();

        // ensure a freshly retrieved object also does not have the location
        // FELIX-1484: this test fails due to bundle location not verified
        // at first configuration access
        final Configuration atEnd = getConfiguration( pid );
        TestCase.assertNull( atEnd.getBundleLocation() );

        // remove the configuration for good
        deleteConfig( pid );
    }


     @Test
    public void test_not_updated_new_configuration_not_bound_after_bundle_uninstall() throws IOException,
        BundleException
    {
        final String pid = "test_not_updated_new_configuration_not_bound_after_bundle_uninstall";

        // create a configuration but do not update with properties
        final Configuration newConfig = configure( pid, null, false );
        TestCase.assertNull( newConfig.getProperties() );
        TestCase.assertNull( newConfig.getBundleLocation() );

        // start and settle bundle
        bundle = installBundle( pid );
        bundle.start();
        delay();

        // ensure no properties provided to bundle
        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( "Activator not started !!", tester );
        TestCase.assertNull( "Expect no properties after Service Registration", tester.props );
        TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );

        // assert configuration is still unset but bound
        TestCase.assertNull( newConfig.getProperties() );
        TestCase.assertEquals( bundle.getLocation(), newConfig.getBundleLocation() );

        // uninstall bundle, should unbind configuration
        bundle.uninstall();
        bundle = null;

        delay();

        // assert configuration is still unset and unbound
        TestCase.assertNull( newConfig.getProperties() );
        TestCase.assertNull( newConfig.getBundleLocation() );

        // remove the configuration for good
        deleteConfig( pid );
    }


     @Test
    public void test_create_with_location_unbind_before_service_supply() throws BundleException, IOException
    {

        final String pid = "test_create_with_location_unbind_before_service_supply";
        final String dummyLocation = "http://some/dummy/location";

        // 1. create and statically bind the configuration
        final Configuration config = configure( pid, dummyLocation, false );
        TestCase.assertEquals( pid, config.getPid() );
        TestCase.assertEquals( dummyLocation, config.getBundleLocation() );

        // 2. update configuration
        Hashtable<String, String> props = new Hashtable<String, String>();
        props.put( PROP_NAME, PROP_NAME );
        config.update( props );
        TestCase.assertEquals( PROP_NAME, config.getProperties().get( PROP_NAME ) );
        TestCase.assertEquals( pid, config.getPid() );
        TestCase.assertEquals( dummyLocation, config.getBundleLocation() );

        // 3. (statically) set location to null
        config.setBundleLocation( null );
        TestCase.assertNull( config.getBundleLocation() );

        // 4. install bundle with service
        bundle = installBundle( pid );
        bundle.start();
        delay();

        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( "Activator not started !!", tester );

        // assert activater has configuration (two calls, one per pid)
        TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
        TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );

        TestCase.assertEquals( bundle.getLocation(), config.getBundleLocation() );

        bundle.uninstall();
        bundle = null;

        delay();

        // statically bound configurations must remain bound after bundle
        // uninstall
        TestCase.assertNull( config.getBundleLocation() );

        // remove the configuration for good
        deleteConfig( pid );
    }


     @Test
    public void test_statically_bound() throws BundleException
    {
        final String pid = "test_statically_bound";

        // install the bundle (we need the location)
        bundle = installBundle( pid );
        final String location = bundle.getLocation();

        // create and statically bind the configuration
        configure( pid );
        final Configuration config = getConfiguration( pid );
        TestCase.assertEquals( pid, config.getPid() );
        TestCase.assertNull( config.getBundleLocation() );
        config.setBundleLocation( location );
        TestCase.assertEquals( location, config.getBundleLocation() );

        // ensure configuration is settled before starting the bundle
        delay();

        bundle.start();

        // give cm time for distribution
        delay();

        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( "Activator not started !!", tester );

        // assert activater has configuration (two calls, one per pid)
        TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
        TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );

        TestCase.assertEquals( location, config.getBundleLocation() );

        bundle.uninstall();
        bundle = null;

        delay();

        // statically bound configurations must remain bound after bundle
        // uninstall
        TestCase.assertEquals( location, config.getBundleLocation() );

        // remove the configuration for good
        deleteConfig( pid );
    }


     @Test
    public void test_static_binding_and_unbinding() throws BundleException
    {
        final String pid = "test_static_binding_and_unbinding";
        final String location = bundleContext.getBundle().getLocation();

        // create and statically bind the configuration
        configure( pid );
        final Configuration config = getConfiguration( pid );
        TestCase.assertEquals( pid, config.getPid() );
        TestCase.assertNull( config.getBundleLocation() );

        // bind the configuration
        config.setBundleLocation( location );
        TestCase.assertEquals( location, config.getBundleLocation() );

        // restart CM bundle
        final Bundle cmBundle = getCmBundle();
        cmBundle.stop();
        delay();
        cmBundle.start();

        // assert configuration still bound
        final Configuration configAfterRestart = getConfiguration( pid );
        TestCase.assertEquals( pid, configAfterRestart.getPid() );
        TestCase.assertEquals( location, configAfterRestart.getBundleLocation() );

        // unbind the configuration
        configAfterRestart.setBundleLocation( null );
        TestCase.assertNull( configAfterRestart.getBundleLocation() );

        // restart CM bundle
        cmBundle.stop();
        delay();
        cmBundle.start();

        // assert configuration unbound
        final Configuration configUnboundAfterRestart = getConfiguration( pid );
        TestCase.assertEquals( pid, configUnboundAfterRestart.getPid() );
        TestCase.assertNull( configUnboundAfterRestart.getBundleLocation() );
    }


     @Test
    public void test_dynamic_binding_and_unbinding() throws BundleException
    {
        final String pid = "test_dynamic_binding_and_unbinding";

        // create and statically bind the configuration
        configure( pid );
        final Configuration config = getConfiguration( pid );
        TestCase.assertEquals( pid, config.getPid() );
        TestCase.assertNull( config.getBundleLocation() );

        // dynamically bind the configuration
        bundle = installBundle( pid );
        final String location = bundle.getLocation();
        bundle.start();
        delay();
        TestCase.assertEquals( location, config.getBundleLocation() );

        // restart CM bundle
        final Bundle cmBundle = getCmBundle();
        cmBundle.stop();
        delay();
        cmBundle.start();

        // assert configuration still bound
        final Configuration configAfterRestart = getConfiguration( pid );
        TestCase.assertEquals( pid, configAfterRestart.getPid() );
        TestCase.assertEquals( location, configAfterRestart.getBundleLocation() );

        // stop bundle (configuration remains bound !!)
        bundle.stop();
        delay();
        TestCase.assertEquals( location, configAfterRestart.getBundleLocation() );

        // restart CM bundle
        cmBundle.stop();
        delay();
        cmBundle.start();

        // assert configuration still bound
        final Configuration configBoundAfterRestart = getConfiguration( pid );
        TestCase.assertEquals( pid, configBoundAfterRestart.getPid() );
        TestCase.assertEquals( location, configBoundAfterRestart.getBundleLocation() );
    }


     @Test
    public void test_static_binding() throws BundleException
    {
        final String pid = "test_static_binding";

        // install a bundle to get a location for binding
        bundle = installBundle( pid );
        final String location = bundle.getLocation();

        // create and statically bind the configuration
        configure( pid );
        final Configuration config = getConfiguration( pid );
        TestCase.assertEquals( pid, config.getPid() );
        TestCase.assertNull( config.getBundleLocation() );
        config.setBundleLocation( location );
        TestCase.assertEquals( location, config.getBundleLocation() );

        // ensure configuration is settled before starting the bundle
        delay();

        // start the bundle
        bundle.start();
        delay();
        TestCase.assertEquals( location, config.getBundleLocation() );

        // assert the configuration is supplied
        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( "Activator not started !!", tester );
        TestCase.assertNotNull( "Expect Properties after Service Registration", tester.props );
        TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceUpdatedCalls );

        // remove the static binding and assert still bound
        config.setBundleLocation( null );
        delay();
        TestCase.assertEquals( location, config.getBundleLocation() );

        // uninstall bundle and assert configuration unbound
        bundle.uninstall();
        bundle = null;
        delay();
        TestCase.assertNull( config.getBundleLocation() );
    }


     @Test
    public void test_two_bundles_one_pid() throws BundleException, IOException
    {
        // 1. Bundle registers service with pid1
        final String pid = "test_two_bundles_one_pid";
        final Bundle bundleA = installBundle( pid, ManagedServiceTestActivator.class );
        final String locationA = bundleA.getLocation();
        bundleA.start();
        delay();

        // call back with null
        final ManagedServiceTestActivator tester = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNull( tester.props );
        TestCase.assertEquals( 1, tester.numManagedServiceUpdatedCalls );

        // 2. create new Conf with pid1 and locationA.
        final Configuration config = configure( pid, locationA, false );
        delay();

        // ==> No call back.
        TestCase.assertNull( tester.props );
        TestCase.assertEquals( 1, tester.numManagedServiceUpdatedCalls );

        // 3. Configuration#update(prop) is called.
        config.update( theConfig );
        delay();

        // ==> call back with the prop.
        TestCase.assertNotNull( tester.props );
        TestCase.assertEquals( 2, tester.numManagedServiceUpdatedCalls );

        // 4. Stop BundleA
        bundleA.stop();
        delay();

        // 5. Start BundleA
        bundleA.start();
        delay();

        // ==> call back with the prop.
        final ManagedServiceTestActivator tester2 = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( tester2.props );
        TestCase.assertEquals( 1, tester2.numManagedServiceUpdatedCalls );

        // 6. Configuration#deleted() is called.
        config.delete();
        delay();

        // ==> call back with null.
        TestCase.assertNull( tester2.props );
        TestCase.assertEquals( 2, tester2.numManagedServiceUpdatedCalls );

        // 7. uninstall Bundle A for cleanup.
        bundleA.uninstall();
        delay();

        // Test 2

        // 8. BundleA registers ManagedService with pid1.
        final Bundle bundleA2 = installBundle( pid, ManagedServiceTestActivator.class );
        final String locationA2 = bundleA.getLocation();
        bundleA2.start();
        delay();

        // call back with null
        final ManagedServiceTestActivator tester21 = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNull( tester21.props );
        TestCase.assertEquals( 1, tester21.numManagedServiceUpdatedCalls );

        // 9. create new Conf with pid1 and locationB.
        final String locationB = "test:locationB/" + pid;
        final Configuration configB = configure( pid, locationB, false );
        delay();

        // ==> No call back.
        TestCase.assertNull( tester21.props );
        TestCase.assertEquals( 1, tester21.numManagedServiceUpdatedCalls );

        // 10. Configuration#update(prop) is called.
        configB.update( theConfig );
        delay();

        // ==> No call back because the Conf is not bound to locationA.
        TestCase.assertNull( tester21.props );
        TestCase.assertEquals( 1, tester21.numManagedServiceUpdatedCalls );
    }


    @Test
    public void test_switch_static_binding() throws BundleException
    {
        // 1. create config with pid and locationA
        // 2. update config with properties
        final String pid = "test_switch_static_binding";
        final String locationA = "test:location/A/" + pid;
        final Configuration config = configure( pid, locationA, true );

        // 3. register ManagedService ms1 with pid from said locationA
        final Bundle bundleA = installBundle( pid, ManagedServiceTestActivator.class, locationA );
        bundleA.start();
        delay();

        // ==> configuration supplied to the service ms1
        final ManagedServiceTestActivator testerA1 = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( testerA1.props );
        TestCase.assertEquals( 1, testerA1.numManagedServiceUpdatedCalls );

        // 4. register ManagedService ms2 with pid from locationB
        final String locationB = "test:location/B/" + pid;
        final Bundle bundleB = installBundle( pid, ManagedServiceTestActivator2.class, locationB );
        bundleB.start();
        delay();

        // ==> configuration not supplied to service ms2
        final ManagedServiceTestActivator2 testerB1 = ManagedServiceTestActivator2.INSTANCE;
        TestCase.assertNull( testerB1.props );
        TestCase.assertEquals( 0, testerB1.numManagedServiceUpdatedCalls );

        // 5. Call Configuration.setBundleLocation( "locationB" )
        config.setBundleLocation( locationB );
        delay();

        // ==> configuration is bound to locationB
        TestCase.assertEquals( locationB, config.getBundleLocation() );

        // ==> configuration removed from service ms1
        TestCase.assertNull( testerA1.props );
        TestCase.assertEquals( 2, testerA1.numManagedServiceUpdatedCalls );

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.props );
        TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );
    }


    @Test
    public void test_switch_dynamic_binding() throws BundleException, IOException
    {
        // 1. create config with pid with null location
        // 2. update config with properties
        final String pid = "test_switch_dynamic_binding";
        final String locationA = "test:location/A/" + pid;
        final Configuration config = configure( pid, null, true );

        // 3. register ManagedService ms1 with pid from locationA
        final Bundle bundleA = installBundle( pid, ManagedServiceTestActivator.class, locationA );
        bundleA.start();
        delay();

        // ==> configuration supplied to the service ms1
        final ManagedServiceTestActivator testerA1 = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( testerA1.props );
        TestCase.assertEquals( 1, testerA1.numManagedServiceUpdatedCalls );

        // ==> configuration is dynamically bound to locationA
        TestCase.assertEquals( locationA, config.getBundleLocation() );

        // 4. register ManagedService ms2 with pid from locationB
        final String locationB = "test:location/B/" + pid;
        final Bundle bundleB = installBundle( pid, ManagedServiceTestActivator2.class, locationB );
        bundleB.start();
        delay();

        // ==> configuration not supplied to service ms2
        final ManagedServiceTestActivator2 testerB1 = ManagedServiceTestActivator2.INSTANCE;
        TestCase.assertNull( testerB1.props );
        TestCase.assertEquals( 0, testerB1.numManagedServiceUpdatedCalls );

        // 5. Call Configuration.setBundleLocation( "locationB" )
        config.setBundleLocation( locationB );
        delay();

        // ==> configuration is bound to locationB
        TestCase.assertEquals( locationB, config.getBundleLocation() );

        // ==> configuration removed from service ms1
        TestCase.assertNull( testerA1.props );
        TestCase.assertEquals( 2, testerA1.numManagedServiceUpdatedCalls );

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.props );
        TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );

        // 6. Update configuration now
        config.update();
        delay();

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.props );
        TestCase.assertEquals( 2, testerB1.numManagedServiceUpdatedCalls );
    }


    @Test
    public void test_switch_static_binding_factory() throws BundleException, IOException
    {
        // 1. create config with pid and locationA
        // 2. update config with properties
        final String factoryPid = "test_switch_static_binding_factory";
        final String locationA = "test:location/A/" + factoryPid;
        final Configuration config = createFactoryConfiguration( factoryPid, locationA, true );
        final String pid = config.getPid();

        // 3. register ManagedService ms1 with pid from said locationA
        final Bundle bundleA = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class, locationA );
        bundleA.start();
        delay();

        // ==> configuration supplied to the service ms1
        final ManagedServiceFactoryTestActivator testerA1 = ManagedServiceFactoryTestActivator.INSTANCE;
        TestCase.assertNotNull( testerA1.configs.get( pid ) );
        TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );

        // 4. register ManagedService ms2 with pid from locationB
        final String locationB = "test:location/B/" + factoryPid;
        final Bundle bundleB = installBundle( factoryPid, ManagedServiceFactoryTestActivator2.class, locationB );
        bundleB.start();
        delay();

        // ==> configuration not supplied to service ms2
        final ManagedServiceFactoryTestActivator2 testerB1 = ManagedServiceFactoryTestActivator2.INSTANCE;
        TestCase.assertNull( testerB1.configs.get( pid ));
        TestCase.assertEquals( 0, testerB1.numManagedServiceFactoryUpdatedCalls );

        // 5. Call Configuration.setBundleLocation( "locationB" )
        config.setBundleLocation( locationB );
        delay();

        // ==> configuration is bound to locationB
        TestCase.assertEquals( locationB, config.getBundleLocation() );

        // ==> configuration removed from service ms1
        TestCase.assertNull( testerA1.configs.get( pid ));
        TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
        TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryDeleteCalls );

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.configs.get( pid ) );
        TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );

        // 6. Update configuration now
        config.update();
        delay();

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.configs.get( pid ) );
        TestCase.assertEquals( 2, testerB1.numManagedServiceFactoryUpdatedCalls );
   }


    @Test
    public void test_switch_dynamic_binding_factory() throws BundleException, IOException
    {
        // 1. create config with pid and locationA
        // 2. update config with properties
        final String factoryPid = "test_switch_static_binding_factory";
        final String locationA = "test:location/A/" + factoryPid;
        final Configuration config = createFactoryConfiguration( factoryPid, null, true );
        final String pid = config.getPid();

        TestCase.assertNull( config.getBundleLocation() );

        // 3. register ManagedService ms1 with pid from said locationA
        final Bundle bundleA = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class, locationA );
        bundleA.start();
        delay();

        // ==> configuration supplied to the service ms1
        final ManagedServiceFactoryTestActivator testerA1 = ManagedServiceFactoryTestActivator.INSTANCE;
        TestCase.assertNotNull( testerA1.configs.get( pid ) );
        TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
        TestCase.assertEquals( locationA, config.getBundleLocation() );

        // 4. register ManagedService ms2 with pid from locationB
        final String locationB = "test:location/B/" + factoryPid;
        final Bundle bundleB = installBundle( factoryPid, ManagedServiceFactoryTestActivator2.class, locationB );
        bundleB.start();
        delay();

        // ==> configuration not supplied to service ms2
        final ManagedServiceFactoryTestActivator2 testerB1 = ManagedServiceFactoryTestActivator2.INSTANCE;
        TestCase.assertNull( testerB1.configs.get( pid ));
        TestCase.assertEquals( 0, testerB1.numManagedServiceFactoryUpdatedCalls );
        TestCase.assertEquals( locationA, config.getBundleLocation() );

        // 5. Call Configuration.setBundleLocation( "locationB" )
        config.setBundleLocation( locationB );
        delay();

        // ==> configuration is bound to locationB
        TestCase.assertEquals( locationB, config.getBundleLocation() );

        // ==> configuration removed from service ms1
        TestCase.assertNull( testerA1.configs.get( pid ));
        TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
        TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryDeleteCalls );

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.configs.get( pid ) );
        TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );

        // 6. Update configuration now
        config.update();
        delay();

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.configs.get( pid ) );
        TestCase.assertEquals( 2, testerB1.numManagedServiceFactoryUpdatedCalls );
    }


    @Test
    public void test_switch_dynamic_binding_after_uninstall() throws BundleException, IOException
    {
        // 1. create config with pid with null location
        // 2. update config with properties
        final String pid = "test_switch_dynamic_binding";
        final String locationA = "test:location/A/" + pid;
        final Configuration config = configure( pid, null, true );

        TestCase.assertNull( config.getBundleLocation() );

        // 3. register ManagedService ms1 with pid from locationA
        final Bundle bundleA = installBundle( pid, ManagedServiceTestActivator.class, locationA );
        bundleA.start();
        delay();

        // ==> configuration supplied to the service ms1
        final ManagedServiceTestActivator testerA1 = ManagedServiceTestActivator.INSTANCE;
        TestCase.assertNotNull( testerA1.props );
        TestCase.assertEquals( 1, testerA1.numManagedServiceUpdatedCalls );

        // ==> configuration is dynamically bound to locationA
        TestCase.assertEquals( locationA, config.getBundleLocation() );

        // 4. register ManagedService ms2 with pid from locationB
        final String locationB = "test:location/B/" + pid;
        final Bundle bundleB = installBundle( pid, ManagedServiceTestActivator2.class, locationB );
        bundleB.start();
        delay();

        // ==> configuration not supplied to service ms2
        final ManagedServiceTestActivator2 testerB1 = ManagedServiceTestActivator2.INSTANCE;
        TestCase.assertNull( testerB1.props );
        TestCase.assertEquals( 0, testerB1.numManagedServiceUpdatedCalls );

        // 5. Uninstall bundle A
        bundleA.uninstall();
        delay();

        // ==> configuration is bound to locationB
        TestCase.assertEquals( locationB, config.getBundleLocation() );

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.props );
        TestCase.assertEquals( 1, testerB1.numManagedServiceUpdatedCalls );

        // 6. Update configuration now
        config.update();
        delay();

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.props );
        TestCase.assertEquals( 2, testerB1.numManagedServiceUpdatedCalls );
    }


    @Test
    public void test_switch_dynamic_binding_factory_after_uninstall() throws BundleException, IOException
    {
        // 1. create config with pid and locationA
        // 2. update config with properties
        final String factoryPid = "test_switch_static_binding_factory";
        final String locationA = "test:location/A/" + factoryPid;
        final Configuration config = createFactoryConfiguration( factoryPid, null, true );
        final String pid = config.getPid();

        TestCase.assertNull( config.getBundleLocation() );

        // 3. register ManagedService ms1 with pid from said locationA
        final Bundle bundleA = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class, locationA );
        bundleA.start();
        delay();

        // ==> configuration supplied to the service ms1
        final ManagedServiceFactoryTestActivator testerA1 = ManagedServiceFactoryTestActivator.INSTANCE;
        TestCase.assertNotNull( testerA1.configs.get( pid ) );
        TestCase.assertEquals( 1, testerA1.numManagedServiceFactoryUpdatedCalls );
        TestCase.assertEquals( locationA, config.getBundleLocation() );

        // 4. register ManagedService ms2 with pid from locationB
        final String locationB = "test:location/B/" + factoryPid;
        final Bundle bundleB = installBundle( factoryPid, ManagedServiceFactoryTestActivator2.class, locationB );
        bundleB.start();
        delay();

        // ==> configuration not supplied to service ms2
        final ManagedServiceFactoryTestActivator2 testerB1 = ManagedServiceFactoryTestActivator2.INSTANCE;
        TestCase.assertNull( testerB1.configs.get( pid ));
        TestCase.assertEquals( 0, testerB1.numManagedServiceFactoryUpdatedCalls );
        TestCase.assertEquals( locationA, config.getBundleLocation() );

        // 5. Uninstall bundle A
        bundleA.uninstall();
        delay();

        // ==> configuration is bound to locationB
        TestCase.assertEquals( locationB, config.getBundleLocation() );

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.configs.get( pid ) );
        TestCase.assertEquals( 1, testerB1.numManagedServiceFactoryUpdatedCalls );

        // 6. Update configuration now
        config.update();
        delay();

        // ==> configuration supplied to the service ms2
        TestCase.assertNotNull( testerB1.configs.get( pid ) );
        TestCase.assertEquals( 2, testerB1.numManagedServiceFactoryUpdatedCalls );
    }
}
