blob: 813267d143960444ab690d36f70e8e2991d08770 [file] [log] [blame]
/*
* 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.scr.integration;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.felix.scr.integration.components.SimpleComponent;
import org.apache.felix.scr.integration.components.SimpleServiceImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.Constants;
import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
@RunWith(JUnit4TestRunner.class)
public class ComponentConfigurationTest extends ComponentTestBase
{
static
{
// uncomment to enable debugging of this test class
// paxRunnerVmOption = DEBUG_VM_OPTION;
}
@Test
public void test_SimpleComponent_configuration_ignore() throws Exception
{
final String pid = "SimpleComponent.configuration.ignore";
TestCase.assertNull( SimpleComponent.INSTANCE );
deleteConfig( pid );
delay();
ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( SimpleComponent.INSTANCE );
TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
configure( pid );
delay();
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( SimpleComponent.INSTANCE );
TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
deleteConfig( pid );
delay();
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( SimpleComponent.INSTANCE );
TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
disableAndCheck( cc );
TestCase.assertNull( SimpleComponent.INSTANCE );
}
@Test
public void test_SimpleComponent_configuration_optional() throws Exception
{
final String pid = "SimpleComponent.configuration.optional";
ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.ACTIVE);
final SimpleComponent firstInstance = SimpleComponent.INSTANCE;
TestCase.assertNotNull( firstInstance );
TestCase.assertNull( firstInstance.getProperty( PROP_NAME ) );
configure( pid );
delay();
final SimpleComponent secondInstance = SimpleComponent.INSTANCE;
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( secondInstance );
TestCase.assertEquals( PROP_NAME, secondInstance.getProperty( PROP_NAME ) );
deleteConfig( pid );
delay();
final SimpleComponent thirdInstance = SimpleComponent.INSTANCE;
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( thirdInstance );
TestCase.assertNull( thirdInstance.getProperty( PROP_NAME ) );
TestCase.assertNotSame( "Expect new instance object after reconfiguration", firstInstance, secondInstance );
TestCase.assertNotSame( "Expect new instance object after configuration deletion (1)", firstInstance,
thirdInstance );
TestCase.assertNotSame( "Expect new instance object after configuration deletion (2)", secondInstance,
thirdInstance );
disableAndCheck( cc );
TestCase.assertNull( SimpleComponent.INSTANCE );
}
@Test
public void test_SimpleComponent_configuration_require() throws Exception
{
final String pid = "SimpleComponent.configuration.require";
deleteConfig( pid );
delay();
TestCase.assertNull( SimpleComponent.INSTANCE );
getConfigurationsDisabledThenEnable(pid, 0, ComponentConfigurationDTO.UNSATISFIED);
TestCase.assertNull( SimpleComponent.INSTANCE );
configure( pid );
delay();
ComponentConfigurationDTO cc = findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( SimpleComponent.INSTANCE );
TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
deleteConfig( pid );
delay();
checkConfigurationCount(pid, 0, -1);
TestCase.assertNull( SimpleComponent.INSTANCE );
disableAndCheck( cc );
TestCase.assertNull( SimpleComponent.INSTANCE );
}
/**
* same as test_SimpleComponent_configuration_require except configuration is present when component is enabled.
*/
@Test
public void test_SimpleComponent_configuration_require_initialize() throws Exception
{
final String pid = "SimpleComponent.configuration.require";
deleteConfig( pid );
configure( pid );
delay();
TestCase.assertNull( SimpleComponent.INSTANCE );
ComponentConfigurationDTO cc = getConfigurationsDisabledThenEnable(pid, 1, ComponentConfigurationDTO.ACTIVE).iterator().next();
TestCase.assertNotNull( SimpleComponent.INSTANCE );
TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
deleteConfig( pid );
delay();
checkConfigurationCount(pid, 0, -1);
TestCase.assertNull( SimpleComponent.INSTANCE );
disableAndCheck( cc );
TestCase.assertNull( SimpleComponent.INSTANCE );
}
@Test
public void test_SimpleComponent_dynamic_configuration() throws Exception
{
final String pid = "DynamicConfigurationComponent";
boolean pre13 = true;
boolean recreateOnDelete = true;
dynamicConfigTest(pid, pre13, recreateOnDelete);
}
@Test
public void test_SimpleComponent_dynamic_configuration_13() throws Exception
{
final String pid = "DynamicConfigurationComponent13";
boolean pre13 = false;
boolean recreateOnDelete = false;
dynamicConfigTest(pid, pre13, recreateOnDelete);
}
@Test
public void test_SimpleComponent_dynamic_configuration_flag() throws Exception
{
final String pid = "DynamicConfigurationComponentFlag";
boolean pre13 = true;
boolean recreateOnDelete = false;
dynamicConfigTest(pid, pre13, recreateOnDelete);
}
private void dynamicConfigTest(final String pid, boolean pre13, boolean recreateOnDelete) throws Exception
{
Object pidWithout;
Object pidWith;
if (pre13)
{
pidWithout = pid + ".description";
pidWith = pid;
}
else
{
pidWithout = Collections.singletonList(pid + ".description");
pidWith = Arrays.asList(new String[] {pid + ".description", pid});
}
deleteConfig( pid );
delay();
ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( SimpleComponent.INSTANCE );
TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
TestCase.assertEquals(pidWithout, SimpleComponent.INSTANCE.getProperty(Constants.SERVICE_PID));
final SimpleComponent instance = SimpleComponent.INSTANCE;
configure( pid );
delay();
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
TestCase.assertEquals(pidWith, SimpleComponent.INSTANCE.getProperty(Constants.SERVICE_PID));
deleteConfig( pid );
delay();
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
if (recreateOnDelete)
{
TestCase.assertNotSame( instance, SimpleComponent.INSTANCE );
}
else
{
TestCase.assertSame( instance, SimpleComponent.INSTANCE );
}
TestCase.assertNull( SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
TestCase.assertEquals(pidWithout, SimpleComponent.INSTANCE.getProperty(Constants.SERVICE_PID));
disableAndCheck( cc );
TestCase.assertNull( SimpleComponent.INSTANCE );
}
@Test
public void test_SimpleComponent_dynamic_optional_configuration_with_required_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 = "DynamicConfigurationComponentWithRequiredReference";
deleteConfig( pid );
delay();
// mandatory ref missing --> component unsatisfied
ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.UNSATISFIED);
// dynamically configure without the correct target
configure( pid );
delay();
// mandatory ref missing --> component unsatisfied
findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED);
// dynamically configure with correct target
theConfig.put( targetProp, "(filterprop=" + filterProp + ")" );
configure( pid );
delay();
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( SimpleComponent.INSTANCE );
TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
final SimpleComponent instance = SimpleComponent.INSTANCE;
configure( pid );
delay();
// same instance after reconfiguration
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
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 );
configure( pid );
delay();
// mandatory ref missing --> component unsatisfied
findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED);
deleteConfig( pid );
delay();
// mandatory ref missing --> component unsatisfied
findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED);
disableAndCheck(cc);
TestCase.assertNull( SimpleComponent.INSTANCE );
}
finally
{
theConfig.remove( targetProp );
if ( service != null )
{
service.drop();
}
}
}
/**
* FELIX-3902. Start with filter matching two services, remove one, then change the filter
* to (still) match the other one. 2nd service should remain bound.
*/
@Test
public void test_SimpleComponent_dynamic_optional_configuration_with_required_service2() throws Exception
{
final String targetProp = "ref.target";
final String filterProp1 = "one";
final String filterProp2 = "two";
final SimpleServiceImpl service1 = SimpleServiceImpl.create( bundleContext, "one", 1 ).setFilterProperty( filterProp1 );
final SimpleServiceImpl service2 = SimpleServiceImpl.create( bundleContext, "two", 2 ).setFilterProperty( filterProp2 );
try
{
final String pid = "DynamicConfigurationComponentWithRequiredReference";
deleteConfig( pid );
delay();
// mandatory ref missing --> component unsatisfied
ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.UNSATISFIED);
// dynamically configure without the correct target
configure( pid );
delay();
// mandatory ref missing --> component unsatisfied
findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED);
// dynamically configure with correct target
theConfig.put( targetProp, "(|(filterprop=" + filterProp1 + ")(filterprop=" + filterProp2 + "))" );
configure( pid );
delay();
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( SimpleComponent.INSTANCE );
TestCase.assertEquals( PROP_NAME, SimpleComponent.INSTANCE.getProperty( PROP_NAME ) );
TestCase.assertEquals( pid, SimpleComponent.INSTANCE.getProperty( Constants.SERVICE_PID ) );
final SimpleComponent instance = SimpleComponent.INSTANCE;
configure( pid );
delay();
//remove higher ranked service
if (service2 != null)
{
service2.drop();
}
// same instance after reconfiguration
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
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 with new filter --> active
theConfig.put( targetProp, "(filterprop=" + filterProp1 + ")" );
configure( pid );
delay();
// same instance after reconfiguration
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
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 );
deleteConfig( pid );
delay();
// mandatory ref missing --> component unsatisfied
findComponentConfigurationByName(pid, ComponentConfigurationDTO.UNSATISFIED);
disableAndCheck(cc);
TestCase.assertNull( SimpleComponent.INSTANCE );
}
finally
{
theConfig.remove( targetProp );
if ( service1 != null )
{
service1.drop();
}
}
}
@Test
public void test_SimpleComponent_dynamic_optional_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";
deleteConfig( pid );
delay();
// optional ref missing --> component active
ComponentConfigurationDTO cc = getDisabledConfigurationAndEnable(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotNull( SimpleComponent.INSTANCE );
final SimpleComponent instance = SimpleComponent.INSTANCE;
// dynamically configure without the correct target
configure( pid );
delay();
// optional ref missing --> component active
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
TestCase.assertNull( SimpleComponent.INSTANCE.m_singleRef );
// dynamically configure with correct target
theConfig.put( targetProp, "(filterprop=" + filterProp + ")" );
configure( pid );
delay();
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
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
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
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
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertEquals( instance, SimpleComponent.INSTANCE );
TestCase.assertNull( SimpleComponent.INSTANCE.m_singleRef );
deleteConfig( pid );
delay();
// optional ref missing --> component active
findComponentConfigurationByName(pid, ComponentConfigurationDTO.ACTIVE);
TestCase.assertNotSame( instance, SimpleComponent.INSTANCE );
TestCase.assertNull( SimpleComponent.INSTANCE.m_singleRef );
disableAndCheck(cc);
TestCase.assertNull( SimpleComponent.INSTANCE );
}
finally
{
// Thread.sleep( 60000 );
theConfig.remove( targetProp );
if ( service != null )
{
service.drop();
}
}
}
@Test
public void test_SimpleComponent_factory_configuration() throws Exception
{
final String factoryPid = "FactoryConfigurationComponent";
deleteFactoryConfigurations( factoryPid );
delay();
getConfigurationsDisabledThenEnable(factoryPid, 0, -1);
TestCase.assertTrue( SimpleComponent.INSTANCES.isEmpty() );
// create two factory configurations expecting two components
final String pid0 = createFactoryConfiguration( factoryPid );
final String pid1 = createFactoryConfiguration( factoryPid );
delay();
// expect two active components, //TODO WTF?? only first is active, second is disabled
checkConfigurationCount(factoryPid, 2, ComponentConfigurationDTO.ACTIVE);
// delete a configuration
deleteConfig( pid0 );
delay();
// expect one component
checkConfigurationCount(factoryPid, 1, ComponentConfigurationDTO.ACTIVE);
// delete second configuration
deleteConfig( pid1 );
delay();
checkConfigurationCount(factoryPid, 0, ComponentConfigurationDTO.ACTIVE);
}
/**
* same as test_SimpleComponent_factory_configuration except configurations are present before
* component is enabled to test initialization.
*/
@Test
public void test_SimpleComponent_factory_configuration_initialize() throws Exception
{
final String factoryPid = "FactoryConfigurationComponent";
deleteFactoryConfigurations( factoryPid );
// create two factory configurations expecting two components
final String pid0 = createFactoryConfiguration( factoryPid );
final String pid1 = createFactoryConfiguration( factoryPid );
delay();
getConfigurationsDisabledThenEnable(factoryPid, 2, ComponentConfigurationDTO.ACTIVE);
// delete a configuration
deleteConfig( pid0 );
delay();
// expect one component
checkConfigurationCount(factoryPid, 1, ComponentConfigurationDTO.ACTIVE);
// delete second configuration
deleteConfig( pid1 );
delay();
checkConfigurationCount(factoryPid, 0, ComponentConfigurationDTO.ACTIVE);
}
@Test
public void test_SimpleComponent_factory_configuration_enabled() throws Exception
{
final String factoryPid = "FactoryConfigurationComponent_enabled";
deleteFactoryConfigurations( factoryPid );
delay();
checkConfigurationCount(factoryPid, 0, ComponentConfigurationDTO.ACTIVE);
// no component config exists without configuration
// create two factory configurations expecting two components
final String pid0 = createFactoryConfiguration( factoryPid );
final String pid1 = createFactoryConfiguration( factoryPid );
delay();
// expect two components, all active
checkConfigurationCount(factoryPid, 2, ComponentConfigurationDTO.ACTIVE);
// disable the name component
disableAndCheck( factoryPid );
delay();
// create a configuration
final String pid3 = createFactoryConfiguration( factoryPid );
delay();
getConfigurationsDisabledThenEnable(factoryPid, 3, ComponentConfigurationDTO.ACTIVE);
}
}