You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gn...@apache.org on 2017/03/10 17:22:28 UTC

svn commit: r1786394 - in /felix/branches/scr-1.8.x: pom.xml src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java src/test/java/org/apache/felix/scr/impl/ConfigurationSupportFactoryPidsAndLocationUpdatesTest.java

Author: gnodet
Date: Fri Mar 10 17:22:28 2017
New Revision: 1786394

URL: http://svn.apache.org/viewvc?rev=1786394&view=rev
Log:
FELIX-5576 - added unit test and modified visibility of some elements in ConfigurationSupport

Added:
    felix/branches/scr-1.8.x/src/test/java/org/apache/felix/scr/impl/ConfigurationSupportFactoryPidsAndLocationUpdatesTest.java
Modified:
    felix/branches/scr-1.8.x/pom.xml
    felix/branches/scr-1.8.x/src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java

Modified: felix/branches/scr-1.8.x/pom.xml
URL: http://svn.apache.org/viewvc/felix/branches/scr-1.8.x/pom.xml?rev=1786394&r1=1786393&r2=1786394&view=diff
==============================================================================
--- felix/branches/scr-1.8.x/pom.xml (original)
+++ felix/branches/scr-1.8.x/pom.xml Fri Mar 10 17:22:28 2017
@@ -220,12 +220,18 @@
             <version>1.0.0</version>
             <scope>test</scope>
         </dependency>
-		<dependency>
-			<groupId>org.codehaus.mojo</groupId>
-			<artifactId>animal-sniffer-annotations</artifactId>
-			<version>1.9</version>
-			<scope>compile</scope>
-		</dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.10.19</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>animal-sniffer-annotations</artifactId>
+            <version>1.9</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
     <build>
         <directory>${bundle.build.name}</directory>

Modified: felix/branches/scr-1.8.x/src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java
URL: http://svn.apache.org/viewvc/felix/branches/scr-1.8.x/src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java?rev=1786394&r1=1786393&r2=1786394&view=diff
==============================================================================
--- felix/branches/scr-1.8.x/src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java (original)
+++ felix/branches/scr-1.8.x/src/main/java/org/apache/felix/scr/impl/config/ConfigurationSupport.java Fri Mar 10 17:22:28 2017
@@ -395,7 +395,7 @@ public class ConfigurationSupport implem
 
     }
 
