Convert DCL tests to use DTCL 00/71800/2
authorTom Pantelis <tompantelis@gmail.com>
Fri, 4 May 2018 04:55:37 +0000 (00:55 -0400)
committerTom Pantelis <tompantelis@gmail.com>
Wed, 23 May 2018 13:45:35 +0000 (09:45 -0400)
Change-Id: I05bd3a9b42e1ab3d9a1e682aaacb585aee313e7a
Signed-off-by: Tom Pantelis <tompantelis@gmail.com>
23 files changed:
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingDOMDataBrokerAdapterTest.java
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/Bug4513Test.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/AbstractDataChangeListenerTest.java [deleted file]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractDataTreeChangeListenerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/compat/LegacyDOMDataBrokerAdapterTest.java
opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMBrokerTest.java
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDataTreeChangeListenerTest.java [moved from opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDataChangeListenerTest.java with 98% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DatastoreTestTask.java
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DefaultDataTreeChangeListenerTestSuite.java [moved from opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DefaultDataChangeListenerTestSuite.java with 54% similarity]
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/RootScopeSubtreeTest.java
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeBaseTest.java
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeOneTest.java [deleted file]
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeSubtreeTest.java [deleted file]

index 3506f4b..b01340a 100644 (file)
@@ -8,28 +8,33 @@
 
 package org.opendaylight.controller.md.sal.binding.impl.test;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.collect.ImmutableMap;
 import org.junit.Before;
 import org.junit.Test;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter;
 import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.dom.api.ClusteredDOMDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.api.ClusteredDOMDataTreeChangeListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
 import org.opendaylight.mdsal.binding.generator.impl.GeneratedClassLoadingStrategy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
-import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 
-
 public class BindingDOMDataBrokerAdapterTest {
 
     @Mock
@@ -37,15 +42,20 @@ public class BindingDOMDataBrokerAdapterTest {
 
     @Mock
     GeneratedClassLoadingStrategy classLoadingStrategy;
+
     @Mock
     BindingNormalizedNodeCodecRegistry codecRegistry;
 
     @Mock
-    YangInstanceIdentifier yangInstanceIdentifier;
+    DOMDataTreeChangeService dataTreeChangeService;
 
+    @Mock
+    ListenerRegistration<DOMDataTreeChangeListener> listenerRegistration;
+
+    @Mock
+    ClusteredDataTreeChangeListener<Top> clusteredDataTreeChangeListener;
 
-    private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier
-        .create(Top.class);
+    private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
 
     @Before
     public void setUp() {
@@ -53,39 +63,33 @@ public class BindingDOMDataBrokerAdapterTest {
     }
 
     @Test
-    public void testClusteredDataChangeListernerRegisteration() {
+    public void testClusteredDataTreeChangeListenerRegisteration() {
+
+        doReturn(YangInstanceIdentifier.of(Top.QNAME)).when(codecRegistry).toYangInstanceIdentifier(TOP_PATH);
+
+        doReturn(listenerRegistration).when(dataTreeChangeService).registerDataTreeChangeListener(any(), any());
+
+        doReturn(ImmutableMap.of(DOMDataTreeChangeService.class, dataTreeChangeService))
+            .when(dataBroker).getSupportedExtensions();
 
         final BindingToNormalizedNodeCodec codec =
                 new BindingToNormalizedNodeCodec(this.classLoadingStrategy, this.codecRegistry);
 
         try (BindingDOMDataBrokerAdapter bindingDOMDataBrokerAdapter = new BindingDOMDataBrokerAdapter(this.dataBroker,
                 codec)) {
-            Mockito.when(this.codecRegistry.toYangInstanceIdentifier(TOP_PATH)).thenReturn(this.yangInstanceIdentifier);
-
-            final ArgumentCaptor<ClusteredDOMDataChangeListener> clusteredDOMListener = ArgumentCaptor
-                    .forClass(ClusteredDOMDataChangeListener.class);
-            final ArgumentCaptor<LogicalDatastoreType> logicalDatastoreType = ArgumentCaptor
-                    .forClass(LogicalDatastoreType.class);
-            final ArgumentCaptor<AsyncDataBroker.DataChangeScope> dataChangeScope = ArgumentCaptor
-                    .forClass(AsyncDataBroker.DataChangeScope.class);
-            final ArgumentCaptor<YangInstanceIdentifier> yangIidCapture = ArgumentCaptor
-                    .forClass(YangInstanceIdentifier.class);
-
-            final TestListener listener = new TestListener();
-
-            bindingDOMDataBrokerAdapter.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, TOP_PATH,
-                    listener, AsyncDataBroker.DataChangeScope.BASE);
-            Mockito.verify(this.dataBroker).registerDataChangeListener(logicalDatastoreType.capture(),
-                    yangIidCapture.capture(), clusteredDOMListener.capture(), dataChangeScope.capture());
-        }
 
-    }
+            ListenerRegistration<ClusteredDataTreeChangeListener<Top>> bindingListenerReg =
+                bindingDOMDataBrokerAdapter.registerDataTreeChangeListener(
+                    new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, TOP_PATH),
+                    clusteredDataTreeChangeListener);
 
-    private class TestListener implements ClusteredDataChangeListener {
+            verify(dataTreeChangeService).registerDataTreeChangeListener(
+                eq(new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.of(Top.QNAME))),
+                any(ClusteredDOMDataTreeChangeListener.class));
 
-        @Override
-        public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+            bindingListenerReg.close();
 
+            verify(listenerRegistration).close();
         }
     }
 }
index 41c3375..fff82db 100644 (file)
@@ -8,17 +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.path;
 import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
 
+import com.google.common.collect.ImmutableSet;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
@@ -26,14 +23,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.TopBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
 /**
  * Regression test suite for Bug 1125 - Can't detect switch disconnection
  * https://bugs.opendaylight.org/show_bug.cgi?id=1125.
  */
-public class Bug1125RegressionTest extends AbstractDataChangeListenerTest {
+public class Bug1125RegressionTest extends AbstractDataTreeChangeListenerTest {
 
     private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier
             .create(Top.class);
@@ -47,7 +45,13 @@ public class Bug1125RegressionTest extends AbstractDataChangeListenerTest {
             .child(TopLevelList.class).augmentation(
                     TreeComplexUsesAugment.class);
 
-    private void writeInitialState() {
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+                BindingReflections.getModuleInfo(TreeComplexUsesAugment.class));
+    }
+
+    private TreeComplexUsesAugment writeInitialState() {
         WriteTransaction initialTx = getDataBroker().newWriteOnlyTransaction();
         initialTx.put(LogicalDatastoreType.OPERATIONAL, TOP_PATH,
                 new TopBuilder().build());
@@ -58,6 +62,7 @@ public class Bug1125RegressionTest extends AbstractDataChangeListenerTest {
         initialTx.put(LogicalDatastoreType.OPERATIONAL, path(TOP_FOO_KEY),
                 topLevelList(TOP_FOO_KEY, fooAugment));
         assertCommit(initialTx.submit());
+        return fooAugment;
     }
 
     private void delete(final InstanceIdentifier<?> path) {
@@ -66,40 +71,20 @@ public class Bug1125RegressionTest extends AbstractDataChangeListenerTest {
         assertCommit(tx.submit());
     }
 
-    private void verifyRemoved(
-            final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event) {
-        assertEmpty(event.getCreatedData());
-        assertEmpty(event.getUpdatedData());
-        assertContains(event.getRemovedPaths(), FOO_AUGMENT_PATH);
-    }
-
-    private void deleteAndListenAugment(final DataChangeScope scope,
-            final InstanceIdentifier<?> path) {
-        writeInitialState();
-        TestListener listener = createListener(LogicalDatastoreType.OPERATIONAL, WILDCARDED_AUGMENT_PATH, scope, false);
+    private void deleteAndListenAugment(final InstanceIdentifier<?> path) {
+        TreeComplexUsesAugment augment = writeInitialState();
+        TestListener<TreeComplexUsesAugment> listener = createListener(LogicalDatastoreType.OPERATIONAL,
+                WILDCARDED_AUGMENT_PATH, added(FOO_AUGMENT_PATH, augment), deleted(FOO_AUGMENT_PATH, augment));
         delete(path);
-        verifyRemoved(listener.event());
+        listener.verify();
     }
 
     @Test
     public void deleteAndListenAugment() {
+        deleteAndListenAugment(TOP_PATH);
 
-        deleteAndListenAugment(DataChangeScope.ONE, TOP_PATH);
-
-        deleteAndListenAugment(DataChangeScope.BASE, TOP_PATH);
-
-        deleteAndListenAugment(DataChangeScope.SUBTREE, TOP_PATH);
-
-        deleteAndListenAugment(DataChangeScope.BASE, TOP_FOO_PATH);
-
-        deleteAndListenAugment(DataChangeScope.ONE, TOP_FOO_PATH);
-
-        deleteAndListenAugment(DataChangeScope.SUBTREE, TOP_FOO_PATH);
-
-        deleteAndListenAugment(DataChangeScope.BASE, FOO_AUGMENT_PATH);
-
-        deleteAndListenAugment(DataChangeScope.ONE, FOO_AUGMENT_PATH);
+        deleteAndListenAugment(TOP_FOO_PATH);
 
-        deleteAndListenAugment(DataChangeScope.SUBTREE, FOO_AUGMENT_PATH);
+        deleteAndListenAugment(FOO_AUGMENT_PATH);
     }
 }
index 177aa6b..93331c7 100644 (file)
@@ -7,9 +7,6 @@
  */
 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.binding.test.AssertCollections.assertNotContains;
 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
 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.USES_ONE_KEY;
@@ -19,17 +16,18 @@ import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUti
 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 com.google.common.collect.ImmutableSet;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
 /**
  * This testsuite tries to replicate bug 1333 and tests regresion of it
@@ -38,18 +36,29 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
  * <p>
  * See  https://bugs.opendaylight.org/show_bug.cgi?id=1333 for Bug Description
  */
-public class Bug1333DataChangeListenerTest extends AbstractDataChangeListenerTest {
+public class Bug1333DataChangeListenerTest extends AbstractDataTreeChangeListenerTest {
 
     private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
 
-    private static final InstanceIdentifier<?> AUGMENT_WILDCARD = TOP_PATH.child(TopLevelList.class).augmentation(
-            TreeComplexUsesAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> AUGMENT_WILDCARD =
+            TOP_PATH.child(TopLevelList.class).augmentation(TreeComplexUsesAugment.class);
 
-    public void writeTopWithListItem(final LogicalDatastoreType store) {
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+                BindingReflections.getModuleInfo(TreeComplexUsesAugment.class));
+    }
+
+    private Top topWithListItem() {
+        return top(topLevelList(TOP_FOO_KEY, complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)));
+    }
+
+    public Top writeTopWithListItem(final LogicalDatastoreType store) {
         ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
-        Top topItem = top(topLevelList(TOP_FOO_KEY, complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)));
+        Top topItem = topWithListItem();
         tx.put(store, TOP_PATH, topItem);
         assertCommit(tx.submit());
+        return topItem;
     }
 
     public void deleteItem(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
@@ -60,81 +69,48 @@ public class Bug1333DataChangeListenerTest extends AbstractDataChangeListenerTes
 
     @Test
     public void writeTopWithListItemAugmentedListenTopSubtree() {
-        TestListener listener = createListener(CONFIGURATION,TOP_PATH, DataChangeScope.SUBTREE, false);
+        TestListener<Top> listener = createListener(CONFIGURATION, TOP_PATH, added(TOP_PATH, topWithListItem()));
 
         writeTopWithListItem(CONFIGURATION);
 
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
-
-        assertContains(event.getCreatedData(), TOP_PATH);
-        assertContains(event.getCreatedData(), path(TOP_FOO_KEY));
-        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
-        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_ONE_KEY));
-        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_TWO_KEY));
-
-        assertEmpty(event.getUpdatedData());
-        assertEmpty(event.getRemovedPaths());
+        listener.verify();
     }
 
     @Test
     public void writeTopWithListItemAugmentedListenAugmentSubtreeWildcarded() {
-        TestListener listener = createListener(CONFIGURATION,AUGMENT_WILDCARD, DataChangeScope.SUBTREE, false);
-        writeTopWithListItem(CONFIGURATION);
-
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, AUGMENT_WILDCARD,
+                added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)));
 
-        /*
-         * Event should not contain parent nodes
-         */
-        assertNotContains(event.getCreatedData(), TOP_PATH, path(TOP_FOO_KEY));
-
-        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
-        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_ONE_KEY));
-        assertContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_TWO_KEY));
+        writeTopWithListItem(CONFIGURATION);
 
