/*
* 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 junit.framework.TestCase;
import org.apache.felix.scr.integration.components.circular.A;
import org.apache.felix.scr.integration.components.circular.B;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
/**
* @version $Rev$ $Date$
*/
@RunWith(JUnit4TestRunner.class)
public class CircularReferenceTest extends ComponentTestBase
{
static
{
// uncomment to enable debugging of this test class
// paxRunnerVmOption = DEBUG_VM_OPTION;
descriptorFile = "/integration_test_circular.xml";
COMPONENT_PACKAGE = COMPONENT_PACKAGE + ".circular";
}
/**
* A and B have mandatory dependencies on each other. Neither should start.
*/
@Test
public void test_A11_B11()
{
String componentNameA = "1.A.1.1.dynamic";
final ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.UNSATISFIED_REFERENCE );
String componentNameB = "1.B.1.1.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.UNSATISFIED_REFERENCE );
}
/**
* A > 1.1 > B > 0..n > A Both should start (A first), but B should not have an A reference.
* @throws InvalidSyntaxException
*/
@Test
public void test_A11_B0n_immediate_A_first() throws InvalidSyntaxException
{
String componentNameA = "2.A.1.1.dynamic";
final ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.SATISFIED | ComponentConfigurationDTO.ACTIVE );
A a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
delay();
String componentNameB = "2.B.0.n.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.ACTIVE );
B b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
}
/**
* A > 1.1 > B > 0..n > A Both should start (B first), and B should have an A reference.
* @throws InvalidSyntaxException
*/
@Test
public void test_A11_B0n_immediate_B_first() throws InvalidSyntaxException
{
String componentNameA = "3.A.1.1.dynamic";
final ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.ACTIVE );
A a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
delay();
String componentNameB = "3.B.0.n.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.ACTIVE );
B b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
}
/**
* A > 1.1 > B > 0..n > A Both should start, but B should not have an A reference.
*/
@Test
public void test_A11_B0n_delayed_A_first() throws InvalidSyntaxException
{
String componentNameA = "4.A.1.1.dynamic";
final ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.SATISFIED );
String componentNameB = "4.B.0.n.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.SATISFIED );
delay();
A a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
delay(); //async binding of a to b after circular ref detected
B b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
}
/**
* A > 1.1 > B > 0..n > A Both should start, but B should not have an A reference.
*/
@Test
public void test_A11_B0n_delayed_B_first() throws Exception
{
String componentNameA = "4.A.1.1.dynamic";
ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.SATISFIED );
String componentNameB = "4.B.0.n.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.SATISFIED);
ServiceReference[] serviceReferencesB = bundleContext.getServiceReferences( B.class.getName(), "(service.pid=" + componentNameB + ")" );
TestCase.assertEquals( 1, serviceReferencesB.length );
ServiceReference serviceReferenceB = serviceReferencesB[0];
Object serviceB = bundleContext.getService( serviceReferenceB );
assertNotNull( serviceB );
ServiceReference[] serviceReferencesA = bundleContext.getServiceReferences( A.class.getName(), "(service.pid=" + componentNameA + ")" );
TestCase.assertEquals( 1, serviceReferencesA.length );
ServiceReference serviceReferenceA = serviceReferencesA[0];
Object serviceA = bundleContext.getService( serviceReferenceA );
assertNotNull( serviceA );
delay();
A a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
B b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
//disabling (removing the A service registration) and re-enabling will
//result in a service event to B, so B will bind A.
disableAndCheck(componentA);
delay();
enableAndCheck(componentA.description);
delay();
//new component.id, refetch configuration.
componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.ACTIVE );
a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
}
/**
* A > 1.1 > B > 0..1 > A Both should start (A first), but B should not have an A reference.
* @throws InvalidSyntaxException
*/
@Test
public void test_A11_B01_immediate_A_first() throws InvalidSyntaxException
{
String componentNameA = "5.A.1.1.dynamic";
final ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.SATISFIED | ComponentConfigurationDTO.ACTIVE );
A a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
String componentNameB = "5.B.0.1.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.ACTIVE );
B b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
}
/**
* A > 1.1 > B > 0..1 > A Both should start (B first), and B should have an A reference.
* @throws InvalidSyntaxException
*/
@Test
public void test_A11_B01_immediate_B_first() throws InvalidSyntaxException
{
String componentNameA = "6.A.1.1.dynamic";
final ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.ACTIVE );
A a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
String componentNameB = "6.B.0.1.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.ACTIVE );
B b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
}
/**
* A > 1.1 > B > 0..1 > A Both should start, but B should not have an A reference.
*/
@Test
public void test_A11_B01_delayed_A_first() throws InvalidSyntaxException
{
String componentNameA = "7.A.1.1.dynamic";
final ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.SATISFIED );
String componentNameB = "7.B.0.1.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.SATISFIED );
ServiceReference[] serviceReferences = bundleContext.getServiceReferences( A.class.getName(), "(service.pid=" + componentNameA + ")" );
TestCase.assertEquals( 1, serviceReferences.length );
ServiceReference serviceReference = serviceReferences[0];
Object service = bundleContext.getService( serviceReference );
assertNotNull( service );
delay();
A a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
B b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
}
/**
* A > 1.1 > B > 0..1 > A Both should start, but B should not have an A reference.
*/
@Test
public void test_A11_B01_delayed_B_first() throws Exception
{
String componentNameA = "7.A.1.1.dynamic";
ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.SATISFIED );
String componentNameB = "7.B.0.1.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.SATISFIED );
ServiceReference[] serviceReferencesB = bundleContext.getServiceReferences( B.class.getName(), "(service.pid=" + componentNameB + ")" );
TestCase.assertEquals( 1, serviceReferencesB.length );
ServiceReference serviceReferenceB = serviceReferencesB[0];
Object serviceB = bundleContext.getService( serviceReferenceB );
assertNotNull( serviceB );
ServiceReference[] serviceReferencesA = bundleContext.getServiceReferences( A.class.getName(), "(service.pid=" + componentNameA + ")" );
TestCase.assertEquals( 1, serviceReferencesA.length );
ServiceReference serviceReferenceA = serviceReferencesA[0];
Object serviceA = bundleContext.getService( serviceReferenceA );
assertNotNull( serviceA );
delay();
A a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
B b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
//disabling (removing the A service registration) and re-enabling will
//result in a service event to B, so B will bind A.
disableAndCheck(componentA);
delay();
enableAndCheck(componentA.description);
delay();
//new component.id, refetch configuration.
componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.ACTIVE );
a = getServiceFromConfiguration(componentA, A.class);
assertEquals( 1, a.getBs().size());
b = getServiceFromConfiguration(componentB, B.class);
assertEquals( 1, b.getAs().size() );
}
/**
* A > 1.1 > B > 0..n > A Both should start (B first) and both should have references
* @throws InvalidSyntaxException
*/
@Test
public void test_A11_immediate_B0n_delayed_B_first() throws InvalidSyntaxException
{
String componentNameB = "8.B.0.n.dynamic";
final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.SATISFIED | ComponentConfigurationDTO.ACTIVE );
ServiceReference[] serviceReferencesB = bundleContext.getServiceReferences( B.class.getName(), "(service.pid=" + componentNameB + ")" );
TestCase.assertEquals( 1, serviceReferencesB.length );
ServiceReference<B> serviceReferenceB = serviceReferencesB[0];
B b = bundleContext.getService( serviceReferenceB );
String componentNameA = "8.A.1.1.static";
ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.SATISFIED | ComponentConfigurationDTO.ACTIVE );
ServiceReference[] serviceReferencesA = bundleContext.getServiceReferences( A.class.getName(), "(service.pid=" + componentNameA + ")" );
TestCase.assertEquals( 1, serviceReferencesA.length );
ServiceReference<A> serviceReferenceA = serviceReferencesA[0];
A a = bundleContext.getService( serviceReferenceA );
assertNotNull( a );
assertEquals( 1, a.getBs().size());
delay();
assertEquals( 1, b.getAs().size() );
assertNotNull( b.getAs().get(0) );
}
}