-    private static class ConfigurationInfo
+    protected static class ConfigurationInfo
     {
         private final Dictionary<String, Object> props;
         private final String bundleLocation;
@@ -440,7 +440,7 @@ public class ConfigurationSupport implem
      * @param bundleContext BundleContext to get the CA from
      * @return ConfigurationInfo object containing the info we need from the configuration.
      */
-    private ConfigurationInfo getConfigurationInfo(final TargetedPID pid, ComponentHolder componentHolder,
+    protected ConfigurationInfo getConfigurationInfo(final TargetedPID pid, ComponentHolder componentHolder,
             final BundleContext bundleContext)
     {
         final ServiceReference caRef = bundleContext

Added: felix/branches/scr-1.8.x/src/test/java/org/apache/felix/scr/impl/ConfigurationSupportFactoryPidsAndLocationUpdatesTest.java
URL: http://svn.apache.org/viewvc/felix/branches/scr-1.8.x/src/test/java/org/apache/felix/scr/impl/ConfigurationSupportFactoryPidsAndLocationUpdatesTest.java?rev=1786394&view=auto
==============================================================================
--- felix/branches/scr-1.8.x/src/test/java/org/apache/felix/scr/impl/ConfigurationSupportFactoryPidsAndLocationUpdatesTest.java (added)
+++ felix/branches/scr-1.8.x/src/test/java/org/apache/felix/scr/impl/ConfigurationSupportFactoryPidsAndLocationUpdatesTest.java Fri Mar 10 17:22:28 2017
@@ -0,0 +1,152 @@
+/*
+ * 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.impl;
+
+import junit.framework.TestCase;
+import org.apache.felix.scr.impl.config.ComponentHolder;
+import org.apache.felix.scr.impl.config.ConfigurableComponentHolder;
+import org.apache.felix.scr.impl.config.ConfigurationSupport;
+import org.apache.felix.scr.impl.metadata.ComponentMetadata;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.ConfigurationEvent;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import static org.mockito.Mockito.*;
+
+public class ConfigurationSupportFactoryPidsAndLocationUpdatesTest extends TestCase
+{
+
+    public static final String FACTORY_PID_X = "io.fabric8.gateway.http.mapping";
+    public static final String PID = "io.fabric8.gateway.http.mapping.68a728ef-7dab-4381-9e63-9c69e128f79a";
+
+
+    /**
+     * This test represents a race condition depending on events ordering that can happen at runtime.
+     * A CM_LOCATION_CHANGED event can risk to update the component registry with the wrong pid, with the effect that
+     * subsequent CM_UPDATE event will be discarded since not matching the pid.
+     *
+     * This test simulates this interaction:
+     * - verifies that an UPDATE event correctly triggers an update operation
+     * - forges a LOCATION_UPDATE event
+     * - verifies that after that even, a subsequent UPDATE event still triggers the update operation.
+     *
+     *  https://issues.apache.org/jira/browse/FELIX-5576
+     */
+    public void testFactoryPids()
+    {
+        BundleContext bundleContext = Mockito.mock(BundleContext.class);
+        Bundle bundle = mock(Bundle.class);
+        when(bundleContext.getBundle()).thenReturn(bundle);
+
+        ComponentRegistry componentRegistry = new ComponentRegistry(bundleContext);
+
+        ComponentMetadata metadata = mock(ComponentMetadata.class);
+        BundleComponentActivator activator = mock(BundleComponentActivator.class);
+        ComponentHolder holder = spy(new ConfigurableComponentHolder(activator, metadata));
+
+        when(metadata.getConfigurationPid()).thenReturn(PID);
+        when(metadata.isConfigurationIgnored()).thenReturn(false);
+
+        when(activator.getBundleContext()).thenReturn(bundleContext);
+
+        componentRegistry.registerComponentHolder(key(1, "bundle1"), holder);
+
+        when(bundleContext.registerService(any(String[].class), any(), any(Dictionary.class))).thenReturn(null);
+        //wrong visibility for ConfigurationSupport::getConfigurationInfo, I have to subclass to re-expose
+        ConfigurationSupport support = spy(new ConfigurationSupport(bundleContext, componentRegistry){
+            ConfigurationInfo configurationInfo;
+            @Override
+            public ConfigurationInfo getConfigurationInfo(final TargetedPID pid, ComponentHolder componentHolder,
+                                                          final BundleContext bundleContext){
+                if(this.configurationInfo == null){
+                    ConfigurationInfo configurationInfo = mock(ConfigurationInfo.class);
+                    Dictionary<String, Object> props = new Hashtable<String, Object>();
+                    when(configurationInfo.getProps()).thenReturn(props);
+                    this.configurationInfo = configurationInfo;
+                }
+
+                return configurationInfo;
+            }
+
+        });
+
+
+        ConfigurationEvent event = null;
+
+        event = mockAnEvent(ConfigurationEvent.CM_UPDATED);
+
+        // this represents the race condition
+        doReturn(null).when(holder).getConfigurationTargetedPID(any(TargetedPID.class));
+
+        //emit event
+        support.configurationEvent(event);
+
+        verify(holder, times(1)).configurationUpdated(any(String.class), any(Dictionary.class), anyLong(), any(TargetedPID.class));
+
+        event = mockAnEvent(ConfigurationEvent.CM_LOCATION_CHANGED);
+
+        //emit event
+        support.configurationEvent(event);
+
+        // here we are removing the subbed call for the value seen during race conditions
+        Mockito.reset(holder);
+
+        event = mockAnEvent(ConfigurationEvent.CM_UPDATED);
+
+        //emit event
+        support.configurationEvent(event);
+
+
+        try {
+            verify(holder, times(1)).configurationUpdated(any(String.class), any(Dictionary.class), anyLong(), any(TargetedPID.class));
+        } catch (MockitoAssertionError e) {
+            MockitoAssertionError err = new MockitoAssertionError("Was expecting a call to holder.configurationUpdated().");
+            err.initCause(e);
+            throw err;
+        }
+
+    }
+
+    protected ConfigurationEvent mockAnEvent(int eventType) {
+        ConfigurationEvent event;
+        event = mock(ConfigurationEvent.class);
+        when(event.getPid()).thenReturn(FACTORY_PID_X);
+        when(event.getFactoryPid()).thenReturn(PID);
+        when(event.getType()).thenReturn(eventType);
+        return event;
+    }
+
+    private static ComponentRegistryKey key( final long bundleId, final String name )
+    {
+        return new ComponentRegistryKey( new MockBundle()
+        {
+            //            @Override
+            public long getBundleId()
+            {
+                return bundleId;
+            }
+        }, name );
+    }
+
+}
\ No newline at end of file