-        assertEmpty(event.getUpdatedData());
-        assertEmpty(event.getRemovedPaths());
+        listener.verify();
     }
 
     @Test
     public void deleteAugmentChildListenTopSubtree() {
-        writeTopWithListItem(CONFIGURATION);
-        TestListener listener = createListener(CONFIGURATION, TOP_PATH, DataChangeScope.SUBTREE);
-        InstanceIdentifier<?> deletePath = path(TOP_FOO_KEY,USES_ONE_KEY);
-        deleteItem(CONFIGURATION,deletePath);
-
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+        Top top = writeTopWithListItem(CONFIGURATION);
 
+        TestListener<Top> listener = createListener(CONFIGURATION, TOP_PATH, added(TOP_PATH, top),
+                subtreeModified(TOP_PATH, top, top(topLevelList(TOP_FOO_KEY, complexUsesAugment(USES_TWO_KEY)))));
 
-        assertEmpty(event.getCreatedData());
+        InstanceIdentifier<ListViaUses> deletePath = path(TOP_FOO_KEY, USES_ONE_KEY);
+        deleteItem(CONFIGURATION, deletePath);
 
-        assertContains(event.getRemovedPaths(), deletePath);
-
-        assertContains(event.getUpdatedData(), TOP_PATH);
-        assertContains(event.getUpdatedData(), path(TOP_FOO_KEY));
-        assertContains(event.getUpdatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
-
-        assertNotContains(event.getCreatedData(), path(TOP_FOO_KEY, USES_TWO_KEY));
+        listener.verify();
     }
 
     @Test
     public void deleteAugmentChildListenAugmentSubtreeWildcarded() {
         writeTopWithListItem(CONFIGURATION);
 
-        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();
-
-        assertEmpty(event.getCreatedData());
-
-        assertContains(event.getUpdatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class));
+        TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, AUGMENT_WILDCARD,
+                added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)),
+                subtreeModified(path(TOP_FOO_KEY, TreeComplexUsesAugment.class),
+                    complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY), complexUsesAugment(USES_TWO_KEY)));
 
-        /*
-         * Event should not contain parent nodes
-         */
-        assertNotContains(event.getUpdatedData(), TOP_PATH, path(TOP_FOO_KEY));
+        InstanceIdentifier<?> deletePath = path(TOP_FOO_KEY, USES_ONE_KEY);
+        deleteItem(CONFIGURATION, deletePath);
 
-        assertContains(event.getRemovedPaths(), deletePath);
+        listener.verify();
     }
 }
index ca6c78f..728e292 100644 (file)
@@ -8,31 +8,29 @@
 
 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.common.api.data.LogicalDatastoreType.CONFIGURATION;
 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.path;
 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 com.google.common.collect.ImmutableSet;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
-public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest {
+public class Bug1418AugmentationTest extends AbstractDataTreeChangeListenerTest {
     private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
     private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
     private static final InstanceIdentifier<TreeLeafOnlyUsesAugment> SIMPLE_AUGMENT =
@@ -44,94 +42,105 @@ public class Bug1418AugmentationTest extends AbstractDataChangeListenerTest {
     private static final ListViaUsesKey LIST_VIA_USES_KEY_MOD =
             new ListViaUsesKey("list key modified");
 
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+                BindingReflections.getModuleInfo(TreeComplexUsesAugment.class),
+                BindingReflections.getModuleInfo(TreeLeafOnlyUsesAugment.class));
+    }
+
     @Test
     public void leafOnlyAugmentationCreatedTest() {
-        final TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
-                AsyncDataBroker.DataChangeScope.SUBTREE, false);
+        TreeLeafOnlyUsesAugment leafOnlyUsesAugment = leafOnlyUsesAugment("test leaf");
+        final TestListener<TreeLeafOnlyUsesAugment> listener = createListener(CONFIGURATION, SIMPLE_AUGMENT,
+                added(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugment));
+
         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"));
+        writeTx.put(CONFIGURATION, TOP, top());
+        writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment);
         assertCommit(writeTx.submit());
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
-        assertContains(event.getCreatedData(), SIMPLE_AUGMENT);
-        assertEmpty(event.getUpdatedData());
-        assertEmpty(event.getOriginalData());
-        assertEmpty(event.getRemovedPaths());
+
+        listener.verify();
     }
 
     @Test
     public void leafOnlyAugmentationUpdatedTest() {
         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"));
+        writeTx.put(CONFIGURATION, TOP, top());
+        writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        TreeLeafOnlyUsesAugment leafOnlyUsesAugmentBefore = leafOnlyUsesAugment("test leaf");
+        writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugmentBefore);
         assertCommit(writeTx.submit());
-        final TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
-                AsyncDataBroker.DataChangeScope.SUBTREE);
+
+        TreeLeafOnlyUsesAugment leafOnlyUsesAugmentAfter = leafOnlyUsesAugment("test leaf changed");
+        final TestListener<TreeLeafOnlyUsesAugment> listener = createListener(CONFIGURATION, SIMPLE_AUGMENT,
+                added(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugmentBefore),
+                replaced(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugmentBefore,
+                    leafOnlyUsesAugmentAfter));
+
         writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment("test leaf changed"));
+        writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugmentAfter);
         assertCommit(writeTx.submit());
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
-        assertContains(event.getUpdatedData(), SIMPLE_AUGMENT);
-        assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
-        assertEmpty(event.getCreatedData());
-        assertEmpty(event.getRemovedPaths());
+
+        listener.verify();
     }
 
     @Test
     public void leafOnlyAugmentationDeletedTest() {
         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"));
+        writeTx.put(CONFIGURATION, TOP, top());
+        writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        TreeLeafOnlyUsesAugment leafOnlyUsesAugment = leafOnlyUsesAugment("test leaf");
+        writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment);
         assertCommit(writeTx.submit());
-        final TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT,
-                AsyncDataBroker.DataChangeScope.SUBTREE);
+
+        final TestListener<TreeLeafOnlyUsesAugment> listener = createListener(CONFIGURATION, SIMPLE_AUGMENT,
+                added(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugment),
+                deleted(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugment));
+
         writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.delete(LogicalDatastoreType.CONFIGURATION, SIMPLE_AUGMENT);
+        writeTx.delete(CONFIGURATION, SIMPLE_AUGMENT);
         assertCommit(writeTx.submit());
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
-        assertContains(event.getRemovedPaths(), SIMPLE_AUGMENT);
-        assertContains(event.getOriginalData(), SIMPLE_AUGMENT);
-        assertEmpty(event.getCreatedData());
-        assertEmpty(event.getUpdatedData());
+
+        listener.verify();
     }
 
     @Test
     public void complexAugmentationCreatedTest() {
-        final TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
-                AsyncDataBroker.DataChangeScope.SUBTREE, false);
+        TreeComplexUsesAugment complexUsesAugment = complexUsesAugment(LIST_VIA_USES_KEY);
+        final TestListener<TreeComplexUsesAugment>  listener = createListener(CONFIGURATION, COMPLEX_AUGMENT,
+                added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugment));
+
         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));
+        writeTx.put(CONFIGURATION, TOP, top());
+        writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment);
         assertCommit(writeTx.submit());
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
-        assertContains(event.getCreatedData(), COMPLEX_AUGMENT);
-        assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
-        assertEmpty(event.getUpdatedData());
-        assertEmpty(event.getOriginalData());
-        assertEmpty(event.getRemovedPaths());
+
+        listener.verify();
     }
 
     @Test
     public void complexAugmentationUpdatedTest() {
         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));
+        writeTx.put(CONFIGURATION, TOP, top());
+        writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+        TreeComplexUsesAugment complexUsesAugmentBefore = complexUsesAugment(LIST_VIA_USES_KEY);
+        writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugmentBefore);
         assertCommit(writeTx.submit());
-        final TestListener listener = createListener(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT,
-                AsyncDataBroker.DataChangeScope.SUBTREE);
+
+        TreeComplexUsesAugment complexUsesAugmentAfter = complexUsesAugment(LIST_VIA_USES_KEY_MOD);
+
+        final TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, COMPLEX_AUGMENT,
+                added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugmentBefore),
+                replaced(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugmentBefore,
+                        complexUsesAugmentAfter));
+
         writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(LogicalDatastoreType.CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment(LIST_VIA_USES_KEY_MOD));
+        writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugmentAfter);
         assertCommit(writeTx.submit());
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
-        assertContains(event.getUpdatedData(), COMPLEX_AUGMENT);
-        assertContains(event.getCreatedData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY_MOD));
-        assertContains(event.getRemovedPaths(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
-        assertContains(event.getOriginalData(), COMPLEX_AUGMENT);
-        assertContains(event.getOriginalData(), COMPLEX_AUGMENT.child(ListViaUses.class, LIST_VIA_USES_KEY));
+
+        listener.verify();
     }
 }
index 57d390b..6d6b16e 100644 (file)
@@ -8,16 +8,11 @@
 
 package org.opendaylight.controller.md.sal.binding.impl.test;
 
-import static org.junit.Assert.assertNotNull;
-import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertContains;
-import static org.opendaylight.controller.md.sal.binding.test.AssertCollections.assertEmpty;
-
-import java.util.ArrayList;
+import com.google.common.collect.ImmutableSet;
+import java.util.Arrays;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.Root;
 import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.RootBuilder;
@@ -26,36 +21,31 @@ import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160
 import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.fooroot.Barroot;
 import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.fooroot.BarrootBuilder;
 import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.fooroot.BarrootKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
-public class Bug2562DeserializedUnkeyedListTest extends AbstractDataChangeListenerTest {
+public class Bug2562DeserializedUnkeyedListTest extends AbstractDataTreeChangeListenerTest {
     private static final InstanceIdentifier<Root> ROOT_PATH = InstanceIdentifier.create(Root.class);
 
-    private void writeRoot(final LogicalDatastoreType store) {
-        final ReadWriteTransaction readWriteTransaction = getDataBroker().newReadWriteTransaction();
-        final Barroot barRoot = new BarrootBuilder().setType(2).setValue(2).setKey(new BarrootKey(2)).build();
-        final ArrayList<Barroot> barRootList = new ArrayList<>();
-        barRootList.add(barRoot);
-        final Fooroot fooRoot = new FoorootBuilder().setBarroot(barRootList).build();
-        final ArrayList<Fooroot> fooRootList = new ArrayList<>();
-        fooRootList.add(fooRoot);
-        final Root root = new RootBuilder().setFooroot(fooRootList).build();
-
-        readWriteTransaction.put(store, ROOT_PATH, root);
-        assertCommit(readWriteTransaction.submit());
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        return ImmutableSet.of(BindingReflections.getModuleInfo(Root.class));
     }
 
     @Test
     public void writeListToList2562Root() {
-        final AbstractDataChangeListenerTest.TestListener listenerRoot =
-            createListener(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, AsyncDataBroker.DataChangeScope.ONE, false);
-        writeRoot(LogicalDatastoreType.CONFIGURATION);
-        final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> eventRoot = listenerRoot.event();
-
-        assertContains(eventRoot.getCreatedData(), ROOT_PATH);
-        assertEmpty(eventRoot.getUpdatedData());
-        assertEmpty(eventRoot.getRemovedPaths());
-        assertNotNull(eventRoot.toString());
+        final Barroot barRoot = new BarrootBuilder().setType(2).setValue(2).setKey(new BarrootKey(2)).build();
+        final Fooroot fooRoot = new FoorootBuilder().setBarroot(Arrays.asList(barRoot)).build();
+        final Root root = new RootBuilder().setFooroot(Arrays.asList(fooRoot)).build();
+
+        final TestListener<Root> listenerRoot = createListener(LogicalDatastoreType.CONFIGURATION, ROOT_PATH,
+                added(ROOT_PATH, root));
+
+        final ReadWriteTransaction readWriteTransaction = getDataBroker().newReadWriteTransaction();
+        readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, root);
+        assertCommit(readWriteTransaction.submit());
+
+        listenerRoot.verify();
     }
 }
index 3b883b4..92f00b5 100644 (file)
@@ -7,31 +7,36 @@
  */
 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.common.api.data.LogicalDatastoreType.CONFIGURATION;
