Bug 8163: Use MT DTCL executor in AbstractConcurrentDataBrokerTest 22/60022/5
authorTom Pantelis <tompantelis@gmail.com>
Thu, 6 Jul 2017 12:30:28 +0000 (08:30 -0400)
committerTom Pantelis <tompantelis@gmail.com>
Wed, 12 Jul 2017 13:42:36 +0000 (13:42 +0000)
Using a direct executor can cause deadlocks so the DTCL executor was
made configurable to use a threadpool as an opt-in. Direct executor
is still the default as many existing tests would break.

Change-Id: I41e14f1e6d3b77a44e61dfc75abff29d11a777dc
Signed-off-by: Tom Pantelis <tompantelis@gmail.com>
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1125RegressionTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug2562DeserializedUnkeyedListTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug3090MultiKeyList.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ListInsertionDataChangeListenerTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractConcurrentDataBrokerTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractDataBrokerTestCustomizer.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractDataChangeListenerTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/ConcurrentDataBrokerTestCustomizer.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java

index 7f5d36f35ec161815576d533c4dd352d94613f1b..9f9276954b08aa402661808f88205375a57b1e30 100644 (file)
@@ -76,9 +76,7 @@ public class Bug1125RegressionTest extends AbstractDataChangeListenerTest {
     private void deleteAndListenAugment(final DataChangeScope scope,
             final InstanceIdentifier<?> path) {
         writeInitialState();
-        TestListener listener = createListener(
-                LogicalDatastoreType.OPERATIONAL, WILDCARDED_AUGMENT_PATH,
-                scope);
+        TestListener listener = createListener(LogicalDatastoreType.OPERATIONAL, WILDCARDED_AUGMENT_PATH, scope, false);
         delete(path);
         verifyRemoved(listener.event());
     }
index 60d56db5819b154de988fe23602fdae3c6c265eb..e7b03d9b146f432e0a4722f42a97905216d4a5a7 100644 (file)
@@ -62,8 +62,7 @@ public class Bug1333DataChangeListenerTest extends AbstractDataChangeListenerTes
 
     @Test
     public void writeTopWithListItemAugmentedListenTopSubtree() {
-        TestListener listener = createListener(CONFIGURATION,TOP_PATH, DataChangeScope.SUBTREE);
-        listener.startCapture();
+        TestListener listener = createListener(CONFIGURATION,TOP_PATH, DataChangeScope.SUBTREE, false);
 
         writeTopWithListItem(CONFIGURATION);
 
@@ -81,8 +80,7 @@ public class Bug1333DataChangeListenerTest extends AbstractDataChangeListenerTes
 
     @Test
     public void writeTopWithListItemAugmentedListenAugmentSubtreeWildcarded() {
-        TestListener listener = createListener(CONFIGURATION,AUGMENT_WILDCARD, DataChangeScope.SUBTREE);
-        listener.startCapture();
+        TestListener listener = createListener(CONFIGURATION,AUGMENT_WILDCARD, DataChangeScope.SUBTREE, false);
         writeTopWithListItem(CONFIGURATION);
 
         AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
@@ -125,7 +123,7 @@ public class Bug1333DataChangeListenerTest extends AbstractDataChangeListenerTes
     public void deleteAugmentChildListenAugmentSubtreeWildcarded() {
         writeTopWithListItem(CONFIGURATION);
 
-        TestListener listener = createListener(CONFIGURATION, AUGMENT_WILDCARD, DataChangeScope.SUBTREE);
+        TestListener listener = createListener(CONFIGURATION, AUGMENT_WILDCARD, DataChangeScope.SUBTREE, false);
         InstanceIdentifier<?> deletePath = path(TOP_FOO_KEY,USES_ONE_KEY);
         deleteItem(CONFIGURATION,deletePath);
         AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
index fe32fa9d18535adc34f12fba55d3d71986757eaa..4393dcc5ef251f074383c5d2a82d3de869256570 100644 (file)
@@ -8,6 +8,14 @@
 
 package org.opendaylight.controller.md.sal.binding.impl.test;
 
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
+import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.complexUsesAugment;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.leafOnlyUsesAugment;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
@@ -24,15 +32,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
-import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
-import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
-import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
-import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
-import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.leafOnlyUsesAugment;
-import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.complexUsesAugment;
-
 public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
     private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
     private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
@@ -48,13 +47,12 @@ public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
     @Test
     public void leafOnlyAugmentationCreatedTest() {
         TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
-                AsyncDataBroker.DataChangeScope.SUBTREE);
+                AsyncDataBroker.DataChangeScope.SUBTREE, false);
         WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
         writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
         writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
         writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf"));
         assertCommit(writeTx.submit());
-        assertTrue(listener.hasEvent());
         AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
         assertContains(event.getCreatedData(), SIMPLE_AUGMENT);
         assertEmpty(event.getUpdatedData());
@@ -74,7 +72,6 @@ public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
         writeTx = getDataBroker().newWriteOnlyTransaction();
         writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf changed"));
         assertCommit(writeTx.submit());
-        assertTrue(listener.hasEvent());
         AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
         assertContains(event.getUpdatedData(), SIMPLE_AUGMENT);
         assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
@@ -94,7 +91,6 @@ public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
         writeTx = getDataBroker().newWriteOnlyTransaction();
         writeTx.delete(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT);
         assertCommit(writeTx.submit());
-        assertTrue(listener.hasEvent());
         AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
         assertContains(event.getRemovedPaths(), SIMPLE_AUGMENT);
         assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
@@ -105,13 +101,12 @@ public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
     @Test
     public void complexAugmentationCreatedTest() {
         TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
-                AsyncDataBroker.DataChangeScope.SUBTREE);
+                AsyncDataBroker.DataChangeScope.SUBTREE, false);
         WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
         writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP, top());
         writeTx.put(LogicalDatastoreType.CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
         writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY));
         assertCommit(writeTx.submit());
