You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2013/11/29 12:06:31 UTC

svn commit: r1546539 - in /felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api: AdapterWithModifiedInstanceBoundDependencyTest.java ModifiedBundleDependencyTest.java

Author: pderop
Date: Fri Nov 29 11:06:31 2013
New Revision: 1546539

URL: http://svn.apache.org/r1546539
Log:
Added tests for the FELIX-4334 issue.

Added:
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/AdapterWithModifiedInstanceBoundDependencyTest.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/ModifiedBundleDependencyTest.java

Added: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/AdapterWithModifiedInstanceBoundDependencyTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/AdapterWithModifiedInstanceBoundDependencyTest.java?rev=1546539&view=auto
==============================================================================
--- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/AdapterWithModifiedInstanceBoundDependencyTest.java (added)
+++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/AdapterWithModifiedInstanceBoundDependencyTest.java Fri Nov 29 11:06:31 2013
@@ -0,0 +1,159 @@
+/*
+ * 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.dm.test.integration.api;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.test.components.Ensure;
+import org.apache.felix.dm.test.integration.common.TestBase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+/**
+ * Test for FELIX-4334 issue.
+ * 
+ * Three components: A, B and C
+ * 
+ * - A provided with property foo=bar
+ * - B adapts A, B has no filters on A, and B.init() method adds an instance bound required dependency to C.
+ * - C depends on A(foo=bar)
+ * - Now someone modifies the service properties of A: foo=bar2
+ * - As a result of that, C becomes unavailable and is unbound from B.
+ * - Since B has an instance bound required dependency to C: B should not be destroyed: it should be called in B.stop(), B.remove(C), B.change(A, "foo=bar2))
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@RunWith(PaxExam.class)
+public class AdapterWithModifiedInstanceBoundDependencyTest extends TestBase {
+    public static interface A {
+    }
+    
+    static class AImpl implements A {
+        final Ensure m_e;
+        AImpl(Ensure e) {
+            m_e = e;
+        }        
+    }
+    
+    public static interface C {
+    }
+
+    static class CImpl implements C {
+        volatile A m_a;
+    }
+    
+    public static interface B {
+    }
+    
+    static class BImpl implements B {
+        final Ensure m_e;
+        volatile A m_a;
+        volatile C m_c;
+        
+        BImpl(Ensure e) {
+            m_e = e;
+        }
+        
+        public void add(A a) {
+            m_e.step(1);
+        }
+
+        void init(Component c) {
+            m_e.step(2);
+            DependencyManager dm = c.getDependencyManager();
+            c.add(dm.createServiceDependency().setService(C.class).setRequired(true).setInstanceBound(true).setCallbacks("add", "remove"));
+        }      
+        
+        public void add(C c) {
+            m_e.step(3);
+        }
+        
+        public void start() {
+            m_e.step(4);            
+        }
+        
+        public void stop() { // C becomes unsatisfied when A properties are changed to foo=bar2
+            m_e.step(5);
+        }
+
+        public void remove(C c) {
+            m_e.step(6);
+        }
+
+        public void change(Map properties, A a) {
+            Assert.assertEquals("bar2", properties.get("foo"));
+            m_e.step(7);
+        }
+        
+        public void destroy() {
+            m_e.step(8);
+        }
+
+        public void remove(A a) {   
+            m_e.step(9);
+        }                    
+    }
+    
+    @Test
+    public void testAdapterWithChangedInstanceBoundDependency() {
+        DependencyManager m = new DependencyManager(context);
+        Ensure e = new Ensure();
+
+        Dictionary props = new Hashtable();
+        props.put("foo", "bar");
+        Component a = m.createComponent()
+                .setImplementation(new AImpl(e))
+                .setInterface(A.class.getName(), props);
+        
+        Component b = m.createAdapterService(A.class, null, "add", "change", "remove")
+                .setInterface(B.class.getName(), null)
+                .setImplementation(new BImpl(e));                
+        
+        Component c = m.createComponent()
+                .setImplementation(new CImpl())
+                .setInterface(C.class.getName(), null)
+                .add(m.createServiceDependency().setService(A.class, "(foo=bar)").setRequired(true));                     
+              
+        m.add(a);
+        m.add(c);
+        m.add(b);
+        
+        e.waitForStep(4, 5000);
+        
+        System.out.println("changing A props ...");
+        props = new Hashtable();
+        props.put("foo", "bar2");
+        a.setServiceProperties(props);
+        
+        e.waitForStep(7, 5000);                
+        
+        m.remove(c);
+        m.remove(a);
+        m.remove(b);
+        
+        e.waitForStep(9, 5000);                
+    }
+}

Added: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/ModifiedBundleDependencyTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/ModifiedBundleDependencyTest.java?rev=1546539&view=auto
==============================================================================
--- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/ModifiedBundleDependencyTest.java (added)
+++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/integration/api/ModifiedBundleDependencyTest.java Fri Nov 29 11:06:31 2013
@@ -0,0 +1,145 @@
+/*
+ * 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.dm.test.integration.api;
+
+import junit.framework.Assert;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.test.components.Ensure;
+import org.apache.felix.dm.test.integration.common.TestBase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+
+/**
+ * Test for FELIX-4334 issue.
+ * 
+ * Two components: A, B
+ * 
+ * - A provided.
+ * - B has a bundle dependency on the dependency manager shell bundle, which is currently stopped.
+ * - B has an instance bound dependency on A.
+ * - Now unregister A.
+ * - As a result of that, B becomes unavailable and is unbound from A. But B is not destroyed, because A dependency 
+ *   is "instance bound". So B is still bound to the bundle dependency.
+ * - Now, someone starts the dependency manager shell bundle: B then shall be called in its "changed" callback.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@RunWith(PaxExam.class)
+public class ModifiedBundleDependencyTest extends TestBase {
+    public static interface A {
+    }
+    
+    static class AImpl implements A {
+    }
+        
+    public static interface B {
+    }
+    
+    static class BImpl implements B {
+        final Ensure m_e;
+        
+        BImpl(Ensure e) {
+            m_e = e;
+        }
+        
+        public void add(Bundle dmTest) {
+            m_e.step(1);
+        }
+
+        void init(Component c) {
+            m_e.step(2);
+            DependencyManager dm = c.getDependencyManager();
+            c.add(dm.createServiceDependency().setService(A.class).setRequired(true).setInstanceBound(true).setCallbacks("add", "remove"));
+        }      
+        
+        public void add(A a) {
+            m_e.step(3);
+        }
+        
+        public void start() {
+            m_e.step(4);            
+        }
+        
+        public void stop() {
+            m_e.step(5);
+        }
+
+        public void remove(A a) {
+            m_e.step(6);
+        }
+
+        public void change(Bundle dmTest) { // called two times: one for STARTING, one for STARTED
+            m_e.step(); 
+        }
+        
+        public void destroy() {
+            m_e.step(9);
+        }
+
+        public void remove(Bundle dmTest) {   
+            m_e.step(10);
+        }                    
+    }
+    
+    @Test
+    public void testAdapterWithChangedInstanceBoundDependency() {
+        DependencyManager m = new DependencyManager(context);
+        Ensure e = new Ensure();
+
+        Component a = m.createComponent()
+                .setImplementation(new AImpl())
+                .setInterface(A.class.getName(), null);
+        
+        Component b = m.createComponent()
+                .setInterface(B.class.getName(), null)
+                .setImplementation(new BImpl(e))
+                .add(m.createBundleDependency()
+                        .setFilter("(Bundle-SymbolicName=org.apache.felix.dependencymanager.shell)")
+                        .setStateMask(Bundle.INSTALLED|Bundle.ACTIVE|Bundle.RESOLVED|Bundle.STARTING)
+                        .setRequired(true)
+                        .setCallbacks("add", "change", "remove"));
+                    
+        Bundle dmtest = getBundle("org.apache.felix.dependencymanager.shell");
+        try {
+            dmtest.stop();
+        } catch (BundleException e1) {
+            Assert.fail("couold not find dependencymanager shell bundle");
+        }
+        
+        m.add(a);
+        m.add(b);
+        
+        e.waitForStep(4, 5000);        
+        m.remove(a); // B will loose A and will enter into "waiting for required (instantiated)" state.
+        System.out.println("Starting dependency manager shell ...");        
+        try {
+            dmtest.start();
+        } catch (BundleException e1) {
+            Assert.fail("could not start dependencymanager shell bundle");
+        }
+        e.waitForStep(7, 5000);     
+        m.remove(b);        
+        e.waitForStep(10, 5000);                
+    }
+}