-
+import com.google.common.collect.ImmutableSet;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.opendaylight.test.bug._3090.rev160101.Root;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.opendaylight.test.bug._3090.rev160101.RootBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.opendaylight.test.bug._3090.rev160101.root.ListInRoot;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.opendaylight.test.bug._3090.rev160101.root.ListInRootBuilder;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
-public class Bug3090MultiKeyList extends AbstractDataChangeListenerTest {
+public class Bug3090MultiKeyList extends AbstractDataTreeChangeListenerTest {
     private static final InstanceIdentifier<Root> ROOT_PATH = InstanceIdentifier.create(Root.class);
 
-    private void write(final LogicalDatastoreType store) {
-        final ReadWriteTransaction readWriteTransaction = getDataBroker().newReadWriteTransaction();
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        return ImmutableSet.of(BindingReflections.getModuleInfo(Root.class));
+    }
 
+    @Test
+    public void listWithMultiKeyTest() {
         final List<ListInRoot> listInRoots = new ArrayList<>();
         for (int i = 0; i < 10; i++) {
             listInRoots.add(new ListInRootBuilder()
@@ -41,21 +46,28 @@ public class Bug3090MultiKeyList extends AbstractDataChangeListenerTest {
                 .build()
             );
         }
+
         final Root root = new RootBuilder().setListInRoot(listInRoots).build();
-        readWriteTransaction.put(store, ROOT_PATH, root);
+
+        final TestListener<Root> listener = createListener(LogicalDatastoreType.CONFIGURATION, ROOT_PATH,
+                match(ModificationType.WRITE, ROOT_PATH, dataBefore -> dataBefore == null,
+                        (Function<Root, Boolean>) dataAfter -> checkData(root, dataAfter)));
+
+        final ReadWriteTransaction readWriteTransaction = getDataBroker().newReadWriteTransaction();
+        readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, root);
         assertCommit(readWriteTransaction.submit());
-    }
 
-    @Test
-    public void listWithMultiKeyTest() {
-        final AbstractDataChangeListenerTest.TestListener listener = createListener(CONFIGURATION, ROOT_PATH,
-                AsyncDataBroker.DataChangeScope.BASE, false);
+        listener.verify();
+    }
 
-        write(CONFIGURATION);
-        final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = listener.event();
+    private boolean checkData(Root expected, Root actual) {
+        if (actual == null) {
+            return false;
+        }
 
-        assertContains(event.getCreatedData(), ROOT_PATH);
-        assertEmpty(event.getUpdatedData());
-        assertEmpty(event.getRemovedPaths());
+        Set<ListInRoot> expListInRoot = new HashSet<>(expected.getListInRoot());
+        Set<ListInRoot> actualListInRoot = actual.getListInRoot().stream()
+                .map(list -> new ListInRootBuilder(list).build()).collect(Collectors.toSet());
+        return expListInRoot.equals(actualListInRoot);
     }
 }
index 82da427..4a84c31 100644 (file)
@@ -17,14 +17,11 @@ import java.util.Collection;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.listener.rev150825.ListenerTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.listener.rev150825.ListenerTestBuilder;
@@ -38,25 +35,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
  * Homogeneous composite key is used homogeneous composite key is used.
  */
 public class Bug4513Test extends AbstractDataBrokerTest {
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Test
-    public void testDataChangeListener() throws Exception {
-        DataChangeListener listener = mock(DataChangeListener.class);
-        InstanceIdentifier<ListItem> wildCard = InstanceIdentifier.builder(ListenerTest.class)
-                .child(ListItem.class).build();
-        ListenerRegistration<DataChangeListener> reg = getDataBroker().registerDataChangeListener(
-                LogicalDatastoreType.OPERATIONAL, wildCard, listener, AsyncDataBroker.DataChangeScope.SUBTREE);
-
-        final ListItem item = writeListItem();
-
-        ArgumentCaptor<AsyncDataChangeEvent> captor = ArgumentCaptor.forClass(AsyncDataChangeEvent.class);
-
-        verify(listener, timeout(100)).onDataChanged(captor.capture());
-
-        AsyncDataChangeEvent event = captor.getValue();
-        assertEquals("createdData", 1, event.getCreatedData().size());
-        assertEquals("ListItem", item, event.getCreatedData().values().iterator().next());
-    }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     @Test
index b245139..36240fe 100644 (file)
@@ -6,40 +6,49 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 package org.opendaylight.controller.md.sal.binding.impl.test;
-import static org.junit.Assert.assertFalse;
-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.binding.test.AssertCollections.assertNotContains;
 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
 import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.TOP_BAR_KEY;
 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.top;
 import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
 
+import com.google.common.collect.ImmutableSet;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 import org.junit.Before;
 import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.binding.test.AbstractDataChangeListenerTest;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
 /**
  * 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.
  */
-public class ListInsertionDataChangeListenerTest extends AbstractDataChangeListenerTest {
+public class ListInsertionDataChangeListenerTest extends AbstractDataTreeChangeListenerTest {
 
     private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
     private static final InstanceIdentifier<TopLevelList> WILDCARDED = TOP.child(TopLevelList.class);
     private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
     private static final InstanceIdentifier<TopLevelList> TOP_BAR = TOP.child(TopLevelList.class, TOP_BAR_KEY);
 
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class));
+    }
+
     @Before
     public void setupWithDataBroker() {
         WriteTransaction initialTx = getDataBroker().newWriteOnlyTransaction();
@@ -49,141 +58,116 @@ public class ListInsertionDataChangeListenerTest extends AbstractDataChangeListe
 
     @Test
     public void replaceTopNodeSubtreeListeners() {
-        TestListener topListener = createListener(CONFIGURATION, TOP, 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, false);
+        final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
+        final Top top = top(topBar);
+        final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
+
+        // Listener for TOP element
+        final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+                added(TOP, top(topLevelList(TOP_FOO_KEY))), replaced(TOP, top(topFoo), top));
+
+        // Listener for all list items. This one should see Foo item deleted and Bar item added.
+        final TestListener<TopLevelList> allListener = createListener(CONFIGURATION, WILDCARDED,
+                added(TOP_FOO, topFoo), added(TOP_BAR, topBar), deleted(TOP_FOO, topFoo));
+
+        // Listener for all Foo item. This one should see only Foo item deleted.
+        final TestListener<TopLevelList> fooListener = createListener(CONFIGURATION, TOP_FOO,
+                added(TOP_FOO, topFoo), deleted(TOP_FOO, topFoo));
+
+        // Listener for bar list items.
+        final TestListener<TopLevelList> barListener = createListener(CONFIGURATION, TOP_BAR,
+                added(TOP_BAR, topBar));
 
         ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
-        writeTx.put(CONFIGURATION, TOP, top(topLevelList(TOP_BAR_KEY)));
+        writeTx.put(CONFIGURATION, TOP, top);
         assertCommit(writeTx.submit());
-        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);
-        assertContains(top.getCreatedData(), TOP_BAR);
-        assertContains(top.getUpdatedData(), TOP);
-        assertContains(top.getRemovedPaths(), TOP_FOO);
-
-        /*
-         *  Listener for all list items
-         *
-         *  Updated should be empty, since no list item was
-         *  updated, items were only removed and added
-         */
-        assertContains(all.getOriginalData(), TOP_FOO);
-        assertContains(all.getCreatedData(), TOP_BAR);
-        assertEmpty(all.getUpdatedData());
-        assertContains(all.getRemovedPaths(), TOP_FOO);
-
-
-        /*
-         *  Listener for all Foo item
-         *
-         *  This one should see only Foo item removed
-         */
-        assertContains(foo.getOriginalData(), TOP_FOO);
-        assertEmpty(foo.getCreatedData());
-        assertEmpty(foo.getUpdatedData());
-        assertContains(foo.getRemovedPaths(), TOP_FOO);
-
-        /*
-         *  Listener for bar list items
-         *
-         *  Updated should be empty, since no list item was
-         *  updated, items were only removed and added
-         */
-        assertEmpty(bar.getOriginalData());
-        assertContains(bar.getCreatedData(), TOP_BAR);
-        assertEmpty(bar.getUpdatedData());
-        assertEmpty(bar.getRemovedPaths());
+        topListener.verify();
+        allListener.verify();
+        fooListener.verify();
+        barListener.verify();
     }
 
     @Test
     public void mergeTopNodeSubtreeListeners() {
-        TestListener topListener = createListener(CONFIGURATION, TOP, 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, false);
+        final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
+        final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
+
+        final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+                added(TOP, top(topLevelList(TOP_FOO_KEY))), topSubtreeModified(topFoo, topBar));
+        final TestListener<TopLevelList> allListener = createListener(CONFIGURATION, WILDCARDED,
+                added(TOP_FOO, topFoo), added(TOP_BAR, topBar));
+        final TestListener<TopLevelList> fooListener = createListener(CONFIGURATION, TOP_FOO,
+                added(TOP_FOO, topFoo));
+        final TestListener<TopLevelList> barListener = createListener(CONFIGURATION, TOP_BAR,
+                added(TOP_BAR, topBar));
 
         ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
         writeTx.merge(CONFIGURATION, TOP, top(topLevelList(TOP_BAR_KEY)));
         assertCommit(writeTx.submit());
 
-        verifyBarOnlyAdded(topListener,allListener,fooListener,barListener);
+        topListener.verify();
+        allListener.verify();
+        fooListener.verify();
+        barListener.verify();
     }
 
     @Test
     public void putTopBarNodeSubtreeListeners() {
-        TestListener topListener = createListener(CONFIGURATION, TOP, 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, false);
+        final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
+        final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
+
+        final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+                added(TOP, top(topLevelList(TOP_FOO_KEY))), topSubtreeModified(topFoo, topBar));
+        final TestListener<TopLevelList> allListener = createListener(CONFIGURATION, WILDCARDED,
+                added(TOP_FOO, topFoo), added(TOP_BAR, topBar));
+        final TestListener<TopLevelList> fooListener = createListener(CONFIGURATION, TOP_FOO,
+                added(TOP_FOO, topFoo));
+        final TestListener<TopLevelList> barListener = createListener(CONFIGURATION, TOP_BAR,
+                added(TOP_BAR, topBar));
 
         ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
         writeTx.put(CONFIGURATION, TOP_BAR, topLevelList(TOP_BAR_KEY));
         assertCommit(writeTx.submit());
 
-        verifyBarOnlyAdded(topListener,allListener,fooListener,barListener);
+        topListener.verify();
+        allListener.verify();
+        fooListener.verify();
+        barListener.verify();
     }
 
     @Test
     public void mergeTopBarNodeSubtreeListeners() {
-        TestListener topListener = createListener(CONFIGURATION, TOP, 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, false);
+        final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
+        final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
+
+        final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+                added(TOP, top(topLevelList(TOP_FOO_KEY))), topSubtreeModified(topFoo, topBar));
+        final TestListener<TopLevelList> allListener = createListener(CONFIGURATION, WILDCARDED,
+                added(TOP_FOO, topFoo), added(TOP_BAR, topBar));
+        final TestListener<TopLevelList> fooListener = createListener(CONFIGURATION, TOP_FOO,
+                added(TOP_FOO, topFoo));
+        final TestListener<TopLevelList> barListener = createListener(CONFIGURATION, TOP_BAR,
+                added(TOP_BAR, topBar));
 
         ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
         writeTx.merge(CONFIGURATION, TOP_BAR, topLevelList(TOP_BAR_KEY));
         assertCommit(writeTx.submit());
 
-        verifyBarOnlyAdded(topListener,allListener,fooListener,barListener);
+        topListener.verify();
+        allListener.verify();
+        fooListener.verify();
+        barListener.verify();
     }
 
-    private void verifyBarOnlyAdded(final TestListener top, final TestListener all, final TestListener foo,
-            final TestListener bar) {
-
-        assertFalse(foo.hasEvent());
-
-        // Listener for TOP element
-        assertContains(top.event().getOriginalData(), TOP);
-        assertNotContains(top.event().getOriginalData(),TOP_FOO);
-        assertContains(top.event().getCreatedData(), TOP_BAR);
-        assertContains(top.event().getUpdatedData(), TOP);
-        assertEmpty(top.event().getRemovedPaths());
-
-        /*
-         *  Listener for all list items
-         *
-         *  Updated should be empty, since no list item was
-         *  updated, items were only removed and added
-         */
-        assertEmpty(all.event().getOriginalData());
-        assertContains(all.event().getCreatedData(), TOP_BAR);
-        assertEmpty(all.event().getUpdatedData());
-        assertEmpty(all.event().getRemovedPaths());
-
-        /*
-         *  Listener for all Foo item
-         *
-         *  Foo Listener should not have foo event
-         */
-        assertFalse(foo.hasEvent());
-
-        /*
-         *  Listener for bar list items
-         *
-         *  Updated should be empty, since no list item was
-         *  updated, items were only removed and added
-         */
-        assertEmpty(bar.event().getOriginalData());
-        assertContains(bar.event().getCreatedData(), TOP_BAR);
-        assertEmpty(bar.event().getUpdatedData());
-        assertEmpty(bar.event().getRemovedPaths());
+    private Function<DataTreeModification<Top>, Boolean> topSubtreeModified(TopLevelList topFoo, TopLevelList topBar) {
+        return match(ModificationType.SUBTREE_MODIFIED, TOP,
+            (Function<Top, Boolean>) dataBefore -> Objects.equals(top(topFoo), dataBefore),
+            dataAfter -> {
+                Set<TopLevelList> expList = new HashSet<>(top(topBar, topFoo).getTopLevelList());
+                Set<TopLevelList> actualList = dataAfter.getTopLevelList().stream()
+                        .map(list -> new TopLevelListBuilder(list).build()).collect(Collectors.toSet());
+                return expList.equals(actualList);
+            });
     }
-
 }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractDataChangeListenerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractDataChangeListenerTest.java
