You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2009/08/31 15:43:32 UTC

svn commit: r809592 - in /felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration: ./ helper/

Author: fmeschbe
Date: Mon Aug 31 13:43:32 2009
New Revision: 809592

URL: http://svn.apache.org/viewvc?rev=809592&view=rev
Log:
FELIX-1545 integration testcases exhibiting the concurrency issues of
duplicate and lost configuration update

Added:
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigUpdateStressTest.java   (with props)
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ConfigureThread.java   (with props)
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryThread.java   (with props)
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceThread.java   (with props)
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/TestThread.java   (with props)
    felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/UpdateThreadSignalTask.java   (with props)

Added: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigUpdateStressTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigUpdateStressTest.java?rev=809592&view=auto
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigUpdateStressTest.java (added)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigUpdateStressTest.java Mon Aug 31 13:43:32 2009
@@ -0,0 +1,227 @@
+/*
+ * 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.cm.integration;
+
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.cm.integration.helper.ConfigureThread;
+import org.apache.felix.cm.integration.helper.ManagedServiceFactoryThread;
+import org.apache.felix.cm.integration.helper.ManagedServiceThread;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+
+
+/**
+ * The <code>ConfigUpdateStressTest</code> class tests the issues related to
+ * concurrency between configuration update (Configuration.update(Dictionary))
+ * and ManagedService[Factory] registration.
+ * <p>
+ * @see <a href="https://issues.apache.org/jira/browse/FELIX-1545">FELIX-1545</a>
+ */
+@RunWith(JUnit4TestRunner.class)
+public class ConfigUpdateStressTest extends ConfigurationTestBase
+{
+
+    @Test
+    public void test_ManagedService_race_condition_test()
+    {
+        int counterMax = 30;
+        int failures = 0;
+
+        for ( int counter = 0; counter < counterMax; counter++ )
+        {
+            try
+            {
+                single_test_ManagedService_race_condition_test( counter );
+            }
+            catch ( Throwable ae )
+            {
+                System.out.println( "single_test_ManagedService_race_condition_test#" + counter + " failed: " + ae );
+                ae.printStackTrace( System.out );
+                failures++;
+            }
+        }
+
+        // fail the test if there is at least one failure
+        if ( failures != 0 )
+        {
+            TestCase.fail( failures + "/" + counterMax + " iterations failed" );
+        }
+    }
+
+
+    @Test
+    public void test_ManagedServiceFactory_race_condition_test()
+    {
+        int counterMax = 30;
+        int failures = 0;
+
+        for ( int counter = 0; counter < counterMax; counter++ )
+        {
+            try
+            {
+                single_test_ManagedServiceFactory_race_condition_test( counter );
+            }
+            catch ( Throwable ae )
+            {
+                System.out.println( "single_test_ManagedServiceFactory_race_condition_test#" + counter + " failed: "
+                    + ae );
+                ae.printStackTrace( System.out );
+                failures++;
+            }
+        }
+
+        // fail the test if there is at least one failure
+        if ( failures != 0 )
+        {
+            TestCase.fail( failures + "/" + counterMax + " iterations failed" );
+        }
+    }
+
+
+    // runs a single test to encounter the race condition between ManagedService
+    // registration and Configuration.update(Dictionary)
+    // This test creates/updates configuration and registers a ManagedService
+    // almost at the same time. The ManagedService must receive the
+    // configuration
+    // properties exactly once.
+    private void single_test_ManagedService_race_condition_test( final int counter ) throws IOException,
+        InterruptedException
+    {
+
+        final String pid = "single_test_ManagedService_race_condition_test." + counter;
+
+        final ConfigureThread ct = new ConfigureThread( getConfigurationAdmin(), pid, false );
+        final ManagedServiceThread mt = new ManagedServiceThread( bundleContext, pid );
+
+        try
+        {
+            // start threads -- both are waiting to be triggered
+            ct.start();
+            mt.start();
+
+            // trigger for action
+            ct.trigger();
+            mt.trigger();
+
+            // wait for threads to terminate
+            ct.join();
+            mt.join();
+
+            // wait for all tasks to terminate
+            delay();
+
+            final ArrayList<Dictionary> configs = mt.getConfigs();
+
+            // terminate mt to ensure no further config updates
+            mt.cleanup();
+
+            if ( configs.size() == 0 )
+            {
+                TestCase.fail( "No configuration provided to ManagedService at all" );
+            }
+            else if ( configs.size() == 2 )
+            {
+                final Dictionary props0 = configs.get( 0 );
+                final Dictionary props1 = configs.get( 1 );
+
+                TestCase.assertNull( "Expected first (of two) updates without configuration", props0 );
+                TestCase.assertNotNull( "Expected second (of two) updates with configuration", props1 );
+            }
+            else if ( configs.size() == 1 )
+            {
+                final Dictionary props = configs.get( 0 );
+                TestCase.assertNotNull( "Expected non-null configuration: " + props, props );
+            }
+            else
+            {
+                TestCase.fail( "Unexpectedly got " + configs.size() + " updated" );
+            }
+        }
+        finally
+        {
+            mt.cleanup();
+            ct.cleanup();
+        }
+    }
+
+
+    // runs a single test to encounter the race condition between
+    // ManagedServiceFactory registration and Configuration.update(Dictionary)
+    // This test creates/updates configuration and registers a
+    // ManagedServiceFactory almost at the same time. The ManagedServiceFactory
+    // must receive the configuration properties exactly once.
+    private void single_test_ManagedServiceFactory_race_condition_test( final int counter ) throws IOException,
+        InterruptedException
+    {
+
+        final String factoryPid = "single_test_ManagedServiceFactory_race_condition_test." + counter;
+
+        final ConfigureThread ct = new ConfigureThread( getConfigurationAdmin(), factoryPid, true );
+        final ManagedServiceFactoryThread mt = new ManagedServiceFactoryThread( bundleContext, factoryPid );
+
+        try
+        {
+            // start threads -- both are waiting to be triggered
+            ct.start();
+            mt.start();
+
+            // trigger for action
+            ct.trigger();
+            mt.trigger();
+
+            // wait for threads to terminate
+            ct.join();
+            mt.join();
+
+            // wait for all tasks to terminate
+            delay();
+
+            final ArrayList<Dictionary> configs = mt.getConfigs();
+
+            // terminate mt to ensure no further config updates
+            mt.cleanup();
+
+            if ( configs.size() == 0 )
+            {
+                TestCase.fail( "No configuration provided to ManagedServiceFactory at all" );
+            }
+            else if ( configs.size() == 1 )
+            {
+                final Dictionary props = configs.get( 0 );
+                TestCase.assertNotNull( "Expected non-null configuration: " + props, props );
+            }
+            else
+            {
+                TestCase.fail( "Unexpectedly got " + configs.size() + " updated" );
+            }
+        }
+        finally
+        {
+            mt.cleanup();
+            ct.cleanup();
+        }
+    }
+}

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigUpdateStressTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/ConfigUpdateStressTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ConfigureThread.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ConfigureThread.java?rev=809592&view=auto
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ConfigureThread.java (added)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ConfigureThread.java Mon Aug 31 13:43:32 2009
@@ -0,0 +1,92 @@
+/*
+ * 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.cm.integration.helper;
+
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+
+/**
+ * The <code>ConfigureThread</code> class is extends the {@link TestThread} for
+ * use as the configuration creator and updater in the
+ * {@link org.apache.felix.cm.integration.ConfigUpdateStressTest}.
+ */
+public class ConfigureThread extends TestThread
+{
+    private final Configuration config;
+
+    private final Hashtable<String, Object> props;
+
+
+    public ConfigureThread( final ConfigurationAdmin configAdmin, final String pid, final boolean isFactory )
+        throws IOException
+    {
+        // ensure configuration and disown it
+        final Configuration config;
+        if ( isFactory )
+        {
+            config = configAdmin.createFactoryConfiguration( pid );
+        }
+        else
+        {
+            config = configAdmin.getConfiguration( pid );
+        }
+        config.setBundleLocation( null );
+
+        Hashtable<String, Object> props = new Hashtable<String, Object>();
+        props.put( "prop1", "aValue" );
+        props.put( "prop2", 4711 );
+
+        this.config = config;
+        this.props = props;
+    }
+
+
+    @Override
+    public void doRun()
+    {
+        try
+        {
+            config.update( props );
+            System.out.println( "   " + config.getPid() + " - Configuration updated" );
+        }
+        catch ( IOException ioe )
+        {
+            // TODO: log !!
+        }
+    }
+
+
+    @Override
+    public void cleanup()
+    {
+        try
+        {
+            config.delete();
+        }
+        catch ( IOException ioe )
+        {
+            // TODO: log !!
+        }
+    }
+}
\ No newline at end of file

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ConfigureThread.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ConfigureThread.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryThread.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryThread.java?rev=809592&view=auto
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryThread.java (added)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryThread.java Mon Aug 31 13:43:32 2009
@@ -0,0 +1,113 @@
+/*
+ * 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.cm.integration.helper;
+
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+
+/**
+ * The <code>ManagedServiceFactoryThread</code> class is a ManagedServiceFactory
+ * and extends the {@link TestThread} for use in the
+ * {@link org.apache.felix.cm.integration.ConfigUpdateStressTest}.
+ */
+public class ManagedServiceFactoryThread extends TestThread implements ManagedServiceFactory
+{
+
+    private final BundleContext bundleContext;
+
+    private final Hashtable<String, Object> serviceProps;
+
+    private ServiceRegistration service;
+
+    private final ArrayList<Dictionary> configs;
+
+    private boolean configured;
+
+
+    public ManagedServiceFactoryThread( final BundleContext bundleContext, final String pid )
+    {
+        Hashtable<String, Object> serviceProps = new Hashtable<String, Object>();
+        serviceProps.put( Constants.SERVICE_PID, pid );
+
+        this.bundleContext = bundleContext;
+        this.serviceProps = serviceProps;
+        this.configs = new ArrayList<Dictionary>();
+    }
+
+
+    public ArrayList<Dictionary> getConfigs()
+    {
+        synchronized ( configs )
+        {
+            return new ArrayList<Dictionary>( configs );
+        }
+    }
+
+
+    public boolean isConfigured()
+    {
+        return configured;
+    }
+
+
+    @Override
+    public void doRun()
+    {
+        service = bundleContext.registerService( ManagedServiceFactory.class.getName(), this, serviceProps );
+        System.out.println( "   " + serviceProps.get( Constants.SERVICE_PID ) + " - ManagedServiceFactory registered" );
+    }
+
+
+    @Override
+    public void cleanup()
+    {
+        if ( service != null )
+        {
+            service.unregister();
+            service = null;
+        }
+    }
+
+
+    public void deleted( String pid )
+    {
+        synchronized ( configs )
+        {
+            configs.add( null );
+        }
+    }
+
+
+    public void updated( String pid, Dictionary properties )
+    {
+        synchronized ( configs )
+        {
+            configs.add( properties );
+            configured = true;
+        }
+    }
+}
\ No newline at end of file

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryThread.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceFactoryThread.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceThread.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceThread.java?rev=809592&view=auto
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceThread.java (added)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceThread.java Mon Aug 31 13:43:32 2009
@@ -0,0 +1,104 @@
+/*
+ * 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.cm.integration.helper;
+
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ManagedService;
+
+
+/**
+ * The <code>ManagedServiceThread</code> class is a ManagedService and extends
+ * the {@link TestThread} for use in the
+ * {@link org.apache.felix.cm.integration.ConfigUpdateStressTest}.
+ */
+public class ManagedServiceThread extends TestThread implements ManagedService
+{
+
+    private final BundleContext bundleContext;
+
+    private final Hashtable<String, Object> serviceProps;
+
+    private ServiceRegistration service;
+
+    private final ArrayList<Dictionary> configs;
+
+    private boolean configured;
+
+
+    public ManagedServiceThread( final BundleContext bundleContext, final String pid )
+    {
+        Hashtable<String, Object> serviceProps = new Hashtable<String, Object>();
+        serviceProps.put( Constants.SERVICE_PID, pid );
+
+        this.bundleContext = bundleContext;
+        this.serviceProps = serviceProps;
+        this.configs = new ArrayList<Dictionary>();
+    }
+
+
+    public ArrayList<Dictionary> getConfigs()
+    {
+        synchronized ( configs )
+        {
+            return new ArrayList<Dictionary>( configs );
+        }
+    }
+
+
+    public boolean isConfigured()
+    {
+        return configured;
+    }
+
+
+    @Override
+    public void doRun()
+    {
+        service = bundleContext.registerService( ManagedService.class.getName(), this, serviceProps );
+        System.out.println( "   " + serviceProps.get( Constants.SERVICE_PID ) + " - ManagedService registered" );
+    }
+
+
+    @Override
+    public void cleanup()
+    {
+        if ( service != null )
+        {
+            service.unregister();
+            service = null;
+        }
+    }
+
+
+    public void updated( Dictionary properties )
+    {
+        synchronized ( configs )
+        {
+            configs.add( properties );
+            configured = properties != null;
+        }
+    }
+}
\ No newline at end of file

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceThread.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/ManagedServiceThread.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/TestThread.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/TestThread.java?rev=809592&view=auto
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/TestThread.java (added)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/TestThread.java Mon Aug 31 13:43:32 2009
@@ -0,0 +1,74 @@
+/*
+ * 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.cm.integration.helper;
+
+
+/**
+ * The <code>TestThread</code> class is a base helper class for the
+ * {@link org.apache.felix.cm.integration.ConfigUpdateStressTest}. It implements
+ * basic mechanics to be able to run two task at quasi the same time.
+ * <p>
+ * It is not important to have exact timings because running the tests multiple
+ * times and based on low-level Java VM timings thread execution will in the end
+ * be more or less random.
+ */
+abstract class TestThread extends Thread
+{
+    private final Object flag = new Object();
+
+    private volatile boolean notified;
+
+
+    @Override
+    public void run()
+    {
+        synchronized ( flag )
+        {
+            if ( !notified )
+            {
+                try
+                {
+                    flag.wait();
+                }
+                catch ( InterruptedException ie )
+                {
+                    // TODO: log
+                }
+            }
+        }
+
+        doRun();
+    }
+
+
+    protected abstract void doRun();
+
+
+    public abstract void cleanup();
+
+
+    public void trigger()
+    {
+        synchronized ( flag )
+        {
+            notified = true;
+            flag.notifyAll();
+        }
+    }
+}
\ No newline at end of file

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/TestThread.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/TestThread.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/UpdateThreadSignalTask.java
URL: http://svn.apache.org/viewvc/felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/UpdateThreadSignalTask.java?rev=809592&view=auto
==============================================================================
--- felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/UpdateThreadSignalTask.java (added)
+++ felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/UpdateThreadSignalTask.java Mon Aug 31 13:43:32 2009
@@ -0,0 +1,80 @@
+/*
+ * 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.cm.integration.helper;
+
+
+import junit.framework.TestCase;
+
+
+/**
+ * The <code>UpdateThreadSignalTask</code> class is a special task used by the
+ * {@link org.apache.felix.cm.integration.ConfigurationTestBase#delay} method.
+ * <p>
+ * This task is intended to be added to the update thread schedule and signals
+ * to the tests that all current tasks on the queue have terminated and tests
+ * may continue checking results.
+ */
+public class UpdateThreadSignalTask implements Runnable
+{
+
+    private final Object trigger = new Object();
+
+    private volatile boolean signal;
+
+
+    public void run()
+    {
+        synchronized ( trigger )
+        {
+            signal = true;
+            trigger.notifyAll();
+        }
+    }
+
+
+    public void waitSignal()
+    {
+        synchronized ( trigger )
+        {
+            if ( !signal )
+            {
+                try
+                {
+                    trigger.wait( 10 * 1000L ); // seconds
+                }
+                catch ( InterruptedException ie )
+                {
+                    // sowhat ??
+                }
+            }
+
+            if ( !signal )
+            {
+                TestCase.fail( "Timed out waiting for the queue to keep up" );
+            }
+        }
+    }
+
+
+    @Override
+    public String toString()
+    {
+        return "Update Thread Signal Task";
+    }
+}

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/UpdateThreadSignalTask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/configadmin/src/test/java/org/apache/felix/cm/integration/helper/UpdateThreadSignalTask.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url