-        assertTrue(listener.hasEvent());
         AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
         assertContains(event.getCreatedData(), COMPLEX_AUGMENT);
         assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
@@ -132,7 +127,6 @@ public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest{
         writeTx = getDataBroker().newWriteOnlyTransaction();
         writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY_MOD));
         assertCommit(writeTx.submit());
-        assertTrue(listener.hasEvent());
         AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
         assertContains(event.getUpdatedData(), COMPLEX_AUGMENT);
         assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY_MOD));
index 1d4a708f4f5131b13e856dcf3d93393c205e6320..94d727287c6b3cb9ca44985341d3d58027dac4d0 100644 (file)
@@ -49,8 +49,7 @@ public class Bug2562DeserializedUnkeyedListTest extends AbstractDataChangeListen
     @Test
     public void writeListToList2562Root() {
         final AbstractDataChangeListenerTest.TestListener listenerRoot = createListener(LogicalDatastoreType.CONFIGURATION,
-                ROOT_PATH, AsyncDataBroker.DataChangeScope.ONE);
-        listenerRoot.startCapture();
+                ROOT_PATH, AsyncDataBroker.DataChangeScope.ONE, false);
         writeRoot(LogicalDatastoreType.CONFIGURATION);
         final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> eventRoot = listenerRoot.event();
 
index 83bb6a4414fd8264a48e65eae7ace34a321277a3..1efa3a7a6c243eaf3234ef48a0872ab47c06ba01 100644 (file)
@@ -49,8 +49,7 @@ public class Bug3090MultiKeyList extends AbstractDataChangeListenerTest{
     @Test
     public void listWithMultiKeyTest() {
         final AbstractDataChangeListenerTest.TestListener listener = createListener(CONFIGURATION, ROOT_PATH,
-                AsyncDataBroker.DataChangeScope.BASE);
-        listener.startCapture();
+                AsyncDataBroker.DataChangeScope.BASE, false);
 
         write(CONFIGURATION);
         final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
@@ -59,4 +58,4 @@ public class Bug3090MultiKeyList extends AbstractDataChangeListenerTest{
         assertEmpty(event.getUpdatedData());
         assertEmpty(event.getRemovedPaths());
     }
-}
\ No newline at end of file
+}
index 0bc73824bf0cabe0691823f8b733e44317e581d2..b2451391bca3a432d5bc5366ed1ca4e9227c3d86 100644 (file)
@@ -31,9 +31,9 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 /**
  * This testsuite tests explanation for data change scope and data modifications
  * which were described in
- * https://lists.opendaylight.org/pipermail/controller-dev/2014-July/005541.html
+ * https://lists.opendaylight.org/pipermail/controller-dev/2014-July/005541.html.
  */