deleted file mode 100644 (file)
index 2a5c0e8..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-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;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public abstract class AbstractDataChangeListenerTest extends AbstractConcurrentDataBrokerTest {
-
-    protected static final class TestListener implements DataChangeListener {
-
-        private final SettableFuture<AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>> event;
-        private final CountDownLatch initialEventLatch;
-        private volatile boolean capture = false;
-
-        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();
-            }
-        }
-
-        public AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event() {
-            try {
-                return event.get(500, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException | TimeoutException | ExecutionException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-
-        public boolean hasEvent() {
-            return event.isDone();
-        }
-
-        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) {
-        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.waitForInitialEvent();
-        return listener;
-    }
-}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractDataTreeChangeListenerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractDataTreeChangeListenerTest.java
new file mode 100644 (file)
index 0000000..f2b5f93
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018 Inocybe Technologies and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.binding.test;
+
+import static org.junit.Assert.fail;
+
+import com.google.common.util.concurrent.SettableFuture;
+import com.google.common.util.concurrent.Uninterruptibles;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Function;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Abstract base that provides a DTCL for verification.
+ *
+ * @author Thomas Pantelis
+ */
+public class AbstractDataTreeChangeListenerTest extends AbstractConcurrentDataBrokerTest {
+    protected static final class TestListener<T extends DataObject> implements DataTreeChangeListener<T> {
+
+        private final List<DataTreeModification<T>> accumulatedChanges = new ArrayList<>();
+        private final SettableFuture<Collection<DataTreeModification<T>>> future = SettableFuture.create();
+        private final Function<DataTreeModification<T>, Boolean>[] matchers;
+        private final int expChangeCount;
+
+        private TestListener(Function<DataTreeModification<T>, Boolean>[] matchers) {
+            this.expChangeCount = matchers.length;
+            this.matchers = matchers;
+        }
+
+        @Override
+        public void onDataTreeChanged(Collection<DataTreeModification<T>> changes) {
+            synchronized (accumulatedChanges) {
+                accumulatedChanges.addAll(changes);
+                if (expChangeCount == accumulatedChanges.size()) {
+                    future.set(new ArrayList<>(accumulatedChanges));
+                }
+            }
+        }
+
+        public Collection<DataTreeModification<T>> changes() {
+            try {
+                final Collection<DataTreeModification<T>> changes = future.get(5, TimeUnit.SECONDS);
+                Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
+                return changes;
+            } catch (InterruptedException | TimeoutException | ExecutionException e) {
+                throw new AssertionError(String.format(
+                    "Data tree change notifications not received. Expected: %s. Actual: %s - %s",
+                        expChangeCount, accumulatedChanges.size(), accumulatedChanges), e);
+            }
+        }
+
+        public void verify() {
+            Collection<DataTreeModification<T>> changes = new ArrayList<>(changes());
+            Iterator<DataTreeModification<T>> iter = changes.iterator();
+            while (iter.hasNext()) {
+                DataTreeModification<T> dataTreeModification = iter.next();
+                for (Function<DataTreeModification<T>, Boolean> matcher: matchers) {
+                    if (matcher.apply(dataTreeModification)) {
+                        iter.remove();
+                        break;
+                    }
+                }
+            }
+
+            if (!changes.isEmpty()) {
+                DataTreeModification<T> mod = changes.iterator().next();
+                fail(String.format("Received unexpected notification: type: %s, path: %s, before: %s, after: %s",
+                        mod.getRootNode().getModificationType(), mod.getRootPath().getRootIdentifier(),
+                        mod.getRootNode().getDataBefore(), mod.getRootNode().getDataAfter()));
+            }
+        }
+
+        public boolean hasChanges() {
+            synchronized (accumulatedChanges) {
+                return !accumulatedChanges.isEmpty();
+            }
+        }
+    }
+
+    protected AbstractDataTreeChangeListenerTest() {
+        super(true);
+    }
+
+    @SafeVarargs
+    protected final <T extends DataObject> TestListener<T> createListener(final LogicalDatastoreType store,
+            final InstanceIdentifier<T> path, Function<DataTreeModification<T>, Boolean>... matchers) {
+        TestListener<T> listener = new TestListener<>(matchers);
+        getDataBroker().registerDataTreeChangeListener(new DataTreeIdentifier<>(store, path), listener);
+        return listener;
+    }
+
+    public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> match(
+            ModificationType type, InstanceIdentifier<T> path, Function<T, Boolean> checkDataBefore,
+            Function<T, Boolean> checkDataAfter) {
+        return modification -> type == modification.getRootNode().getModificationType()
+                && path.equals(modification.getRootPath().getRootIdentifier())
+                && checkDataBefore.apply(modification.getRootNode().getDataBefore())
+                && checkDataAfter.apply(modification.getRootNode().getDataAfter());
+    }
+
+    public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> match(
+            ModificationType type, InstanceIdentifier<T> path, T expDataBefore, T expDataAfter) {
+        return match(type, path, dataBefore -> Objects.equals(expDataBefore, dataBefore),
+            (Function<T, Boolean>) dataAfter -> Objects.equals(expDataAfter, dataAfter));
+    }
+
+    public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> added(
+            InstanceIdentifier<T> path, T data) {
+        return match(ModificationType.WRITE, path, null, data);
+    }
+
+    public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> replaced(
+            InstanceIdentifier<T> path, T dataBefore, T dataAfter) {
+        return match(ModificationType.WRITE, path, dataBefore, dataAfter);
+    }
+
+    public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> deleted(
+            InstanceIdentifier<T> path, T dataBefore) {
+        return match(ModificationType.DELETE, path, dataBefore, null);
+    }
+
+    public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> subtreeModified(
+            InstanceIdentifier<T> path, T dataBefore, T dataAfter) {
+        return match(ModificationType.SUBTREE_MODIFIED, path, dataBefore, dataAfter);
+    }
+}
index e9f0b20..48872a8 100644 (file)
@@ -8,10 +8,10 @@
 package org.opendaylight.controller.md.sal.binding.data;
 
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
 
-import com.google.common.util.concurrent.SettableFuture;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Uninterruptibles;
 import java.util.Collections;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
@@ -19,10 +19,7 @@ import java.util.concurrent.TimeoutException;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ContainerWithUses;
@@ -33,13 +30,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
 /**
  * FIXME: THis test should be moved to compat test-suite
  */
-public class WildcardedDataChangeListenerTest extends AbstractDataServiceTest {
+public class WildcardedDataChangeListenerTest extends AbstractDataTreeChangeListenerTest {
 
     private static final TopLevelListKey TOP_LEVEL_LIST_0_KEY = new TopLevelListKey("test:0");
     private static final TopLevelListKey TOP_LEVEL_LIST_1_KEY = new TopLevelListKey("test:1");
@@ -82,90 +80,78 @@ public class WildcardedDataChangeListenerTest extends AbstractDataServiceTest {
             .setName("john")
             .build();
 
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+                BindingReflections.getModuleInfo(TreeComplexUsesAugment.class));
+    }
+
     @Test
     public void testSeparateWrites() throws InterruptedException, TimeoutException, ExecutionException {
 
-        DataBroker dataBroker = testContext.getDataBroker();
+        DataBroker dataBroker = getDataBroker();
 
-        final SettableFuture<AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>> eventFuture =
-                SettableFuture.create();
-        dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, DEEP_WILDCARDED_PATH,
-            dataChangeEvent -> eventFuture.set(dataChangeEvent), DataChangeScope.SUBTREE);
+        final TestListener<ListViaUses> listener = createListener(OPERATIONAL, DEEP_WILDCARDED_PATH,
+            dataTreeModification -> NODE_0_LVU_PATH.equals(dataTreeModification.getRootPath().getRootIdentifier()),
+            dataTreeModification -> NODE_1_LVU_PATH.equals(dataTreeModification.getRootPath().getRootIdentifier()));
 
         final WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
-        transaction.put(LogicalDatastoreType.OPERATIONAL, NODE_0_CWU_PATH, CWU, true);
-        transaction.put(LogicalDatastoreType.OPERATIONAL, NODE_0_LVU_PATH, LVU, true);
-        transaction.put(LogicalDatastoreType.OPERATIONAL, NODE_1_LVU_PATH, LVU, true);
+        transaction.put(OPERATIONAL, NODE_0_CWU_PATH, CWU, true);
+        transaction.put(OPERATIONAL, NODE_0_LVU_PATH, LVU, true);
+        transaction.put(OPERATIONAL, NODE_1_LVU_PATH, LVU, true);
         transaction.submit().get(5, TimeUnit.SECONDS);
 
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = eventFuture.get(1000, TimeUnit.MILLISECONDS);
-
-        validateEvent(event);
+        listener.verify();
     }
 
     @Test
     public void testWriteByReplace() throws InterruptedException, TimeoutException, ExecutionException {
 
-        DataBroker dataBroker = testContext.getDataBroker();
+        DataBroker dataBroker = getDataBroker();
 
-        final SettableFuture<AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>> eventFuture =
-                SettableFuture.create();
-        dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, DEEP_WILDCARDED_PATH,
-            dataChangeEvent -> eventFuture.set(dataChangeEvent), DataChangeScope.SUBTREE);
+        final TestListener<ListViaUses> listener = createListener(OPERATIONAL, DEEP_WILDCARDED_PATH,
+            dataTreeModification -> NODE_0_LVU_PATH.equals(dataTreeModification.getRootPath().getRootIdentifier()),
+            dataTreeModification -> NODE_1_LVU_PATH.equals(dataTreeModification.getRootPath().getRootIdentifier()));
 
         final WriteTransaction cwuTx = dataBroker.newWriteOnlyTransaction();
-        cwuTx.put(LogicalDatastoreType.OPERATIONAL, NODE_0_CWU_PATH, CWU, true);
+        cwuTx.put(OPERATIONAL, NODE_0_CWU_PATH, CWU, true);
         cwuTx.submit().get(5, TimeUnit.SECONDS);
 
-        assertFalse(eventFuture.isDone());
+        Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
+        assertFalse(listener.hasChanges());
 
         final WriteTransaction lvuTx = dataBroker.newWriteOnlyTransaction();
 
         TreeComplexUsesAugment tcua = new TreeComplexUsesAugmentBuilder()
                 .setListViaUses(Collections.singletonList(LVU)).build();
 
-        lvuTx.put(LogicalDatastoreType.OPERATIONAL, NODE_0_TCU_PATH, tcua, true);
-        lvuTx.put(LogicalDatastoreType.OPERATIONAL, NODE_1_LVU_PATH, LVU, true);
+        lvuTx.put(OPERATIONAL, NODE_0_TCU_PATH, tcua, true);
+        lvuTx.put(OPERATIONAL, NODE_1_LVU_PATH, LVU, true);
         lvuTx.submit().get(5, TimeUnit.SECONDS);
 
-        validateEvent(eventFuture.get(1000, TimeUnit.MILLISECONDS));
+        listener.verify();
     }
 
     @Test
-    public void testNoChangeOnReplaceWithSameValue() throws InterruptedException, TimeoutException, ExecutionException {
+    public void testChangeOnReplaceWithSameValue() throws InterruptedException, TimeoutException, ExecutionException {
 
-        DataBroker dataBroker = testContext.getDataBroker();
+        DataBroker dataBroker = getDataBroker();
 
-        // We wrote initial state NODE_0_FLOW
+        // Write initial state NODE_0_FLOW
         final WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
-        transaction.put(LogicalDatastoreType.OPERATIONAL, NODE_0_LVU_PATH, LVU, true);
+        transaction.put(OPERATIONAL, NODE_0_LVU_PATH, LVU, true);
         transaction.submit().get(5, TimeUnit.SECONDS);
 
-        // We registered DataChangeListener
-        final SettableFuture<AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>> eventFuture =
-                SettableFuture.create();
-        dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, DEEP_WILDCARDED_PATH,
-            dataChangeEvent -> eventFuture.set(dataChangeEvent), DataChangeScope.SUBTREE);
-        assertFalse(eventFuture.isDone());
+        final TestListener<ListViaUses> listener = createListener(OPERATIONAL, DEEP_WILDCARDED_PATH,
+            dataTreeModification -> NODE_1_LVU_PATH.equals(dataTreeModification.getRootPath().getRootIdentifier()),
+            dataTreeModification -> NODE_0_LVU_PATH.equals(dataTreeModification.getRootPath().getRootIdentifier()),
+            dataTreeModification -> NODE_1_LVU_PATH.equals(dataTreeModification.getRootPath().getRootIdentifier()));
 
         final WriteTransaction secondTx = dataBroker.newWriteOnlyTransaction();
-        secondTx.put(LogicalDatastoreType.OPERATIONAL, NODE_0_LVU_PATH, LVU, true);
-        secondTx.put(LogicalDatastoreType.OPERATIONAL, NODE_1_LVU_PATH, LVU, true);
+        secondTx.put(OPERATIONAL, NODE_0_LVU_PATH, LVU, true);
+        secondTx.put(OPERATIONAL, NODE_1_LVU_PATH, LVU, true);
         secondTx.submit().get(5, TimeUnit.SECONDS);
 
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event = eventFuture.get(1000, TimeUnit.MILLISECONDS);
-        assertNotNull(event);
-        // Data change should contains NODE_1 Flow - which was added
-        assertTrue(event.getCreatedData().containsKey(NODE_1_LVU_PATH));
-        // Data change must not containe NODE_0 Flow which was replaced with same value.
-        assertFalse(event.getUpdatedData().containsKey(NODE_0_LVU_PATH));
+        listener.verify();
     }
