Added a test case which reproduces the issue described in FELIX-4984.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1701869 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
index 9854c33..8351ceb 100644
--- a/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
+++ b/scr/src/test/java/org/apache/felix/scr/integration/ComponentTestBase.java
@@ -155,6 +155,7 @@
                                             "org.apache.felix.scr.integration.components.concurrency," +
                                             "org.apache.felix.scr.integration.components.deadlock," +
                                             "org.apache.felix.scr.integration.components.felix3680," +
+                                            "org.apache.felix.scr.integration.components.felix4984," +
                                             "org.apache.felix.scr.integration.components.felix3680_2");
         builder.setHeader("Import-Package", "org.apache.felix.scr.component");
         builder.setHeader("Bundle-ManifestVersion", "2");
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/Felix4984Test.java b/scr/src/test/java/org/apache/felix/scr/integration/Felix4984Test.java
new file mode 100644
index 0000000..7a03fbc
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/integration/Felix4984Test.java
@@ -0,0 +1,85 @@
+package org.apache.felix.scr.integration;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+
+import org.apache.felix.scr.integration.components.felix4984.A;
+import org.apache.felix.scr.integration.components.felix4984.B;
+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.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.runtime.dto.ComponentConfigurationDTO;
+import org.osgi.service.log.LogService;
+
+import junit.framework.TestCase;
+
+
+@RunWith(JUnit4TestRunner.class)
+public class Felix4984Test extends ComponentTestBase
+{
+    static
+    {
+        descriptorFile = "/integration_test_FELIX_4984.xml";
+        COMPONENT_PACKAGE = COMPONENT_PACKAGE + ".felix4984";
+        DS_LOGLEVEL = "debug";
+    }
+
+    /**
+     * A > 1.1 > B > 0..n > A 
+     * This test validates that A is bound to one B instance. See FELIX-4984 for more informations.
+     */
+    @Test
+    public void test_A11_B0n_delayed_B_first_ABoundToAtMostOneB() throws Exception
+    {
+        Bundle bundle = findABBundle(bundleContext);
+        bundle.stop();
+        
+        for (int i = 0; i < 1000; i ++) {   
+        	bundle.start();
+
+            String componentNameA = "felix4984.A.1.1.dynamic";
+            ComponentConfigurationDTO componentA = findComponentConfigurationByName( componentNameA, ComponentConfigurationDTO.SATISFIED );
+
+            String componentNameB = "felix4984.B.0.n.dynamic";
+            final ComponentConfigurationDTO componentB = findComponentConfigurationByName( componentNameB, ComponentConfigurationDTO.SATISFIED);
+
+            ServiceReference[] serviceReferencesB = bundleContext.getServiceReferences( B.class.getName(), "(service.pid=" + componentNameB + ")" );
+            assertNotNull( serviceReferencesB );
+            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 );
+
+            A a = getServiceFromConfiguration(componentA, A.class);
+            assertABoundToOneB(a);
+
+            bundle.stop();
+        }
+    }
+    
+    private Bundle findABBundle(BundleContext ctx) {
+        for (Bundle b : ctx.getBundles()) {
+            if (b.getSymbolicName().equals("simplecomponent")) {
+                return b;
+            }
+        }
+        throw new IllegalStateException("bundle \"simplecomponent\" not found");
+    }
+    
+    private void assertABoundToOneB(A a) {
+        if (a.getBs().size() != 1) {
+            log.log(LogService.LOG_WARNING, "detected problem ...");
+            a.dumpStackTracesWhenBWasBound(log);
+        }
+        assertEquals( 1, a.getBs().size());
+    }
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/components/felix4984/A.java b/scr/src/test/java/org/apache/felix/scr/integration/components/felix4984/A.java
new file mode 100644
index 0000000..e872ebf
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/integration/components/felix4984/A.java
@@ -0,0 +1,69 @@
+/*
+ * 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.components.felix4984;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.log.LogService;
+
+/**
+ * @version $Rev: 1350816 $ $Date: 2012-06-15 23:37:30 +0200 (Fri, 15 Jun 2012) $
+ */
+public class A
+{
+
+    private List<B> bs = new ArrayList<B>();
+    private List<Exception> bsStackTraces = new ArrayList();
+
+    private boolean activated;
+
+    private void activate(ComponentContext cc)
+    {
+        activated = true;
+    }
+
+    private void setB(B b)
+    {
+        bs.add( b );
+        bsStackTraces.add(new Exception());
+    }
+
+    private void unsetB(B b)
+    {
+        bs.remove( b );
+        bsStackTraces.remove(bsStackTraces.size()-1);
+    }
+
+    public List<B> getBs()
+    {
+        return bs;
+    }
+    
+    public void dumpStackTracesWhenBWasBound(LogService log) {
+        log.log(LogService.LOG_WARNING, "Stack traces when B was bound:");
+        for (Exception e : bsStackTraces) {
+            log.log(LogService.LOG_WARNING, "stack trace:", e);
+        }
+    }
+
+}
diff --git a/scr/src/test/java/org/apache/felix/scr/integration/components/felix4984/B.java b/scr/src/test/java/org/apache/felix/scr/integration/components/felix4984/B.java
new file mode 100644
index 0000000..0e504e0
--- /dev/null
+++ b/scr/src/test/java/org/apache/felix/scr/integration/components/felix4984/B.java
@@ -0,0 +1,24 @@
+package org.apache.felix.scr.integration.components.felix4984;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class B
+{
+    private List<A> as = new ArrayList<A>();
+
+    private void setA(A a)
+    {
+        as.add( a );
+    }
+
+    private void unsetA(A a)
+    {
+        as.remove( a );
+    }
+
+    public List<A> getAs()
+    {
+        return as;
+    }
+}
diff --git a/scr/src/test/resources/integration_test_FELIX_4984.xml b/scr/src/test/resources/integration_test_FELIX_4984.xml
new file mode 100644
index 0000000..500924d
--- /dev/null
+++ b/scr/src/test/resources/integration_test_FELIX_4984.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0">
+
+    <!-- A 1.1 dynamic. B 0..n dynamic  both delayed. -->
+    <scr:component name="felix4984.A.1.1.dynamic"
+        enabled="true"
+        immediate="false"
+        configuration-policy="ignore">
+        <implementation class="org.apache.felix.scr.integration.components.felix4984.A" />
+        <service>
+            <provide interface="org.apache.felix.scr.integration.components.felix4984.A" />
+        </service>
+        <reference
+            name="b"
+            interface="org.apache.felix.scr.integration.components.felix4984.B"
+            cardinality="1..1"
+            policy="dynamic"
+            bind="setB"
+            unbind="unsetB"
+            target="(service.pid=felix4984.B.0.n.dynamic)"
+        />
+        <property name="service.pid" value="felix4984.A.1.1.dynamic" />
+    </scr:component>
+    
+    <scr:component name="felix4984.B.0.n.dynamic"
+        enabled="true"
+        immediate="false"
+        configuration-policy="ignore">
+        <implementation class="org.apache.felix.scr.integration.components.felix4984.B" />
+        <service>
+            <provide interface="org.apache.felix.scr.integration.components.felix4984.B" />
+        </service>
+        <reference
+            name="a"
+            interface="org.apache.felix.scr.integration.components.felix4984.A"
+            cardinality="0..n"
+            policy="dynamic"
+            bind="setA"
+            unbind="unsetA"
+            target="(service.pid=felix4984.A.1.1.dynamic)"
+        />
+        <property name="service.pid" value="felix4984.B.0.n.dynamic" />
+    </scr:component>
+    
+</components>
\ No newline at end of file