-public class ListInsertionDataChangeListenerTest extends AbstractDataChangeListenerTest{
+public class ListInsertionDataChangeListenerTest extends AbstractDataChangeListenerTest {
 
     private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
     private static final InstanceIdentifier<TopLevelList> WILDCARDED = TOP.child(TopLevelList.class);
@@ -50,17 +50,17 @@ public class ListInsertionDataChangeListenerTest extends AbstractDataChangeListe
     @Test
     public void replaceTopNodeSubtreeListeners() {
         TestListener topListener = createListener(CONFIGURATION, TOP, DataChangeScope.SUBTREE);
-        TestListener allListener = createListener(CONFIGURATION, WILDCARDED, DataChangeScope.SUBTREE);
+        TestListener allListener = createListener(CONFIGURATION, WILDCARDED, DataChangeScope.SUBTREE, false);
         TestListener fooListener = createListener(CONFIGURATION, TOP_FOO, DataChangeScope.SUBTREE);
-        TestListener barListener = createListener(CONFIGURATION, TOP_BAR, DataChangeScope.SUBTREE);
+        TestListener barListener = createListener(CONFIGURATION, TOP_BAR, DataChangeScope.SUBTREE, false);
 
         ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
         writeTx.put(CONFIGURATION, TOP, top(topLevelList(TOP_BAR_KEY)));
         assertCommit(writeTx.submit());
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> top = topListener.event();
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> all = allListener.event();
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> foo = fooListener.event();
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> bar = barListener.event();
+        final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> top = topListener.event();
+        final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> all = allListener.event();
+        final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> foo = fooListener.event();
+        final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> bar = barListener.event();
 
         // Listener for TOP element
         assertContains(top.getOriginalData(), TOP,TOP_FOO);
@@ -105,9 +105,9 @@ public class ListInsertionDataChangeListenerTest extends AbstractDataChangeListe
     @Test
     public void mergeTopNodeSubtreeListeners() {
         TestListener topListener = createListener(CONFIGURATION, TOP, DataChangeScope.SUBTREE);
-        TestListener allListener = createListener(CONFIGURATION, WILDCARDED, DataChangeScope.SUBTREE);
+        TestListener allListener = createListener(CONFIGURATION, WILDCARDED, DataChangeScope.SUBTREE, false);
         TestListener fooListener = createListener(CONFIGURATION, TOP_FOO, DataChangeScope.SUBTREE);
-        TestListener barListener = createListener(CONFIGURATION, TOP_BAR, DataChangeScope.SUBTREE);
+        TestListener barListener = createListener(CONFIGURATION, TOP_BAR, DataChangeScope.SUBTREE, false);
 
         ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
         writeTx.merge(CONFIGURATION, TOP, top(topLevelList(TOP_BAR_KEY)));
@@ -119,9 +119,9 @@ public class ListInsertionDataChangeListenerTest extends AbstractDataChangeListe
     @Test
     public void putTopBarNodeSubtreeListeners() {
         TestListener topListener = createListener(CONFIGURATION, TOP, DataChangeScope.SUBTREE);
-        TestListener allListener = createListener(CONFIGURATION, WILDCARDED, DataChangeScope.SUBTREE);
+        TestListener allListener = createListener(CONFIGURATION, WILDCARDED, DataChangeScope.SUBTREE, false);
         TestListener fooListener = createListener(CONFIGURATION, TOP_FOO, DataChangeScope.SUBTREE);
-        TestListener barListener = createListener(CONFIGURATION, TOP_BAR, DataChangeScope.SUBTREE);
+        TestListener barListener = createListener(CONFIGURATION, TOP_BAR, DataChangeScope.SUBTREE, false);
 
         ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
         writeTx.put(CONFIGURATION, TOP_BAR, topLevelList(TOP_BAR_KEY));
@@ -133,9 +133,9 @@ public class ListInsertionDataChangeListenerTest extends AbstractDataChangeListe
     @Test
     public void mergeTopBarNodeSubtreeListeners() {
         TestListener topListener = createListener(CONFIGURATION, TOP, DataChangeScope.SUBTREE);
-        TestListener allListener = createListener(CONFIGURATION, WILDCARDED, DataChangeScope.SUBTREE);
+        TestListener allListener = createListener(CONFIGURATION, WILDCARDED, DataChangeScope.SUBTREE, false);
         TestListener fooListener = createListener(CONFIGURATION, TOP_FOO, DataChangeScope.SUBTREE);
-        TestListener barListener = createListener(CONFIGURATION, TOP_BAR, DataChangeScope.SUBTREE);
+        TestListener barListener = createListener(CONFIGURATION, TOP_BAR, DataChangeScope.SUBTREE, false);
 
         ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
         writeTx.merge(CONFIGURATION, TOP_BAR, topLevelList(TOP_BAR_KEY));
index 3239850f2f7ea4167c97a4116dd7372ee83162e4..77c0c3f83f740a246a1e7e1033d4e3ca491b7fb7 100644 (file)
@@ -19,10 +19,24 @@ package org.opendaylight.controller.md.sal.binding.test;
  * @author Michael Vorburger
  */
 public abstract class AbstractConcurrentDataBrokerTest extends AbstractBaseDataBrokerTest {
+    private final boolean useMTDataTreeChangeListenerExecutor;
+
+    protected AbstractConcurrentDataBrokerTest() {
+        this(false);
+    }
+
+    protected AbstractConcurrentDataBrokerTest(final boolean useMTDataTreeChangeListenerExecutor) {
+        this.useMTDataTreeChangeListenerExecutor = useMTDataTreeChangeListenerExecutor;
+    }
 
     @Override
     protected AbstractDataBrokerTestCustomizer createDataBrokerTestCustomizer() {
-        return new ConcurrentDataBrokerTestCustomizer();
+        ConcurrentDataBrokerTestCustomizer customizer = new ConcurrentDataBrokerTestCustomizer();
+        if (useMTDataTreeChangeListenerExecutor) {
+            customizer.useMTDataTreeChangeListenerExecutor();
+        }
+
+        return customizer;
     }
 
 }
index 02f3257b659b5d15d7260f92a14907a572946146..8d968b0a01526da6cbd6892f20d775e57f5cec31 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.md.sal.binding.test;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
+import javassist.ClassPool;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
@@ -31,7 +32,6 @@ import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializ
 import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
 import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import javassist.ClassPool;
 
 public abstract class AbstractDataBrokerTestCustomizer {
 
@@ -40,6 +40,7 @@ public abstract class AbstractDataBrokerTestCustomizer {
     private final MockSchemaService schemaService;
     private ImmutableMap<LogicalDatastoreType, DOMStore> datastores;
     private final BindingToNormalizedNodeCodec bindingToNormalized;
+    private ListeningExecutorService dataTreeChangeListenerExecutor = MoreExecutors.newDirectExecutorService();
 
     public ImmutableMap<LogicalDatastoreType, DOMStore> createDatastores() {
         return ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
@@ -60,13 +61,13 @@ public abstract class AbstractDataBrokerTestCustomizer {
     }
 
     public DOMStore createConfigurationDatastore() {
-        final InMemoryDOMDataStore store = new InMemoryDOMDataStore("CFG", MoreExecutors.newDirectExecutorService());
+        final InMemoryDOMDataStore store = new InMemoryDOMDataStore("CFG", dataTreeChangeListenerExecutor);
         this.schemaService.registerSchemaContextListener(store);
         return store;
     }
 
     public DOMStore createOperationalDatastore() {
-        final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", MoreExecutors.newDirectExecutorService());
+        final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", dataTreeChangeListenerExecutor);
         this.schemaService.registerSchemaContextListener(store);
         return store;
     }
@@ -111,6 +112,10 @@ public abstract class AbstractDataBrokerTestCustomizer {
         return this.datastores;
     }
 
+    public void setDataTreeChangeListenerExecutor(ListeningExecutorService executor) {
+        this.dataTreeChangeListenerExecutor = executor;
+    }
+
     public void updateSchema(final SchemaContext ctx) {
         this.schemaService.changeSchema(ctx);
     }
index a82df937fd876411a3acb23571edaec7519a3887..2a5c0e8332819a567329bc703d765c365d9dd08a 100644 (file)
@@ -7,10 +7,13 @@
  */
 package org.opendaylight.controller.md.sal.binding.test;
 
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.util.concurrent.SettableFuture;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
@@ -18,23 +21,25 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import com.google.common.util.concurrent.SettableFuture;
-
 public abstract class AbstractDataChangeListenerTest extends AbstractConcurrentDataBrokerTest {
 
     protected static final class TestListener implements DataChangeListener {
 
         private final SettableFuture<AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>> event;
-        private boolean capture = false;
+        private final CountDownLatch initialEventLatch;
+        private volatile boolean capture = false;
 
-        private TestListener() {
+        private TestListener(boolean expectInitialEvent) {
             event = SettableFuture.create();
+            initialEventLatch = new CountDownLatch(expectInitialEvent ? 1 : 0);
         }
 
         @Override
         public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> arg) {
             if (capture) {
                 event.set(arg);
+            } else {
+                initialEventLatch.countDown();
             }
         }
 
@@ -50,16 +55,31 @@ public abstract class AbstractDataChangeListenerTest extends AbstractConcurrentD
             return event.isDone();
         }
 
-        public void startCapture() {
+        private void waitForInitialEvent() {
+            try {
+                assertTrue("Initial DataChangeEvent was not received", initialEventLatch.await(3, TimeUnit.SECONDS));
+            } catch (InterruptedException e) {
+                throw new IllegalStateException(e);
+            }
+
             this.capture = true;
         }
     }
 
+    protected AbstractDataChangeListenerTest() {
+        super(true);
+    }
+
     protected final TestListener createListener(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
             final DataChangeScope scope) {
-        TestListener listener = new TestListener();
+        return createListener(store, path, scope, true);
+    }
+
+    protected final TestListener createListener(final LogicalDatastoreType store, final InstanceIdentifier<?> path,
+            final DataChangeScope scope, boolean expectInitialEvent) {
+        TestListener listener = new TestListener(expectInitialEvent);
         getDataBroker().registerDataChangeListener(store, path, listener, scope);
-        listener.startCapture();
+        listener.waitForInitialEvent();
         return listener;
     }
 }
index c8dba37441a64b7a34862204957cbee39171976d..0b2de070f8f5109694cc2bfb2e3ca5adb0be7560 100644 (file)
@@ -14,7 +14,8 @@ import java.util.concurrent.Executors;
 /**
  * ConcurrentDataBrokerTestCustomizer.
  *
- * <p>See {@link AbstractConcurrentDataBrokerTest} and <a href="https://bugs.opendaylight.org/show_bug.cgi?id=7538">bug 7538</a> for more details & background.
+ * <p>See {@link AbstractConcurrentDataBrokerTest} and
+ * <a href="https://bugs.opendaylight.org/show_bug.cgi?id=7538">bug 7538</a> for more details & background.
  *
  * @author Michael Vorburger
  */
@@ -24,4 +25,8 @@ public class ConcurrentDataBrokerTestCustomizer extends AbstractDataBrokerTestCu
     public ListeningExecutorService getCommitCoordinatorExecutor() {
         return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
     }
+
+    public void useMTDataTreeChangeListenerExecutor() {
+        setDataTreeChangeListenerExecutor(MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()));
+    }
 }
index 8c7bf207ccf92fc7b85b665a910f3d557cca3b36..e037de452b37961b9a3afa3564238ce0e175fa63 100644 (file)
@@ -23,5 +23,4 @@ public class DataBrokerTestCustomizer extends AbstractDataBrokerTestCustomizer {
     public ListeningExecutorService getCommitCoordinatorExecutor() {
         return MoreExecutors.newDirectExecutorService();
     }
-
 }