-
-    private static void validateEvent(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> event) {
-        assertNotNull(event);
-        assertTrue(event.getCreatedData().containsKey(NODE_1_LVU_PATH));
-        assertTrue(event.getCreatedData().containsKey(NODE_0_LVU_PATH));
-        assertFalse(event.getCreatedData().containsKey(NODE_0_CWU_PATH));
-    }
-
 }
index 213f62e..be22d83 100644 (file)
@@ -8,19 +8,15 @@
 
 package org.opendaylight.controller.sal.binding.test.bugfix;
 
-import static org.junit.Assert.assertFalse;
-
-import com.google.common.util.concurrent.SettableFuture;
+import com.google.common.collect.ImmutableSet;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.List11SimpleAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.List11SimpleAugmentBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment;
@@ -32,10 +28,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
-public class DeleteNestedAugmentationListenParentTest extends AbstractDataServiceTest {
+public class DeleteNestedAugmentationListenParentTest extends AbstractDataTreeChangeListenerTest {
 
     private static final TopLevelListKey FOO_KEY = new TopLevelListKey("foo");
 
@@ -53,25 +50,31 @@ public class DeleteNestedAugmentationListenParentTest extends AbstractDataServic
             .child(List11.class,LIST11_KEY)
             .build();
 
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+                BindingReflections.getModuleInfo(List11SimpleAugment.class));
+    }
 
     @Test
     public void deleteChildListenParent() throws InterruptedException, ExecutionException, TimeoutException {
-        DataBroker dataBroker = testContext.getDataBroker();
+        DataBroker dataBroker = getDataBroker();
         final WriteTransaction initTx = dataBroker.newWriteOnlyTransaction();
 
-        initTx.put(LogicalDatastoreType.OPERATIONAL, LIST11_PATH, createList11(), true);
+        List11 list11Before = createList11();
+        initTx.put(LogicalDatastoreType.OPERATIONAL, LIST11_PATH, list11Before, true);
         initTx.submit().get(5, TimeUnit.SECONDS);
 
-        final SettableFuture<AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>> event = SettableFuture.create();
-        dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, LIST11_PATH,
-            change -> event.set(change), DataChangeScope.SUBTREE);
+        List11 list11After = new List11Builder().setKey(LIST11_KEY).setAttrStr("good").build();
+
+        final TestListener<List11> listener = createListener(LogicalDatastoreType.OPERATIONAL, LIST11_PATH,
+                added(LIST11_PATH, list11Before), subtreeModified(LIST11_PATH, list11Before, list11After));
 
         final WriteTransaction deleteTx = dataBroker.newWriteOnlyTransaction();
         deleteTx.delete(LogicalDatastoreType.OPERATIONAL, LIST11_PATH.augmentation(List11SimpleAugment.class));
         deleteTx.submit().get(5, TimeUnit.SECONDS);
 
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> receivedEvent = event.get();
-        assertFalse(receivedEvent.getRemovedPaths().contains(TLL_COMPLEX_AUGMENT_PATH));
+        listener.verify();
     }
 
     private List11 createList11() {
@@ -82,5 +85,4 @@ public class DeleteNestedAugmentationListenParentTest extends AbstractDataServic
             .setAttrStr("good");
         return builder.build();
     }
-
 }
index aba648c..4a76ad9 100644 (file)
@@ -9,17 +9,14 @@
 package org.opendaylight.controller.sal.binding.test.bugfix;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
 
-import com.google.common.util.concurrent.SettableFuture;
+import com.google.common.collect.ImmutableSet;
 import java.util.concurrent.TimeUnit;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
@@ -27,11 +24,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 
-public class WriteParentListenAugmentTest extends AbstractDataServiceTest {
+public class WriteParentListenAugmentTest extends AbstractDataTreeChangeListenerTest {
 
     private static final String TLL_NAME = "foo";
 
@@ -45,34 +42,37 @@ public class WriteParentListenAugmentTest extends AbstractDataServiceTest {
     private static final InstanceIdentifier<TreeComplexUsesAugment> AUGMENT_TLL_PATH = InstanceIdentifier
             .builder(Top.class).child(TopLevelList.class, TLL_KEY).augmentation(TreeComplexUsesAugment.class).build();
 
+    @Override
+    protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+        return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+                BindingReflections.getModuleInfo(TreeComplexUsesAugment.class));
+    }
+
     @Test
     public void writeNodeListenAugment() throws Exception {
 
-        final SettableFuture<AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject>> event = SettableFuture.create();
-        DataBroker dataBroker = testContext.getDataBroker();
-        ListenerRegistration<org.opendaylight.controller.md.sal.binding.api.DataChangeListener> dclRegistration =
-                dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, AUGMENT_WILDCARDED_PATH,
-                    change -> event.set(change), DataChangeScope.SUBTREE);
+        DataBroker dataBroker = getDataBroker();
+
+        final TreeComplexUsesAugment treeComplexUsesAugment = treeComplexUsesAugment("one");
+
+        final TestListener<TreeComplexUsesAugment> listener = createListener(OPERATIONAL, AUGMENT_WILDCARDED_PATH,
+                added(AUGMENT_TLL_PATH, treeComplexUsesAugment));
 
         final WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
 
-        TopLevelList tll = new TopLevelListBuilder()
-                .setKey(TLL_KEY)
-                .addAugmentation(TreeComplexUsesAugment.class, treeComplexUsesAugment("one")).build();
-        transaction.put(LogicalDatastoreType.OPERATIONAL, TLL_INSTANCE_ID_BA, tll, true);
+        TopLevelList tll = new TopLevelListBuilder().setKey(TLL_KEY)
+                .addAugmentation(TreeComplexUsesAugment.class, treeComplexUsesAugment).build();
+        transaction.put(OPERATIONAL, TLL_INSTANCE_ID_BA, tll, true);
         transaction.submit().get(5, TimeUnit.SECONDS);
 
-        AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> receivedEvent = event.get(1000, TimeUnit.MILLISECONDS);
-        assertTrue(receivedEvent.getCreatedData().containsKey(AUGMENT_TLL_PATH));
-
-        dclRegistration.close();
+        listener.verify();
 
         final WriteTransaction transaction2 = dataBroker.newWriteOnlyTransaction();
-        transaction2.put(LogicalDatastoreType.OPERATIONAL, AUGMENT_TLL_PATH, treeComplexUsesAugment("two"));
+        transaction2.put(OPERATIONAL, AUGMENT_TLL_PATH, treeComplexUsesAugment("two"));
         transaction2.submit().get(5, TimeUnit.SECONDS);
 
         TreeComplexUsesAugment readedAug = dataBroker.newReadOnlyTransaction().read(
-                LogicalDatastoreType.OPERATIONAL, AUGMENT_TLL_PATH).get(5, TimeUnit.SECONDS).get();
+                OPERATIONAL, AUGMENT_TLL_PATH).get(5, TimeUnit.SECONDS).get();
         assertEquals("two", readedAug.getContainerWithUses().getLeafFromGrouping());
     }
 
index eafa2dc..852c4e4 100644 (file)
@@ -159,8 +159,7 @@ public interface AsyncWriteTransaction<P extends Path<P>, D> extends AsyncTransa
      * ({@link AsyncConfigurationCommitHandler}) if the transaction changes the data tree.
      *
      * <p>
-     * The effects of a successful commit of data depends on data change listeners
-     * ({@link AsyncDataChangeListener}) and commit participants
+     * The effects of a successful commit of data depends on data tree change listeners and commit participants
      * ({@link AsyncConfigurationCommitHandler}) that are registered with the data broker.
      *
      * <h3>Example usage:</h3>
index 738a87c..dfc0ae1 100644 (file)
@@ -41,7 +41,6 @@ import org.opendaylight.controller.cluster.databroker.ConcurrentDOMDataBroker;
 import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
 import org.opendaylight.controller.cluster.datastore.exceptions.NoShardLeaderException;
 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.DataStoreUnavailableException;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -50,7 +49,6 @@ import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.api.ClusteredDOMDataTreeChangeListener;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
@@ -433,20 +431,6 @@ public class LegacyDOMDataBrokerAdapterTest {
         verify(mockConfigStore).registerCommitCohort(treeId, mockCohort);
     }
 
-    @Test
-    public void testDataChangeListener() {
-        DOMDataChangeListener listener = mock(DOMDataChangeListener.class);
-        ListenerRegistration<DOMDataChangeListener> mockReg = mock(ListenerRegistration.class);
-        doReturn(mockReg).when(mockConfigStore).registerChangeListener(
-                TestModel.TEST_PATH, listener, DataChangeScope.ONE);
-
-        ListenerRegistration<DOMDataChangeListener> reg = adapter.registerDataChangeListener(
-                LogicalDatastoreType.CONFIGURATION, TestModel.TEST_PATH, listener, DataChangeScope.ONE);
-        assertEquals("ListenerRegistration<DOMDataChangeListener>", mockReg, reg);
-
-        verify(mockConfigStore).registerChangeListener(TestModel.TEST_PATH, listener, DataChangeScope.ONE);
-    }
-
     @Test
     @Deprecated
     public void testSubmit() throws Exception {
index 519c364..b2fb3c2 100644 (file)
@@ -8,7 +8,6 @@
 
 package org.opendaylight.controller.md.sal.dom.broker.impl;
 
-import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -18,13 +17,10 @@ import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastor
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ForwardingExecutorService;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -36,12 +32,9 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
@@ -50,7 +43,6 @@ import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
 import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -211,139 +203,6 @@ public class DOMBrokerTest {
         }
     }
 
