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


/**
 * The <code>MultiServicePIDTest</code> tests the case of multiple services
 * bound with the same PID
 */
@RunWith(JUnit4TestRunner.class)
public class MultiServiceFactoryPIDTest extends ConfigurationTestBase
{
    static
    {
        // uncomment to enable debugging of this test class
        // paxRunnerVmOption = DEBUG_VM_OPTION;
    }

    @Test
    public void test_two_services_same_pid_in_same_bundle_configure_before_registration() throws BundleException
    {
        final String factoryPid = "test.pid";

        final Configuration config = createFactoryConfiguration( factoryPid );
        final String pid = config.getPid();
        TestCase.assertEquals( factoryPid, config.getFactoryPid() );
        TestCase.assertNull( config.getBundleLocation() );

        bundle = installBundle( factoryPid, MultiManagedServiceFactoryTestActivator.class );
        bundle.start();

        // give cm time for distribution
        delay();

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

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

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

        bundle.uninstall();
        bundle = null;

        delay();

        TestCase.assertNull( config.getBundleLocation() );

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


    @Test
    public void test_two_services_same_pid_in_same_bundle_configure_after_registration() throws BundleException
    {
        final String factoryPid = "test.pid";

        bundle = installBundle( factoryPid, MultiManagedServiceFactoryTestActivator.class );
        bundle.start();

        // give cm time for distribution
        delay();

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

        // no configuration yet
        TestCase.assertTrue( "Expect Properties after Service Registration", tester.configs.isEmpty() );
        TestCase.assertEquals( "Expect two update calls", 0, tester.numManagedServiceFactoryUpdatedCalls );

        final Configuration config = createFactoryConfiguration( factoryPid );
        final String pid = config.getPid();

        delay();

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

        // assert activater has configuration (two calls, one per pid)
        TestCase.assertNotNull( "Expect Properties after Service Registration", tester.configs.get( pid ) );
        TestCase.assertEquals( "Expect another two single update call", 2, tester.numManagedServiceFactoryUpdatedCalls );

        bundle.uninstall();
        bundle = null;

        delay();

        TestCase.assertNull( config.getBundleLocation() );

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


    @Test
    public void test_two_services_same_pid_in_two_bundle_configure_before_registration() throws BundleException
    {
        Bundle bundle2 = null;
        try
        {
            final String factoryPid = "test.pid";
            final Configuration config = createFactoryConfiguration( factoryPid );
            final String pid = config.getPid();

            TestCase.assertEquals( factoryPid, config.getFactoryPid() );
            TestCase.assertNull( config.getBundleLocation() );

            bundle = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class );
            bundle.start();

            bundle2 = installBundle( factoryPid, ManagedServiceFactoryTestActivator2.class );
            bundle2.start();

            // give cm time for distribution
            delay();

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

            final ManagedServiceFactoryTestActivator2 tester2 = ManagedServiceFactoryTestActivator2.INSTANCE;
            TestCase.assertNotNull( "Activator 2 not started !!", tester2 );

            // expect first activator to have received properties

            // assert first bundle has configuration (two calls, one per srv)
            TestCase.assertNotNull( "Expect Properties after Service Registration", tester.configs.get( pid ) );
            TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceFactoryUpdatedCalls );

            // assert second bundle has no configuration
            TestCase.assertTrue( tester2.configs.isEmpty() );
            TestCase.assertEquals( 0, tester2.numManagedServiceFactoryUpdatedCalls );

            // expect configuration bound to first bundle
            TestCase.assertEquals( bundle.getLocation(), config.getBundleLocation() );

            bundle.uninstall();
            bundle = null;

            delay();

            // expect configuration reassigned
            TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
            TestCase.assertNotNull( "Expect Properties after Configuration Redispatch", tester2.configs.get( pid ) );
            TestCase.assertEquals( "Expect update call after Configuration Redispatch", 1, tester2.numManagedServiceFactoryUpdatedCalls );

            // remove the configuration for good
            deleteConfig( pid );
        }
        finally
        {
            if ( bundle2 != null )
            {
                bundle2.uninstall();
            }
        }
    }


    @Test
    public void test_two_services_same_pid_in_two_bundle_configure_after_registration() throws BundleException
    {
        Bundle bundle2 = null;
        try
        {
            final String factoryPid = "test.pid";

            bundle = installBundle( factoryPid, ManagedServiceFactoryTestActivator.class );
            bundle.start();

            bundle2 = installBundle( factoryPid, ManagedServiceFactoryTestActivator2.class );
            bundle2.start();

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

            final ManagedServiceFactoryTestActivator2 tester2 = ManagedServiceFactoryTestActivator2.INSTANCE;
            TestCase.assertNotNull( "Activator not started !!", tester2 );

            delay();

            // expect no configuration but a call in each service
            TestCase.assertTrue( "Expect Properties after Service Registration", tester.configs.isEmpty() );
            TestCase.assertEquals( "Expect a single update call", 0, tester.numManagedServiceFactoryUpdatedCalls );
            TestCase.assertTrue( "Expect Properties after Service Registration", tester2.configs.isEmpty() );
            TestCase.assertEquals( "Expect a single update call", 0, tester2.numManagedServiceFactoryUpdatedCalls );

            final Configuration config = createFactoryConfiguration( factoryPid );
            final String pid = config.getPid();

            delay();

            TestCase.assertEquals( factoryPid, config.getFactoryPid() );

            TestCase.assertEquals(
                "Configuration must be bound to second bundle because the service has higher ranking",
                bundle.getLocation(), config.getBundleLocation() );

            // configuration assigned to the first bundle
            TestCase.assertNotNull( "Expect Properties after Service Registration", tester.configs.get( pid ) );
            TestCase.assertEquals( "Expect a single update call", 1, tester.numManagedServiceFactoryUpdatedCalls );

            TestCase.assertTrue( "Expect Properties after Service Registration", tester2.configs.isEmpty() );
            TestCase.assertEquals( "Expect a single update call", 0, tester2.numManagedServiceFactoryUpdatedCalls );

            bundle.uninstall();
            bundle = null;

            delay();

            // expect configuration reassigned
            TestCase.assertEquals( bundle2.getLocation(), config.getBundleLocation() );
            TestCase.assertNotNull( "Expect Properties after Configuration Redispatch", tester2.configs.get( pid ) );
            TestCase.assertEquals( "Expect a single update call after Configuration Redispatch", 1, tester2.numManagedServiceFactoryUpdatedCalls );

            // remove the configuration for good
            deleteConfig( pid );
        }
        finally
        {
            if ( bundle2 != null )
            {
                bundle2.uninstall();
            }
        }
    }

}