-    /**
-     * Tests a simple DataChangeListener notification after a write.
-     */
-    @Test
-    @SuppressWarnings("checkstyle:IllegalThrows")
-    public void testDataChangeListener() throws Throwable {
-
-        final NormalizedNode<?, ?> testNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
-
-        TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener();
-
-        domBroker.registerDataChangeListener(OPERATIONAL, TestModel.TEST_PATH, dcListener, DataChangeScope.BASE);
-
-        final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
-        assertNotNull(writeTx);
-
-        writeTx.put(OPERATIONAL, TestModel.TEST_PATH, testNode);
-
-        AtomicReference<Throwable> caughtEx = submitTxAsync(writeTx);
-
-        dcListener.waitForChange();
-
-        if (caughtEx.get() != null) {
-            throw caughtEx.get();
-        }
-
-        NormalizedNode<?, ?> actualNode = dcListener.capturedChange.getCreatedData().get(TestModel.TEST_PATH);
-        assertEquals("Created node", testNode, actualNode);
-    }
-
-    /**
-     * Tests a DataChangeListener that does an async submit of a write Tx in its onDataChanged method.
-     * This should succeed without deadlock.
-     */
-    @Test
-    @SuppressWarnings("checkstyle:IllegalThrows")
-    public void testDataChangeListenerDoingAsyncWriteTxSubmit() throws Throwable {
-
-        final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
-        final CountDownLatch commitCompletedLatch = new CountDownLatch(1);
-
-        TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
-            @Override
-            public void onDataChanged(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
-
-                DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
-                writeTx.put(OPERATIONAL, TestModel.TEST2_PATH, ImmutableNodes.containerNode(TestModel.TEST2_QNAME));
-                Futures.addCallback(writeTx.submit(), new FutureCallback<Void>() {
-                    @Override
-                    public void onSuccess(final Void result) {
-                        commitCompletedLatch.countDown();
-                    }
-
-                    @Override
-                    public void onFailure(final Throwable throwable) {
-                        caughtCommitEx.set(throwable);
-                        commitCompletedLatch.countDown();
-                    }
-                }, MoreExecutors.directExecutor());
-
-                super.onDataChanged(change);
-            }
-        };
-
-        domBroker.registerDataChangeListener(OPERATIONAL, TestModel.TEST_PATH, dcListener, DataChangeScope.BASE);
-
-        final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
-        assertNotNull(writeTx);
-
-        writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
-
-        AtomicReference<Throwable> caughtEx = submitTxAsync(writeTx);
-
-        dcListener.waitForChange();
-
-        if (caughtEx.get() != null) {
-            throw caughtEx.get();
-        }
-
-        assertTrue("Commit Future was not invoked", commitCompletedLatch.await(5, TimeUnit.SECONDS));
-
-        if (caughtCommitEx.get() != null) {
-            throw caughtCommitEx.get();
-        }
-    }
-
-    /**
-     * Tests a DataChangeListener that does a blocking submit of a write Tx in its onDataChanged method.
-     * This should throw an exception and not deadlock.
-     */
-    @Test(expected = TransactionCommitDeadlockException.class)
-    @SuppressWarnings({"checkstyle:IllegalThrows", "checkstyle:IllegalCatch"})
-    public void testDataChangeListenerDoingBlockingWriteTxSubmit() throws Throwable {
-
-        final AtomicReference<Throwable> caughtCommitEx = new AtomicReference<>();
-
-        TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() {
-            @Override
-            public void onDataChanged(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
-                DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
-                writeTx.put(OPERATIONAL, TestModel.TEST2_PATH, ImmutableNodes.containerNode(TestModel.TEST2_QNAME));
-                try {
-                    writeTx.commit().get();
-                } catch (ExecutionException e) {
-                    caughtCommitEx.set(e.getCause());
-                } catch (Exception e) {
-                    caughtCommitEx.set(e);
-                } finally {
-                    super.onDataChanged(change);
-                }
-            }
-        };
-
-        domBroker.registerDataChangeListener(OPERATIONAL, TestModel.TEST_PATH, dcListener, DataChangeScope.BASE);
-
-        final DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
-        assertNotNull(writeTx);
-
-        writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
-
-        AtomicReference<Throwable> caughtEx = submitTxAsync(writeTx);
-
-        dcListener.waitForChange();
-
-        if (caughtEx.get() != null) {
-            throw caughtEx.get();
-        }
-
-        if (caughtCommitEx.get() != null) {
-            throw caughtCommitEx.get();
-        }
-    }
-
     @SuppressWarnings("checkstyle:IllegalCatch")
     AtomicReference<Throwable> submitTxAsync(final DOMDataWriteTransaction writeTx) {
         final AtomicReference<Throwable> caughtEx = new AtomicReference<>();
@@ -358,21 +217,6 @@ public class DOMBrokerTest {
         return caughtEx;
     }
 
-    static class TestDOMDataChangeListener implements DOMDataChangeListener {
-
-        volatile AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> capturedChange;
-        private final CountDownLatch latch = new CountDownLatch(1);
-
-        @Override
-        public void onDataChanged(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
-            this.capturedChange = change;
-            latch.countDown();
-        }
-
-        void waitForChange() throws InterruptedException {
-            assertTrue("onDataChanged was not called", latch.await(5, TimeUnit.SECONDS));
-        }
-    }
 
     static class CommitExecutorService extends ForwardingExecutorService {
 
@@ -36,7 +36,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContaine
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-public abstract class AbstractDataChangeListenerTest {
+public abstract class AbstractDataTreeChangeListenerTest {
 
     protected static final YangInstanceIdentifier TOP_LEVEL = YangInstanceIdentifier
             .of(Top.QNAME);
@@ -59,7 +59,7 @@ public abstract class AbstractDataChangeListenerTest {
 
         this.dclExecutorService = new TestDCLExecutorService(
                 SpecialExecutors.newBlockingBoundedFastThreadPool(1, 10, "DCL",
-                    AbstractDataChangeListenerTest.class));
+                    AbstractDataTreeChangeListenerTest.class));
 
         this.datastore = new InMemoryDOMDataStore("TEST", this.dclExecutorService);
         this.datastore.onGlobalContextUpdated(this.schemaContext);
index ed17aa5..a62c0ba 100644 (file)
@@ -12,53 +12,76 @@ import static org.junit.Assert.fail;
 
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.SettableFuture;
+import com.google.common.util.concurrent.Uninterruptibles;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import java.util.function.Function;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTreeChangePublisher;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
 
 public class DatastoreTestTask {
 
     private final DOMStore store;
-    private AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> changeListener;
 
     private WriteTransactionCustomizer setup;
     private WriteTransactionCustomizer write;
     private ReadTransactionVerifier read;
     private WriteTransactionCustomizer cleanup;
     private YangInstanceIdentifier changePath;
-    private DataChangeScope changeScope;
-    private volatile boolean postSetup = false;
-    private final ChangeEventListener internalListener;
+    private DOMStoreTreeChangePublisher storeTreeChangePublisher;
+    private ChangeEventListener internalListener;
     private final TestDCLExecutorService dclExecutorService;
 
     public DatastoreTestTask(final DOMStore datastore, final TestDCLExecutorService dclExecutorService) {
         this.store = datastore;
         this.dclExecutorService = dclExecutorService;
-        internalListener = new ChangeEventListener();
     }
 
-    public DatastoreTestTask changeListener(final YangInstanceIdentifier path, final DataChangeScope scope,
-            final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> listener) {
-        this.changeListener = listener;
+    @SafeVarargs
+    public final DatastoreTestTask changeListener(final YangInstanceIdentifier path,
+            Function<DataTreeCandidate, Boolean>... matchers) {
+        assertTrue(store instanceof DOMStoreTreeChangePublisher);
+        this.storeTreeChangePublisher = (DOMStoreTreeChangePublisher)store;
         this.changePath = path;
-        this.changeScope = scope;
+        this.internalListener = new ChangeEventListener(matchers);
         return this;
     }
 
-    public DatastoreTestTask changeListener(final YangInstanceIdentifier path, final DataChangeScope scope) {
-        this.changePath = path;
-        this.changeScope = scope;
-        return this;
+    public static Function<DataTreeCandidate, Boolean> added(YangInstanceIdentifier path) {
+        return candidate -> candidate.getRootNode().getModificationType() == ModificationType.WRITE
+                && path.equals(candidate.getRootPath()) && !candidate.getRootNode().getDataBefore().isPresent()
+                && candidate.getRootNode().getDataAfter().isPresent();
+    }
+
+    public static Function<DataTreeCandidate, Boolean> replaced(YangInstanceIdentifier path) {
+        return candidate -> candidate.getRootNode().getModificationType() == ModificationType.WRITE
+                && path.equals(candidate.getRootPath()) && candidate.getRootNode().getDataBefore().isPresent()
+                && candidate.getRootNode().getDataAfter().isPresent();
+    }
+
+    public static Function<DataTreeCandidate, Boolean> deleted(YangInstanceIdentifier path) {
+        return candidate -> candidate.getRootNode().getModificationType() == ModificationType.DELETE
+                && path.equals(candidate.getRootPath()) && candidate.getRootNode().getDataBefore().isPresent()
+                && !candidate.getRootNode().getDataAfter().isPresent();
+    }
+
+    public static Function<DataTreeCandidate, Boolean> subtreeModified(YangInstanceIdentifier path) {
+        return candidate -> candidate.getRootNode().getModificationType() == ModificationType.SUBTREE_MODIFIED
+                && path.equals(candidate.getRootPath()) && candidate.getRootNode().getDataBefore().isPresent()
+                && candidate.getRootNode().getDataAfter().isPresent();
     }
 
     public DatastoreTestTask setup(final WriteTransactionCustomizer customizer) {
@@ -87,12 +110,11 @@ public class DatastoreTestTask {
         }
         ListenerRegistration<ChangeEventListener> registration = null;
         if (changePath != null) {
-            registration = store.registerChangeListener(changePath, internalListener, changeScope);
+            registration = storeTreeChangePublisher.registerTreeChangeListener(changePath, internalListener);
         }
 
         Preconditions.checkState(write != null, "Write Transaction must be set.");
 
-        postSetup = true;
         dclExecutorService.afterTestSetup();
 
         execute(write);
@@ -100,9 +122,6 @@ public class DatastoreTestTask {
             registration.close();
         }
 
-        if (changeListener != null) {
-            changeListener.onDataChanged(getChangeEvent());
-        }
         if (read != null) {
             read.verify(store.newReadOnlyTransaction());
         }
@@ -111,17 +130,12 @@ public class DatastoreTestTask {
         }
     }
 
-    public AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> getChangeEvent() throws Exception {
-        return internalListener.receivedChange.get(10, TimeUnit.SECONDS);
+    public void verifyChangeEvents() {
+        internalListener.verifyChangeEvents();
     }
 
-    public void verifyNoChangeEvent() throws Exception {
-        try {
-            Object unexpected = internalListener.receivedChange.get(500, TimeUnit.MILLISECONDS);
-            fail("Got unexpected AsyncDataChangeEvent from the Future: " + unexpected);
-        } catch (TimeoutException e) {
-            // Expected
-        }
+    public void verifyNoChangeEvent() {
+        internalListener.verifyNoChangeEvent();
     }
 
     private void execute(final WriteTransactionCustomizer writeCustomizer) throws InterruptedException,
@@ -142,16 +156,71 @@ public class DatastoreTestTask {
         void verify(DOMStoreReadTransaction tx);
     }
 
-    private final class ChangeEventListener implements
-            AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> {
+    private final class ChangeEventListener implements DOMDataTreeChangeListener {
+
+        final SettableFuture<Collection<DataTreeCandidate>> future = SettableFuture.create();
+        final Collection<DataTreeCandidate> accumulatedChanges = new ArrayList<>();
+        final Function<DataTreeCandidate, Boolean>[] matchers;
+        final int expChangeCount;
 
-        protected final SettableFuture<AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>>>
-                receivedChange = SettableFuture.create();
+        ChangeEventListener(Function<DataTreeCandidate, Boolean>[] matchers) {
+            this.expChangeCount = matchers.length;
+            this.matchers = matchers;
+        }
+
+        Collection<DataTreeCandidate> changes() {
+            try {
+                Collection<DataTreeCandidate> changes = internalListener.future.get(10, TimeUnit.SECONDS);
+                Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
+                return changes;
+            } catch (TimeoutException e) {
+                throw new AssertionError(String.format(
+                        "Data tree change notifications not received. Expected: %s. Actual: %s - %s",
+                        expChangeCount, accumulatedChanges.size(), accumulatedChanges), e);
+            } catch (InterruptedException | ExecutionException e) {
+                throw new AssertionError("Data tree change notifications failed", e);
+            }
+        }
+
+        void verifyChangeEvents() {
+            Collection<DataTreeCandidate> changes = new ArrayList<>(changes());
+            Iterator<DataTreeCandidate> iter = changes.iterator();
+            while (iter.hasNext()) {
+                DataTreeCandidate dataTreeModification = iter.next();
+                for (Function<DataTreeCandidate, Boolean> matcher: matchers) {
+                    if (matcher.apply(dataTreeModification)) {
+                        iter.remove();
+                        break;
+                    }
+                }
+            }
+
+            if (!changes.isEmpty()) {
+                DataTreeCandidate mod = changes.iterator().next();
+                fail(String.format("Received unexpected notification: type: %s, path: %s, before: %s, after: %s",
+                        mod.getRootNode().getModificationType(), mod.getRootPath(),
+                        mod.getRootNode().getDataBefore(), mod.getRootNode().getDataAfter()));
+            }
+        }
+
+        void verifyNoChangeEvent() {
+            try {
+                Object unexpected = internalListener.future.get(500, TimeUnit.MILLISECONDS);
+                fail("Got unexpected Data tree change notifications: " + unexpected);
+            } catch (TimeoutException e) {
+                // Expected
+            } catch (InterruptedException | ExecutionException e) {
+                throw new AssertionError("Data tree change notifications failed", e);
+            }
+        }
 
         @Override
-        public void onDataChanged(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
-            if (postSetup) {
-                receivedChange.set(change);
+        public void onDataTreeChanged(Collection<DataTreeCandidate> changes) {
+            synchronized (accumulatedChanges) {
+                accumulatedChanges.addAll(changes);
+                if (expChangeCount == accumulatedChanges.size()) {
+                    future.set(new ArrayList<>(accumulatedChanges));
+                }
             }
         }
     }
@@ -10,40 +10,37 @@ package org.opendaylight.controller.md.sal.dom.store.impl;
 import org.junit.Test;
 
 /**
- * Base template for a test suite for testing DataChangeListener functionality.
+ * Base template for a test suite for testing DataTreeChangeListener functionality.
  */
-public abstract class DefaultDataChangeListenerTestSuite extends AbstractDataChangeListenerTest {
+public abstract class DefaultDataTreeChangeListenerTestSuite extends AbstractDataTreeChangeListenerTest {
 
     protected static final String FOO_SIBLING = "foo-sibling";
 
-    /**
-     * Callback invoked when the test suite can modify task parameters.
-     *
-     * @param task Update task configuration as needed
-     */
-    protected abstract void customizeTask(DatastoreTestTask task);
-
     @Test
     public final void putTopLevelOneNested() throws Exception {
 
         DatastoreTestTask task = newTestTask().test(writeOneTopMultipleNested(FOO, BAR));
-        customizeTask(task);
+        putTopLevelOneNestedSetup(task);
         task.run();
-        putTopLevelOneNested(task);
+        putTopLevelOneNestedVerify(task);
     }
 
-    protected abstract void putTopLevelOneNested(DatastoreTestTask task) throws Exception;
+    protected abstract void putTopLevelOneNestedSetup(DatastoreTestTask task);
+
+    protected abstract void putTopLevelOneNestedVerify(DatastoreTestTask task);
 
     @Test
     public final void existingTopWriteSibling() throws Exception {
         DatastoreTestTask task = newTestTask().setup(writeOneTopMultipleNested(FOO)).test(
             tx -> tx.write(path(FOO_SIBLING), topLevelList(FOO_SIBLING).build()));
-        customizeTask(task);
+        existingTopWriteSiblingSetup(task);
         task.run();
-        existingTopWriteSibling(task);
+        existingTopWriteSiblingVerify(task);
     }
 
-    protected abstract void existingTopWriteSibling(DatastoreTestTask task) throws Exception;
+    protected abstract void existingTopWriteSiblingSetup(DatastoreTestTask task);
+
+    protected abstract void existingTopWriteSiblingVerify(DatastoreTestTask task);
 
     @Test
     public final void existingTopWriteTwoNested() throws Exception {
@@ -52,68 +49,80 @@ public abstract class DefaultDataChangeListenerTestSuite extends AbstractDataCha
                 tx.write(path(FOO,BAR), nestedList(BAR).build());
                 tx.write(path(FOO,BAZ), nestedList(BAZ).build());
             });
-        customizeTask(task);
+        existingTopWriteTwoNestedSetup(task);
         task.run();
-        existingTopWriteTwoNested(task);
+        existingTopWriteTwoNestedVerify(task);
     }
 
-    protected abstract void existingTopWriteTwoNested(DatastoreTestTask task) throws Exception;
+    protected abstract void existingTopWriteTwoNestedSetup(DatastoreTestTask task);
+
+    protected abstract void existingTopWriteTwoNestedVerify(DatastoreTestTask task);
 
 
     @Test
     public final void existingOneNestedWriteAdditionalNested() throws Exception {
         DatastoreTestTask task = newTestTask().setup(writeOneTopMultipleNested(FOO, BAR)).test(
             tx -> tx.write(path(FOO,BAZ), nestedList(BAZ).build()));
-        customizeTask(task);
+        existingOneNestedWriteAdditionalNestedSetup(task);
         task.run();
-        existingOneNestedWriteAdditionalNested(task);
+        existingOneNestedWriteAdditionalNestedVerify(task);
     }
 
-    protected abstract void existingOneNestedWriteAdditionalNested(DatastoreTestTask task) throws Exception;
+    protected abstract void existingOneNestedWriteAdditionalNestedSetup(DatastoreTestTask task);
+
+    protected abstract void existingOneNestedWriteAdditionalNestedVerify(DatastoreTestTask task);
 
     @Test
     public final void replaceTopLevelNestedChanged() throws Exception {
         DatastoreTestTask task = newTestTask().setup(writeOneTopMultipleNested(FOO, BAR)).test(
                 writeOneTopMultipleNested(FOO, BAZ));
-        customizeTask(task);
+        replaceTopLevelNestedSetup(task);
         task.run();
-        replaceTopLevelNestedChanged(task);
+        replaceTopLevelNestedVerify(task);
     }
 
-    protected abstract void replaceTopLevelNestedChanged(DatastoreTestTask task) throws Exception;
+    protected abstract void replaceTopLevelNestedSetup(DatastoreTestTask task);
+
+    protected abstract void replaceTopLevelNestedVerify(DatastoreTestTask task);
 
     @Test
     public final void putTopLevelWithTwoNested() throws Exception {
 
         DatastoreTestTask task = newTestTask().test(writeOneTopMultipleNested(FOO, BAR, BAZ));
-        customizeTask(task);
+        putTopLevelWithTwoNestedSetup(task);
         task.run();
-        putTopLevelWithTwoNested(task);
+        putTopLevelWithTwoNestedVerify(task);
     }
 
-    protected abstract void putTopLevelWithTwoNested(DatastoreTestTask task) throws Exception;
+    protected abstract void putTopLevelWithTwoNestedSetup(DatastoreTestTask task);
+
+    protected abstract void putTopLevelWithTwoNestedVerify(DatastoreTestTask task);
 
     @Test
     public final void twoNestedExistsOneIsDeleted() throws Exception {
 
         DatastoreTestTask task = newTestTask().setup(writeOneTopMultipleNested(FOO, BAR, BAZ)).test(
                 deleteNested(FOO, BAZ));
-        customizeTask(task);
+        twoNestedExistsOneIsDeletedSetup(task);
         task.run();
-        twoNestedExistsOneIsDeleted(task);
+        twoNestedExistsOneIsDeletedVerify(task);
     }
 
-    protected abstract void twoNestedExistsOneIsDeleted(DatastoreTestTask task) throws Exception;
+    protected abstract void twoNestedExistsOneIsDeletedSetup(DatastoreTestTask task);
+
+    protected abstract void twoNestedExistsOneIsDeletedVerify(DatastoreTestTask task);
 
     @Test
     public final void nestedListExistsRootDeleted() throws Exception {
 
         DatastoreTestTask task = newTestTask().cleanup(null).setup(writeOneTopMultipleNested(FOO, BAR, BAZ))
                 .test(DatastoreTestTask.simpleDelete(TOP_LEVEL));
-        customizeTask(task);
+        nestedListExistsRootDeletedSetup(task);
         task.run();
-        nestedListExistsRootDeleted(task);
+        nestedListExistsRootDeletedVerify(task);
     }
 
-    protected abstract void nestedListExistsRootDeleted(DatastoreTestTask task) throws Exception;
+    protected abstract void nestedListExistsRootDeletedSetup(DatastoreTestTask task);
+
+    protected abstract void nestedListExistsRootDeletedVerify(DatastoreTestTask task);
 }
index 7d49656..c5af406 100644 (file)
@@ -7,94 +7,90 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import static org.opendaylight.controller.md.sal.dom.store.impl.DatastoreTestTask.added;
+import static org.opendaylight.controller.md.sal.dom.store.impl.DatastoreTestTask.deleted;
+import static org.opendaylight.controller.md.sal.dom.store.impl.DatastoreTestTask.replaced;
+import static org.opendaylight.controller.md.sal.dom.store.impl.DatastoreTestTask.subtreeModified;
 
-public class RootScopeSubtreeTest extends DefaultDataChangeListenerTestSuite {
+public class RootScopeSubtreeTest extends DefaultDataTreeChangeListenerTestSuite {
 
     @Override
-    protected void customizeTask(final DatastoreTestTask task) {
-        task.changeListener(TOP_LEVEL, DataChangeScope.SUBTREE);
+    protected void putTopLevelOneNestedSetup(final DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL, added(TOP_LEVEL));
     }
 
     @Override
-    public void putTopLevelOneNested(final DatastoreTestTask task) throws Exception {
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertContains(change.getCreatedData(), TOP_LEVEL, path(FOO), path(FOO, BAR));
-        assertEmpty(change.getUpdatedData());
-        assertEmpty(change.getRemovedPaths());
+    protected void putTopLevelOneNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    public void replaceTopLevelNestedChanged(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertContains(change.getCreatedData(), path(FOO, BAZ));
-        assertContains(change.getUpdatedData(), TOP_LEVEL, path(FOO));
-        assertContains(change.getRemovedPaths(), path(FOO, BAR));
+    protected void replaceTopLevelNestedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL, added(TOP_LEVEL), replaced(TOP_LEVEL));
     }
 
     @Override
-    protected void putTopLevelWithTwoNested(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertContains(change.getCreatedData(), TOP_LEVEL, path(FOO), path(FOO, BAR), path(FOO, BAZ));
-        assertEmpty(change.getUpdatedData());
-        assertEmpty(change.getRemovedPaths());
+    protected void replaceTopLevelNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    protected void twoNestedExistsOneIsDeleted(final DatastoreTestTask task) throws Exception {
+    protected void putTopLevelWithTwoNestedSetup(final DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL, added(TOP_LEVEL));
+    }
 
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
+    @Override
+    protected void putTopLevelWithTwoNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
+    }
 
-        assertEmpty(change.getCreatedData());
-        assertContains(change.getUpdatedData(), TOP_LEVEL, path(FOO));
-        assertContains(change.getRemovedPaths(), path(FOO, BAZ));
+    @Override
+    protected void twoNestedExistsOneIsDeletedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL, added(TOP_LEVEL), subtreeModified(TOP_LEVEL));
     }
 
     @Override
-    protected void nestedListExistsRootDeleted(final DatastoreTestTask task) throws Exception {
+    protected void twoNestedExistsOneIsDeletedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
+    }
 
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
+    @Override
+    protected void nestedListExistsRootDeletedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL, added(TOP_LEVEL), deleted(TOP_LEVEL));
+    }
 
-        assertEmpty(change.getCreatedData());
-        assertEmpty(change.getUpdatedData());
-        assertContains(change.getRemovedPaths(), TOP_LEVEL, path(FOO), path(FOO, BAR), path(FOO, BAZ));
+    @Override
+    protected void nestedListExistsRootDeletedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    protected void existingOneNestedWriteAdditionalNested(final DatastoreTestTask task) throws Exception {
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
+    protected void existingOneNestedWriteAdditionalNestedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL, added(TOP_LEVEL), subtreeModified(TOP_LEVEL));
+    }
 
-        assertContains(change.getCreatedData(), path(FOO,BAZ));
-        assertNotContains(change.getCreatedData(), path(FOO,BAR));
-        assertContains(change.getUpdatedData(), TOP_LEVEL, path(FOO));
-        assertEmpty(change.getRemovedPaths());
+    @Override
+    protected void existingOneNestedWriteAdditionalNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    protected void existingTopWriteTwoNested(final DatastoreTestTask task) throws Exception {
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
+    protected void existingTopWriteTwoNestedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL, added(TOP_LEVEL), subtreeModified(TOP_LEVEL));
+    }
 
-        assertContains(change.getCreatedData(), path(FOO,BAR),path(FOO,BAZ));
-        assertContains(change.getUpdatedData(), TOP_LEVEL, path(FOO));
-        assertNotContains(change.getUpdatedData(), path(FOO,BAR));
-        assertEmpty(change.getRemovedPaths());
+    @Override
+    protected void existingTopWriteTwoNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    protected void existingTopWriteSibling(final DatastoreTestTask task) throws Exception {
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
+    protected void existingTopWriteSiblingSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL, added(TOP_LEVEL), subtreeModified(TOP_LEVEL));
+    }
 
-        assertContains(change.getCreatedData(), path(FOO_SIBLING));
-        assertContains(change.getUpdatedData(), TOP_LEVEL);
-        assertNotContains(change.getUpdatedData(), path(FOO));
-        assertEmpty(change.getRemovedPaths());
+    @Override
+    protected void existingTopWriteSiblingVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 }
index b9ce0ac..23c35f3 100644 (file)
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
+import static org.opendaylight.controller.md.sal.dom.store.impl.DatastoreTestTask.added;
+import static org.opendaylight.controller.md.sal.dom.store.impl.DatastoreTestTask.deleted;
+import static org.opendaylight.controller.md.sal.dom.store.impl.DatastoreTestTask.replaced;
 
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
-public class WildcardedScopeBaseTest extends DefaultDataChangeListenerTestSuite {
+public class WildcardedScopeBaseTest extends DefaultDataTreeChangeListenerTestSuite {
 
     private static final YangInstanceIdentifier TOP_LEVEL_LIST_ALL = TOP_LEVEL.node(TopLevelList.QNAME).node(
             TopLevelList.QNAME);
 
     @Override
-    protected void customizeTask(final DatastoreTestTask task) {
-        task.changeListener(TOP_LEVEL_LIST_ALL, DataChangeScope.BASE);
+    protected void putTopLevelOneNestedSetup(final DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL_LIST_ALL, added(path(FOO)));
     }
 
     @Override
-    public void putTopLevelOneNested(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertNotNull(change);
-
-        /*
-         * Created data must not contain nested-list item, since that is two-level deep.
-         */
-        assertNotContains(change.getCreatedData(), TOP_LEVEL,path(FOO, BAR));
-        assertContains(change.getCreatedData(), path(FOO));
-
-        assertEmpty(change.getUpdatedData());
-        assertEmpty(change.getRemovedPaths());
-
+    protected void putTopLevelOneNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    public void replaceTopLevelNestedChanged(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-        assertNotNull(change);
-        /*
-         * Created data must NOT contain nested-list item since scope is base, and change is two
-         * level deep.
-         */
-        assertNotContains(change.getCreatedData(), path(FOO, BAZ));
-        assertContains(change.getUpdatedData(), path(FOO));
-        assertNotContains(change.getUpdatedData(), TOP_LEVEL);
-        /*
-         * Removed data must NOT contain nested-list item since scope is base, and change is two
-         * level deep.
-         */
-        assertNotContains(change.getRemovedPaths(), path(FOO, BAR));
-
+    protected void replaceTopLevelNestedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL_LIST_ALL, added(path(FOO)), replaced(path(FOO)));
     }
 
     @Override
-    protected void putTopLevelWithTwoNested(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-        assertNotNull(change);
-        assertFalse(change.getCreatedData().isEmpty());
+    protected void replaceTopLevelNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
+    }
 
-        // Base event should contain only changed item, no details about child.
-        assertContains(change.getCreatedData(), path(FOO));
-        assertNotContains(change.getCreatedData(), TOP_LEVEL,path(FOO, BAR), path(FOO, BAZ));
-        assertEmpty(change.getUpdatedData());
-        assertEmpty(change.getRemovedPaths());
+    @Override
+    protected void putTopLevelWithTwoNestedSetup(final DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL_LIST_ALL, added(path(FOO)));
+    }
 
+    @Override
+    protected void putTopLevelWithTwoNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    protected void twoNestedExistsOneIsDeleted(final DatastoreTestTask task) throws Exception {
+    protected void twoNestedExistsOneIsDeletedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL_LIST_ALL, added(path(FOO)));
+    }
 
-        /*
-         * Base listener should be notified only and only if actual node changed its state,
-         * since deletion of child, did not result in change of node we are listening
-         * for, we should not be getting data change event
-         * and this means settable future containing receivedDataChangeEvent is not done.
-         *
-         */
-        task.verifyNoChangeEvent();
+    @Override
+    protected void twoNestedExistsOneIsDeletedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    public void nestedListExistsRootDeleted(final DatastoreTestTask task) throws Exception {
+    protected void nestedListExistsRootDeletedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL_LIST_ALL, added(path(FOO)), deleted(path(FOO)));
+    }
 
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
+    @Override
+    protected void nestedListExistsRootDeletedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
+    }
 
-        assertEmpty(change.getCreatedData());
-        assertEmpty(change.getUpdatedData());
+    @Override
+    protected void existingOneNestedWriteAdditionalNestedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL_LIST_ALL, added(path(FOO)));
+    }
 
-        assertNotContains(change.getUpdatedData(), TOP_LEVEL);
-        /*
-         *  Scope base listener event should contain top-level-list item and nested list path
-         *  and should not contain baz, bar which are two-level deep
-         */
-        assertContains(change.getRemovedPaths(), path(FOO));
-        assertNotContains(change.getRemovedPaths(),path(FOO, BAZ),path(FOO,BAR));
+    @Override
+    protected void existingOneNestedWriteAdditionalNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    protected void existingOneNestedWriteAdditionalNested(final DatastoreTestTask task) throws Exception {
-        /*
-         * One listener should be notified only and only if actual node changed its state,
-         * since deletion of nested child (in this case /nested-list/nested-list[foo],
-         * did not result in change of node we are listening
-         * for, we should not be getting data change event
-         * and this means settable future containing receivedDataChangeEvent is not done.
-         *
-         */
-        task.verifyNoChangeEvent();
+    protected void existingTopWriteTwoNestedSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL_LIST_ALL, added(path(FOO)));
     }
 
     @Override
-    protected void existingTopWriteTwoNested(final DatastoreTestTask task) throws Exception {
-        /*
-         * One listener should be notified only and only if actual node changed its state,
-         * since deletion of nested child (in this case /nested-list/nested-list[foo],
-         * did not result in change of node we are listening
-         * for, we should not be getting data change event
-         * and this means settable future containing receivedDataChangeEvent is not done.
-         *
-         */
-        task.verifyNoChangeEvent();
+    protected void existingTopWriteTwoNestedVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 
     @Override
-    protected void existingTopWriteSibling(final DatastoreTestTask task) throws Exception {
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
+    protected void existingTopWriteSiblingSetup(DatastoreTestTask task) {
+        task.changeListener(TOP_LEVEL_LIST_ALL, added(path(FOO)), added(path(FOO_SIBLING)));
+    }
 
-        assertContains(change.getCreatedData(), path(FOO_SIBLING));
-        assertNotContains(change.getUpdatedData(), path(FOO), TOP_LEVEL);
-        assertEmpty(change.getRemovedPaths());
+    @Override
+    protected void existingTopWriteSiblingVerify(final DatastoreTestTask task) {
+        task.verifyChangeEvents();
     }
 }
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeOneTest.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeOneTest.java
deleted file mode 100644 (file)
index 02797c2..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.sal.dom.store.impl;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedList;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-public class WildcardedScopeOneTest extends DefaultDataChangeListenerTestSuite {
-
-    private static final YangInstanceIdentifier TOP_LEVEL_LIST_ALL = TOP_LEVEL.node(TopLevelList.QNAME).node(
-            TopLevelList.QNAME);
-
-    @Override
-    protected void customizeTask(final DatastoreTestTask task) {
-        task.changeListener(TOP_LEVEL_LIST_ALL, DataChangeScope.ONE);
-    }
-
-    @Override
-    public void putTopLevelOneNested(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertNotNull(change);
-
-        assertNotContains(change.getCreatedData(), TOP_LEVEL,path(FOO, BAR));
-        assertContains(change.getCreatedData(), path(FOO), path(FOO).node(NestedList.QNAME));
-
-        assertEmpty(change.getUpdatedData());
-        assertEmpty(change.getRemovedPaths());
-
-    }
-
-    @Override
-    public void replaceTopLevelNestedChanged(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-        assertNotNull(change);
-        /*
-         * Created data must NOT contain nested-list item since scope is base, and change is two
-         * level deep.
-         */
-        assertNotContains(change.getCreatedData(), path(FOO, BAZ));
-        assertContains(change.getUpdatedData(), path(FOO),path(FOO).node(NestedList.QNAME));
-        assertNotContains(change.getUpdatedData(), TOP_LEVEL);
-        /*
-         * Removed data must NOT contain nested-list item since scope is base, and change is two
-         * level deep.
-         */
-        assertNotContains(change.getRemovedPaths(), path(FOO, BAR));
-
-    }
-
-    @Override
-    protected void putTopLevelWithTwoNested(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-        assertNotNull(change);
-        assertFalse(change.getCreatedData().isEmpty());
-
-        // Base event should contain only changed item, and details about immediate child.
-        assertContains(change.getCreatedData(), path(FOO),path(FOO).node(NestedList.QNAME));
-        assertNotContains(change.getCreatedData(), TOP_LEVEL,path(FOO, BAR), path(FOO, BAZ));
-        assertEmpty(change.getUpdatedData());
-        assertEmpty(change.getRemovedPaths());
-
-    }
-
-    @Override
-    protected void twoNestedExistsOneIsDeleted(final DatastoreTestTask task) throws Exception {
-
-        /*
-         * One listener should be notified only and only if actual node changed its state,
-         * since deletion of nested child (in this case /nested-list/nested-list[foo],
-         * did not result in change of node we are listening
-         * for, we should not be getting data change event
-         * and this means settable future containing receivedDataChangeEvent is not done.
-         *
-         */
-        task.verifyNoChangeEvent();
-    }
-
-    @Override
-    public void nestedListExistsRootDeleted(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertEmpty(change.getCreatedData());
-        assertEmpty(change.getUpdatedData());
-
-        assertNotContains(change.getUpdatedData(), TOP_LEVEL);
-        assertContains(change.getRemovedPaths(), path(FOO),path(FOO).node(NestedList.QNAME));
-        assertNotContains(change.getRemovedPaths(), path(FOO, BAZ),path(FOO,BAR));
-    }
-
-    @Override
-    protected void existingOneNestedWriteAdditionalNested(final DatastoreTestTask task) throws Exception {
-        /*
-         * One listener should be notified only and only if actual node changed its state,
-         * since deletion of nested child (in this case /nested-list/nested-list[foo],
-         * did not result in change of node we are listening
-         * for, we should not be getting data change event
-         * and this means settable future containing receivedDataChangeEvent is not done.
-         *
-         */
-        task.verifyNoChangeEvent();
-    }
-
-    @Override
-    protected void existingTopWriteTwoNested(final DatastoreTestTask task) throws Exception {
-        /*
-         * One listener should be notified only and only if actual node changed its state,
-         * since deletion of nested child (in this case /nested-list/nested-list[foo],
-         * did not result in change of node we are listening
-         * for, we should not be getting data change event
-         * and this means settable future containing receivedDataChangeEvent is not done.
-         *
-         */
-        task.verifyNoChangeEvent();
-    }
-
-    @Override
-    protected void existingTopWriteSibling(final DatastoreTestTask task) throws Exception {
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertContains(change.getCreatedData(), path(FOO_SIBLING));
-        assertNotContains(change.getUpdatedData(),path(FOO), TOP_LEVEL);
-        assertEmpty(change.getRemovedPaths());
-    }
-}
diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeSubtreeTest.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeSubtreeTest.java
deleted file mode 100644 (file)
index 31a9f9c..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.md.sal.dom.store.impl;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-public class WildcardedScopeSubtreeTest extends DefaultDataChangeListenerTestSuite {
-
-    private static final YangInstanceIdentifier TOP_LEVEL_LIST_ALL = TOP_LEVEL.node(TopLevelList.QNAME).node(
-            TopLevelList.QNAME);
-
-    @Override
-    protected void customizeTask(final DatastoreTestTask task) {
-        task.changeListener(TOP_LEVEL_LIST_ALL, DataChangeScope.SUBTREE);
-    }
-
-    @Override
-    public void putTopLevelOneNested(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertNotContains(change.getCreatedData(), TOP_LEVEL);
-        assertContains(change.getCreatedData(), path(FOO), path(FOO, BAR));
-        assertEmpty(change.getUpdatedData());
-        assertEmpty(change.getRemovedPaths());
-
-    }
-
-    @Override
-    public void replaceTopLevelNestedChanged(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-        assertNotNull(change);
-
-        assertContains(change.getCreatedData(), path(FOO, BAZ));
-        assertContains(change.getUpdatedData(), path(FOO));
-        assertNotContains(change.getUpdatedData(), TOP_LEVEL);
-        assertContains(change.getRemovedPaths(), path(FOO, BAR));
-
-    }
-
-    @Override
-    protected void putTopLevelWithTwoNested(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-        assertNotNull(change);
-        assertFalse(change.getCreatedData().isEmpty());
-
-        assertContains(change.getCreatedData(), path(FOO), path(FOO, BAR), path(FOO, BAZ));
-        assertNotContains(change.getCreatedData(), TOP_LEVEL);
-        assertEmpty(change.getUpdatedData());
-        assertEmpty(change.getRemovedPaths());
-
-    }
-
-    @Override
-    protected void twoNestedExistsOneIsDeleted(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-        assertNotNull(change);
-        assertTrue(change.getCreatedData().isEmpty());
-        assertContains(change.getUpdatedData(), path(FOO));
-        assertNotContains(change.getUpdatedData(), TOP_LEVEL);
-        assertContains(change.getRemovedPaths(),path(FOO, BAZ));
-    }
-
-    @Override
-    public void nestedListExistsRootDeleted(final DatastoreTestTask task) throws Exception {
-
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertEmpty(change.getCreatedData());
-        assertEmpty(change.getUpdatedData());
-
-        assertNotContains(change.getUpdatedData(), TOP_LEVEL);
-        assertContains(change.getRemovedPaths(), path(FOO),path(FOO, BAZ),path(FOO,BAR));
-    }
-
-    @Override
-    protected void existingOneNestedWriteAdditionalNested(final DatastoreTestTask task) throws Exception {
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertContains(change.getCreatedData(), path(FOO,BAZ));
-        assertNotContains(change.getCreatedData(), path(FOO,BAR));
-        assertContains(change.getUpdatedData(), path(FOO));
-        assertNotContains(change.getUpdatedData(), TOP_LEVEL);
-        assertEmpty(change.getRemovedPaths());
-    }
-
-    @Override
-    protected void existingTopWriteTwoNested(final DatastoreTestTask task) throws Exception {
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertContains(change.getCreatedData(), path(FOO,BAR),path(FOO,BAZ));
-        assertContains(change.getUpdatedData(), path(FOO));
-        assertNotContains(change.getUpdatedData(), TOP_LEVEL, path(FOO,BAR));
-        assertEmpty(change.getRemovedPaths());
-    }
-
-    @Override
-    protected void existingTopWriteSibling(final DatastoreTestTask task) throws Exception {
-        AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change = task.getChangeEvent();
-
-        assertContains(change.getCreatedData(), path(FOO_SIBLING));
-        assertNotContains(change.getUpdatedData(), path(FOO), TOP_LEVEL);
-        assertEmpty(change.getRemovedPaths());
-    }
-}

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.