Refactor AbstractDataTreeChangeListenerTest 96/106196/2
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 28 May 2023 18:18:51 +0000 (20:18 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Sun, 28 May 2023 18:28:37 +0000 (20:28 +0200)
Rather than exposing the underlying DTCL implementation, expose only the
collector aspect, requiring the collector to be closed -- which also
tears down the listener.

This is a stepping stone to allowing step-by-step assertions, but the
notable change is that we await the initial synchronization before
giving out the collector.

Change-Id: I9337bc5b80eb9976ad9dec143b59ef75d742cbfd
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/Bug1125RegressionTest.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/Bug1333DataChangeListenerTest.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/Bug1418AugmentationTest.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/Bug2562DeserializedUnkeyedListTest.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/Bug3090MultiKeyList.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/ListInsertionDataChangeListenerTest.java
binding/mdsal-binding-dom-adapter/src/test/java/org/opendaylight/mdsal/binding/dom/adapter/test/AbstractDataTreeChangeListenerTest.java

index 490299f36b85e3912990ecb2da12c2c249e41da7..cbe44d5c5377edc0c1fd4df7bbffd62387db73be 100644 (file)
@@ -11,10 +11,8 @@ import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.T
 import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.path;
 import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.topLevelList;
 
-import com.google.common.collect.ImmutableSet;
 import java.util.Set;
 import org.junit.Test;
-import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
@@ -45,7 +43,7 @@ public class Bug1125RegressionTest extends AbstractDataTreeChangeListenerTest {
 
     @Override
     protected Set<YangModuleInfo> getModuleInfos() throws Exception {
-        return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+        return Set.of(BindingReflections.getModuleInfo(Top.class),
                 BindingReflections.getModuleInfo(TreeComplexUsesAugment.class));
     }
 
@@ -59,19 +57,22 @@ public class Bug1125RegressionTest extends AbstractDataTreeChangeListenerTest {
     }
 
     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));
-        WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
-        tx.delete(LogicalDatastoreType.OPERATIONAL, path);
-        assertCommit(tx.commit());
-        listener.verify();
+        final var augment = writeInitialState();
+        try (var collector = createCollector(LogicalDatastoreType.OPERATIONAL, WILDCARDED_AUGMENT_PATH)) {
+            final var tx = getDataBroker().newWriteOnlyTransaction();
+            tx.delete(LogicalDatastoreType.OPERATIONAL, path);
+            assertCommit(tx.commit());
+
+            collector.assertModifications(
+                added(FOO_AUGMENT_PATH, augment),
+                deleted(FOO_AUGMENT_PATH, augment));
+        }
     }
 
     private TreeComplexUsesAugment writeInitialState() {
-        WriteTransaction initialTx = getDataBroker().newWriteOnlyTransaction();
+        var initialTx = getDataBroker().newWriteOnlyTransaction();
         initialTx.put(LogicalDatastoreType.OPERATIONAL, TOP_PATH, new TopBuilder().build());
-        TreeComplexUsesAugment fooAugment = new TreeComplexUsesAugmentBuilder()
+        var fooAugment = new TreeComplexUsesAugmentBuilder()
                 .setContainerWithUses(new ContainerWithUsesBuilder().setLeafFromGrouping("foo").build())
                 .build();
         initialTx.put(LogicalDatastoreType.OPERATIONAL, path(TOP_FOO_KEY), topLevelList(TOP_FOO_KEY, fooAugment));
index 10db76fed34757862dfdbc8bedec854e12f24b83..9328e8cb5bb09acdd37ceb7a208899a964d9b374 100644 (file)
@@ -14,17 +14,14 @@ import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.c
 import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.path;
 import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.top;
 import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.topLevelList;
-import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
 
 import com.google.common.collect.ImmutableSet;
 import java.util.Set;
 import org.junit.Test;
-import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.complex.from.grouping.ListViaUses;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -53,63 +50,62 @@ public class Bug1333DataChangeListenerTest extends AbstractDataTreeChangeListene
     }
 
     public Top writeTopWithListItem(final LogicalDatastoreType store) {
-        ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
-        Top topItem = topWithListItem();
+        var tx = getDataBroker().newWriteOnlyTransaction();
+        var topItem = topWithListItem();
         tx.put(store, TOP_PATH, topItem);
         assertCommit(tx.commit());
         return topItem;
     }
 
     public void deleteItem(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
-        ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+        var tx = getDataBroker().newWriteOnlyTransaction();
         tx.delete(store, path);
         assertCommit(tx.commit());
     }
 
     @Test
     public void writeTopWithListItemAugmentedListenTopSubtree() {
-        TestListener<Top> listener = createListener(CONFIGURATION, TOP_PATH, added(TOP_PATH, topWithListItem()));
+        try (var collector = createCollector(LogicalDatastoreType.CONFIGURATION, TOP_PATH)) {
+            writeTopWithListItem(LogicalDatastoreType.CONFIGURATION);
 
-        writeTopWithListItem(CONFIGURATION);
-
-        listener.verify();
+            collector.assertModifications(added(TOP_PATH, topWithListItem()));
+        }
     }
 
     @Test
     public void writeTopWithListItemAugmentedListenAugmentSubtreeWildcarded() {
-        TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, AUGMENT_WILDCARD,
-                added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)));
-
-        writeTopWithListItem(CONFIGURATION);
+        try (var collector = createCollector(LogicalDatastoreType.CONFIGURATION, AUGMENT_WILDCARD)) {
+            writeTopWithListItem(LogicalDatastoreType.CONFIGURATION);
 
-        listener.verify();
+            collector.assertModifications(
+                added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)));
+        }
     }
 
     @Test
     public void deleteAugmentChildListenTopSubtree() {
-        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)))));
+        final var top = writeTopWithListItem(LogicalDatastoreType.CONFIGURATION);
 
-        InstanceIdentifier<ListViaUses> deletePath = path(TOP_FOO_KEY, USES_ONE_KEY);
-        deleteItem(CONFIGURATION, deletePath);
+        try (var collector = createCollector(LogicalDatastoreType.CONFIGURATION, TOP_PATH)) {
+            deleteItem(LogicalDatastoreType.CONFIGURATION, path(TOP_FOO_KEY, USES_ONE_KEY));
 
-        listener.verify();
+            collector.assertModifications(
+                added(TOP_PATH, top),
+                subtreeModified(TOP_PATH, top, top(topLevelList(TOP_FOO_KEY, complexUsesAugment(USES_TWO_KEY)))));
+        }
     }
 
     @Test
     public void deleteAugmentChildListenAugmentSubtreeWildcarded() {
-        writeTopWithListItem(CONFIGURATION);
+        writeTopWithListItem(LogicalDatastoreType.CONFIGURATION);
+
+        try (var collector = createCollector(LogicalDatastoreType.CONFIGURATION, AUGMENT_WILDCARD)) {
+            deleteItem(LogicalDatastoreType.CONFIGURATION, path(TOP_FOO_KEY, USES_ONE_KEY));
 
-        TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, AUGMENT_WILDCARD,
+            collector.assertModifications(
                 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)));
-
-        InstanceIdentifier<?> deletePath = path(TOP_FOO_KEY, USES_ONE_KEY);
-        deleteItem(CONFIGURATION, deletePath);
-
-        listener.verify();
+        }
     }
 }
index 076ed09b58827c36d306794f8074bd1a25f0fa0b..b413993a7dc621aea0b788e9e923065b0b065930 100644 (file)
@@ -15,10 +15,8 @@ import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.t
 import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.topLevelList;
 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
 
-import com.google.common.collect.ImmutableSet;
 import java.util.Set;
 import org.junit.Test;
-import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment;
@@ -43,106 +41,102 @@ public class Bug1418AugmentationTest extends AbstractDataTreeChangeListenerTest
             new ListViaUsesKey("list key modified");
 
     @Override
-    protected Set<YangModuleInfo> getModuleInfos() throws Exception {
-        return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
-                BindingReflections.getModuleInfo(TreeComplexUsesAugment.class),
-                BindingReflections.getModuleInfo(TreeLeafOnlyUsesAugment.class));
+    protected Set<YangModuleInfo> getModuleInfos() {
+        return Set.of(BindingReflections.getModuleInfo(Top.class),
+                BindingReflections.getModuleInfo(TreeComplexUsesAugment.class));
     }
 
     @Test
     public void leafOnlyAugmentationCreatedTest() {
-        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(CONFIGURATION, TOP, top());
-        writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
-        writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment);
-        assertCommit(writeTx.commit());
-
-        listener.verify();
+        final var leafOnlyUsesAugment = leafOnlyUsesAugment("test leaf");
+        try (var collector = createCollector(CONFIGURATION, SIMPLE_AUGMENT)) {
+            final var writeTx = getDataBroker().newWriteOnlyTransaction();
+            writeTx.put(CONFIGURATION, TOP, top());
+            writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+            writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment);
+            assertCommit(writeTx.commit());
+
+            collector.assertModifications(added(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugment));
+        }
     }
 
     @Test
     public void leafOnlyAugmentationUpdatedTest() {
-        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        var writeTx = getDataBroker().newWriteOnlyTransaction();
         writeTx.put(CONFIGURATION, TOP, top());
         writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
-        TreeLeafOnlyUsesAugment leafOnlyUsesAugmentBefore = leafOnlyUsesAugment("test leaf");
+        final var leafOnlyUsesAugmentBefore = leafOnlyUsesAugment("test leaf");
         writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugmentBefore);
         assertCommit(writeTx.commit());
 
-        TreeLeafOnlyUsesAugment leafOnlyUsesAugmentAfter = leafOnlyUsesAugment("test leaf changed");
-        final TestListener<TreeLeafOnlyUsesAugment> listener = createListener(CONFIGURATION, SIMPLE_AUGMENT,
+        final var leafOnlyUsesAugmentAfter = leafOnlyUsesAugment("test leaf changed");
+        try (var collector = createCollector(CONFIGURATION, SIMPLE_AUGMENT)) {
+            writeTx = getDataBroker().newWriteOnlyTransaction();
+            writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugmentAfter);
+            assertCommit(writeTx.commit());
+
+            collector.assertModifications(
                 added(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugmentBefore),
                 replaced(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugmentBefore,
                     leafOnlyUsesAugmentAfter));
-
-        writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugmentAfter);
-        assertCommit(writeTx.commit());
-
-        listener.verify();
+        }
     }
 
     @Test
     public void leafOnlyAugmentationDeletedTest() {
-        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        var writeTx = getDataBroker().newWriteOnlyTransaction();
         writeTx.put(CONFIGURATION, TOP, top());
         writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
-        TreeLeafOnlyUsesAugment leafOnlyUsesAugment = leafOnlyUsesAugment("test leaf");
+        final var leafOnlyUsesAugment = leafOnlyUsesAugment("test leaf");
         writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment);
         assertCommit(writeTx.commit());
 
-        final TestListener<TreeLeafOnlyUsesAugment> listener = createListener(CONFIGURATION, SIMPLE_AUGMENT,
+        try (var collector = createCollector(CONFIGURATION, SIMPLE_AUGMENT)) {
+            writeTx = getDataBroker().newWriteOnlyTransaction();
+            writeTx.delete(CONFIGURATION, SIMPLE_AUGMENT);
+            assertCommit(writeTx.commit());
+
+            collector.assertModifications(
                 added(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugment),
                 deleted(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugment));
-
-        writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.delete(CONFIGURATION, SIMPLE_AUGMENT);
-        assertCommit(writeTx.commit());
-
-        listener.verify();
+        }
     }
 
     @Test
     public void complexAugmentationCreatedTest() {
-        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(CONFIGURATION, TOP, top());
-        writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
-        writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment);
-        assertCommit(writeTx.commit());
-
-        listener.verify();
+        try (var collector = createCollector(CONFIGURATION, COMPLEX_AUGMENT)) {
+            final var complexUsesAugment = complexUsesAugment(LIST_VIA_USES_KEY);
+            final var writeTx = getDataBroker().newWriteOnlyTransaction();
+            writeTx.put(CONFIGURATION, TOP, top());
+            writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+            writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment);
+            assertCommit(writeTx.commit());
+
+            collector.assertModifications(added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugment));
+        }
     }
 
     @Test
     public void complexAugmentationUpdatedTest() {
-        WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+        var writeTx = getDataBroker().newWriteOnlyTransaction();
         writeTx.put(CONFIGURATION, TOP, top());
         writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
-        TreeComplexUsesAugment complexUsesAugmentBefore = complexUsesAugment(LIST_VIA_USES_KEY);
+        final var complexUsesAugmentBefore = complexUsesAugment(LIST_VIA_USES_KEY);
         writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugmentBefore);
         assertCommit(writeTx.commit());
 
-        TreeComplexUsesAugment complexUsesAugmentAfter = complexUsesAugment(LIST_VIA_USES_KEY_MOD);
+        try (var collector = createCollector(CONFIGURATION, COMPLEX_AUGMENT)) {
+            final var complexUsesAugmentAfter = complexUsesAugment(LIST_VIA_USES_KEY_MOD);
+            writeTx = getDataBroker().newWriteOnlyTransaction();
+            writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugmentAfter);
+            assertCommit(writeTx.commit());
 
-        final TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, COMPLEX_AUGMENT,
+            collector.assertModifications(
                 added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugmentBefore),
                 // While we are overwriting the augment, at the transaction ends up replacing one child with another,
                 // so the Augmentation ends up not being overwritten, but modified
                 subtreeModified(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugmentBefore,
                         complexUsesAugmentAfter));
-
-        writeTx = getDataBroker().newWriteOnlyTransaction();
-        writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugmentAfter);
-        assertCommit(writeTx.commit());
-
-        listener.verify();
+        }
     }
 }
index d3a07ad6ef2fe189dd93a45b2c75d4aabb987217..5ab6c8466eab44c23574558ba7f3692000a37f53 100644 (file)
@@ -7,20 +7,16 @@
  */
 package org.opendaylight.mdsal.binding.dom.adapter;
 
-import com.google.common.collect.ImmutableSet;
-import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.junit.Test;
-import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.mdsal.common.api.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;
-import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.Fooroot;
 import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.FoorootBuilder;
-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.InstanceIdentifier;
@@ -31,22 +27,21 @@ public class Bug2562DeserializedUnkeyedListTest extends AbstractDataTreeChangeLi
 
     @Override
     protected Set<YangModuleInfo> getModuleInfos() throws Exception {
-        return ImmutableSet.of(BindingReflections.getModuleInfo(Root.class));
+        return Set.of(BindingReflections.getModuleInfo(Root.class));
     }
 
     @Test
     public void writeListToList2562Root() {
-        final Barroot barRoot = new BarrootBuilder().setType(2).setValue(2).withKey(new BarrootKey(2)).build();
-        final Fooroot fooRoot = new FoorootBuilder().setBarroot(Map.of(barRoot.key(), barRoot)).build();
-        final Root root = new RootBuilder().setFooroot(Arrays.asList(fooRoot)).build();
+        final var barRoot = new BarrootBuilder().setType(2).setValue(2).withKey(new BarrootKey(2)).build();
+        final var fooRoot = new FoorootBuilder().setBarroot(Map.of(barRoot.key(), barRoot)).build();
+        final var root = new RootBuilder().setFooroot(List.of(fooRoot)).build();
 
-        final TestListener<Root> listenerRoot = createListener(LogicalDatastoreType.CONFIGURATION, ROOT_PATH,
-                added(ROOT_PATH, root));
+        try (var collector = createCollector(LogicalDatastoreType.CONFIGURATION, ROOT_PATH)) {
+            final var readWriteTransaction = getDataBroker().newReadWriteTransaction();
+            readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, root);
+            assertCommit(readWriteTransaction.commit());
 
-        final ReadWriteTransaction readWriteTransaction = getDataBroker().newReadWriteTransaction();
-        readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, root);
-        assertCommit(readWriteTransaction.commit());
-
-        listenerRoot.verify();
+            collector.assertModifications(added(ROOT_PATH, root));
+        }
     }
 }
index ad2fec0df8ae51e63f886cc29fc2eda5e2062c59..c4b533ebef62cafdbf8f8daed39b7aaae417f960 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.mdsal.binding.dom.adapter;
 
-import com.google.common.collect.ImmutableSet;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Objects;
@@ -15,7 +14,6 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import org.junit.Test;
 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
-import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
@@ -32,7 +30,7 @@ public class Bug3090MultiKeyList extends AbstractDataTreeChangeListenerTest {
 
     @Override
     protected Set<YangModuleInfo> getModuleInfos() throws Exception {
-        return ImmutableSet.of(BindingReflections.getModuleInfo(Root.class));
+        return Set.of(BindingReflections.getModuleInfo(Root.class));
     }
 
     @Test
@@ -47,17 +45,16 @@ public class Bug3090MultiKeyList extends AbstractDataTreeChangeListenerTest {
             );
         }
 
-        final Root root = new RootBuilder().setListInRoot(BindingMap.of(listInRoots)).build();
+        final var root = new RootBuilder().setListInRoot(BindingMap.of(listInRoots)).build();
 
-        final TestListener<Root> listener = createListener(LogicalDatastoreType.CONFIGURATION, ROOT_PATH,
-                match(ModificationType.WRITE, ROOT_PATH, Objects::isNull,
-                    (DataMatcher<Root>) dataAfter -> checkData(root, dataAfter)));
+        try (var collector = createCollector(LogicalDatastoreType.CONFIGURATION, ROOT_PATH)) {
+            final var readWriteTransaction = getDataBroker().newReadWriteTransaction();
+            readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, root);
+            assertCommit(readWriteTransaction.commit());
 
-        final ReadWriteTransaction readWriteTransaction = getDataBroker().newReadWriteTransaction();
-        readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, root);
-        assertCommit(readWriteTransaction.commit());
-
-        listener.verify();
+            collector.assertModifications(match(ModificationType.WRITE, ROOT_PATH, Objects::isNull,
+                (DataMatcher<Root>) dataAfter -> checkData(root, dataAfter)));
+        }
     }
 
     private static boolean checkData(final Root expected, final Root actual) {
@@ -65,8 +62,8 @@ public class Bug3090MultiKeyList extends AbstractDataTreeChangeListenerTest {
             return false;
         }
 
-        Set<ListInRoot> expListInRoot = new HashSet<>(expected.getListInRoot().values());
-        Set<ListInRoot> actualListInRoot = actual.getListInRoot().values().stream()
+        var expListInRoot = new HashSet<>(expected.nonnullListInRoot().values());
+        var actualListInRoot = actual.nonnullListInRoot().values().stream()
                 .map(list -> new ListInRootBuilder(list).build()).collect(Collectors.toSet());
         return expListInRoot.equals(actualListInRoot);
     }
index e761ba6f3ce6400c50c6b28ec2d40e68037b9d45..fb61d7a4cd0c97bd83cc96033bf8a153c6382610 100644 (file)
@@ -21,7 +21,6 @@ import java.util.stream.Collectors;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
-import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
@@ -60,109 +59,110 @@ public class ListInsertionDataChangeListenerTest extends AbstractDataTreeChangeL
         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);
-        assertCommit(writeTx.commit());
-
-        topListener.verify();
-        allListener.verify();
-        fooListener.verify();
-        barListener.verify();
+        try (var topListener = createCollector(CONFIGURATION, TOP)) {
+            // Listener for all list items. This one should see Foo item deleted and Bar item added.
+            try (var allListener = createCollector(CONFIGURATION, WILDCARDED)) {
+                // Listener for all Foo item. This one should see only Foo item deleted.
+                try (var fooListener = createCollector(CONFIGURATION, TOP_FOO)) {
+                    // Listener for bar list items.
+                    try (var barListener = createCollector(CONFIGURATION, TOP_BAR)) {
+                        final var writeTx = getDataBroker().newWriteOnlyTransaction();
+                        writeTx.put(CONFIGURATION, TOP, top);
+                        assertCommit(writeTx.commit());
+
+                        barListener.assertModifications(added(TOP_BAR, topBar));
+                    }
+                    fooListener.assertModifications(added(TOP_FOO, topFoo), deleted(TOP_FOO, topFoo));
+                }
+                allListener.assertModifications(
+                    added(TOP_FOO, topFoo),
+                    added(TOP_BAR, topBar),
+                    deleted(TOP_FOO, topFoo));
+            }
+            topListener.assertModifications(
+                added(TOP, top(topLevelList(TOP_FOO_KEY))),
+                replaced(TOP, top(topFoo), top));
+        }
     }
 
     @Test
     public void mergeTopNodeSubtreeListeners() {
-        final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
-        final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
-
-        final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+        final var topBar = topLevelList(TOP_BAR_KEY);
+        final var topFoo = topLevelList(TOP_FOO_KEY);
+
+        try (var topListener = createCollector(CONFIGURATION, TOP)) {
+            try (var allListener = createCollector(CONFIGURATION, WILDCARDED)) {
+                try (var fooListener = createCollector(CONFIGURATION, TOP_FOO)) {
+                    try (var barListener = createCollector(CONFIGURATION, TOP_BAR)) {
+                        final var writeTx = getDataBroker().newWriteOnlyTransaction();
+                        writeTx.merge(CONFIGURATION, TOP, top(topLevelList(TOP_BAR_KEY)));
+                        assertCommit(writeTx.commit());
+
+                        barListener.assertModifications(added(TOP_BAR, topBar));
+                    }
+                    fooListener.assertModifications(added(TOP_FOO, topFoo));
+                }
+                allListener.assertModifications(added(TOP_FOO, topFoo), added(TOP_BAR, topBar));
+            }
+            topListener.assertModifications(
                 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.commit());
-
-        topListener.verify();
-        allListener.verify();
-        fooListener.verify();
-        barListener.verify();
+        }
     }
 
     @Test
     public void putTopBarNodeSubtreeListeners() {
-        final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
-        final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
-
-        final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+        final var topBar = topLevelList(TOP_BAR_KEY);
+        final var topFoo = topLevelList(TOP_FOO_KEY);
+
+        try (var topListener = createCollector(CONFIGURATION, TOP)) {
+            try (var allListener = createCollector(CONFIGURATION, WILDCARDED)) {
+                try (var fooListener = createCollector(CONFIGURATION, TOP_FOO)) {
+                    try (var barListener = createCollector(CONFIGURATION, TOP_BAR)) {
+                        var writeTx = getDataBroker().newWriteOnlyTransaction();
+                        writeTx.put(CONFIGURATION, TOP_BAR, topLevelList(TOP_BAR_KEY));
+                        assertCommit(writeTx.commit());
+
+                        barListener.assertModifications(added(TOP_BAR, topBar));
+                    }
+                    fooListener.assertModifications(added(TOP_FOO, topFoo));
+                }
+                allListener.assertModifications(added(TOP_FOO, topFoo), added(TOP_BAR, topBar));
+            }
+            topListener.assertModifications(
                 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.commit());
-
-        topListener.verify();
-        allListener.verify();
-        fooListener.verify();
-        barListener.verify();
+        }
     }
 
     @Test
     public void mergeTopBarNodeSubtreeListeners() {
-        final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
-        final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
-
-        final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+        final var topBar = topLevelList(TOP_BAR_KEY);
+        final var topFoo = topLevelList(TOP_FOO_KEY);
+
+        try (var topListener = createCollector(CONFIGURATION, TOP)) {
+            try (var allListener = createCollector(CONFIGURATION, WILDCARDED)) {
+                try (var fooListener = createCollector(CONFIGURATION, TOP_FOO)) {
+                    try (var barListener = createCollector(CONFIGURATION, TOP_BAR)) {
+                        final var writeTx = getDataBroker().newWriteOnlyTransaction();
+                        writeTx.merge(CONFIGURATION, TOP_BAR, topLevelList(TOP_BAR_KEY));
+                        assertCommit(writeTx.commit());
+
+                        barListener.assertModifications(added(TOP_BAR, topBar));
+                    }
+                    fooListener.assertModifications(added(TOP_FOO, topFoo));
+                }
+                allListener.assertModifications(added(TOP_FOO, topFoo), added(TOP_BAR, topBar));
+            }
+            topListener.assertModifications(
                 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.commit());
-
-        topListener.verify();
-        allListener.verify();
-        fooListener.verify();
-        barListener.verify();
+        }
     }
 
     private static Matcher<Top> topSubtreeModified(final TopLevelList topFoo, final TopLevelList topBar) {
         return match(ModificationType.SUBTREE_MODIFIED, TOP,
             (DataMatcher<Top>) dataBefore -> Objects.equals(top(topFoo), dataBefore),
             dataAfter -> {
-                Set<TopLevelList> expList = new HashSet<>(top(topBar, topFoo).getTopLevelList().values());
-                Set<TopLevelList> actualList = dataAfter.getTopLevelList().values().stream()
+                var expList = new HashSet<>(top(topBar, topFoo).nonnullTopLevelList().values());
+                var actualList = dataAfter.nonnullTopLevelList().values().stream()
                         .map(list -> new TopLevelListBuilder(list).build()).collect(Collectors.toSet());
                 return expList.equals(actualList);
             });
index b11d595450cb78aeb1475d088bd27022565aadd7..249b765838c12d73ebaf2e06796536d717022c69 100644 (file)
@@ -7,25 +7,25 @@
  */
 package org.opendaylight.mdsal.binding.dom.adapter.test;
 
+import static java.util.Objects.requireNonNull;
 import static org.junit.Assert.fail;
 
-import com.google.common.util.concurrent.SettableFuture;
+import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.Uninterruptibles;
 import java.util.ArrayDeque;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Deque;
 import java.util.List;
 import java.util.Objects;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
 import org.opendaylight.mdsal.binding.api.DataTreeModification;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
@@ -47,41 +47,20 @@ public class AbstractDataTreeChangeListenerTest extends AbstractConcurrentDataBr
         boolean apply(T data);
     }
 
-    protected static final class TestListener<T extends DataObject> implements DataTreeChangeListener<T> {
-        private final SettableFuture<List<DataTreeModification<T>>> future = SettableFuture.create();
-        private final List<DataTreeModification<T>> accumulatedChanges = new ArrayList<>();
-        private final Deque<Matcher<T>> matchers;
-        private final int expChangeCount;
+    protected static final class ModificationCollector<T extends DataObject> implements AutoCloseable {
+        private final TestListener<T> listener;
+        private final Registration reg;
 
-        private TestListener(final List<Matcher<T>> matchers) {
-            this.matchers = new ArrayDeque<>(matchers);
-            expChangeCount = this.matchers.size();
+        private ModificationCollector(final TestListener<T> listener, final Registration reg) {
+            this.listener = requireNonNull(listener);
+            this.reg = requireNonNull(reg);
         }
 
-        @Override
-        public void onDataTreeChanged(final Collection<DataTreeModification<T>> changes) {
-            synchronized (accumulatedChanges) {
-                accumulatedChanges.addAll(changes);
-                if (expChangeCount == accumulatedChanges.size()) {
-                    future.set(List.copyOf(accumulatedChanges));
-                }
-            }
-        }
+        @SafeVarargs
+        public final void assertModifications(final Matcher<T>... inOrder) {
+            final var matchers = new ArrayDeque<>(Arrays.asList(inOrder));
+            final var changes = new ArrayDeque<>(listener.awaitChanges(matchers.size()));
 
-        public List<DataTreeModification<T>> changes() {
-            try {
-                final var 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() {
-            final var changes = new ArrayDeque<>(changes());
             while (!changes.isEmpty()) {
                 final var mod = changes.pop();
                 final var matcher = matchers.peek();
@@ -101,9 +80,60 @@ public class AbstractDataTreeChangeListenerTest extends AbstractConcurrentDataBr
             }
         }
 
-        public boolean hasChanges() {
-            synchronized (accumulatedChanges) {
-                return !accumulatedChanges.isEmpty();
+        @Override
+        public void close() {
+            reg.close();
+        }
+    }
+
+    private static final class TestListener<T extends DataObject> implements DataTreeChangeListener<T> {
+        private final Deque<DataTreeModification<T>> accumulatedChanges = new ArrayDeque<>();
+
+        private boolean synced;
+
+        @Override
+        public synchronized void onDataTreeChanged(final Collection<DataTreeModification<T>> changes) {
+            accumulatedChanges.addAll(changes);
+            synced = true;
+        }
+
+        @Override
+        public synchronized void onInitialData() {
+            synced = true;
+        }
+
+        private void awaitSync() {
+            final var sw = Stopwatch.createStarted();
+
+            do {
+                synchronized (this) {
+                    if (synced) {
+                        return;
+                    }
+                }
+
+                Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
+            } while (sw.elapsed(TimeUnit.SECONDS) < 5);
+
+            throw new AssertionError("Failed to achieve initial sync");
+        }
+
+        private List<DataTreeModification<T>> awaitChanges(final int expectedCount) {
+            final var sw = Stopwatch.createStarted();
+
+            do {
+                synchronized (this) {
+                    if (accumulatedChanges.size() >= expectedCount) {
+                        return List.copyOf(accumulatedChanges);
+                    }
+                }
+
+                Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
+            } while (sw.elapsed(TimeUnit.SECONDS) < 5);
+
+            synchronized (this) {
+                throw new AssertionError("Expected %s changes, received only %s".formatted(expectedCount,
+                    accumulatedChanges.size()));
             }
         }
     }
@@ -112,42 +142,45 @@ public class AbstractDataTreeChangeListenerTest extends AbstractConcurrentDataBr
         super(true);
     }
 
-    @SafeVarargs
-    protected final <T extends DataObject> TestListener<T> createListener(final LogicalDatastoreType store,
-            final InstanceIdentifier<T> path, final Matcher<T>... matchers) {
-        final var listener = new TestListener<>(Arrays.asList(matchers));
-        getDataBroker().registerDataTreeChangeListener(DataTreeIdentifier.create(store, path), listener);
-        return listener;
+    protected final <T extends DataObject> @NonNull ModificationCollector<T> createCollector(
+            final LogicalDatastoreType store, final InstanceIdentifier<T> path) {
+        final var listener = new TestListener<T>();
+        final var reg = getDataBroker().registerDataTreeChangeListener(DataTreeIdentifier.create(store, path),
+            listener);
+        listener.awaitSync();
+        return new ModificationCollector<>(listener, reg);
     }
 
-    public static <T extends DataObject> Matcher<T> match(final ModificationType type, final InstanceIdentifier<T> path,
-            final DataMatcher<T> checkDataBefore, final DataMatcher<T> checkDataAfter) {
+    public static <T extends DataObject> @NonNull Matcher<T> match(final ModificationType type,
+            final InstanceIdentifier<T> path, final DataMatcher<T> checkDataBefore,
+            final DataMatcher<T> 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> Matcher<T> match(final ModificationType type, final InstanceIdentifier<T> path,
-            final T expDataBefore, final T expDataAfter) {
+    public static <T extends DataObject> @NonNull Matcher<T> match(final ModificationType type,
+            final InstanceIdentifier<T> path, final T expDataBefore, final T expDataAfter) {
         return match(type, path, dataBefore -> Objects.equals(expDataBefore, dataBefore),
             (DataMatcher<T>) dataAfter -> Objects.equals(expDataAfter, dataAfter));
     }
 
-    public static <T extends DataObject> Matcher<T> added(final InstanceIdentifier<T> path, final T data) {
+    public static <T extends DataObject> @NonNull Matcher<T> added(final InstanceIdentifier<T> path, final T data) {
         return match(ModificationType.WRITE, path, null, data);
     }
 
-    public static <T extends DataObject> Matcher<T> replaced(final InstanceIdentifier<T> path, final T dataBefore,
-            final T dataAfter) {
+    public static <T extends DataObject> @NonNull Matcher<T> replaced(final InstanceIdentifier<T> path,
+            final T dataBefore, final T dataAfter) {
         return match(ModificationType.WRITE, path, dataBefore, dataAfter);
     }
 
-    public static <T extends DataObject> Matcher<T> deleted(final InstanceIdentifier<T> path, final T dataBefore) {
+    public static <T extends DataObject> @NonNull Matcher<T> deleted(final InstanceIdentifier<T> path,
+            final T dataBefore) {
         return match(ModificationType.DELETE, path, dataBefore, null);
     }
 
-    public static <T extends DataObject> Matcher<T> subtreeModified(final InstanceIdentifier<T> path,
+    public static <T extends DataObject> @NonNull Matcher<T> subtreeModified(final InstanceIdentifier<T> path,
             final T dataBefore, final T dataAfter) {
         return match(ModificationType.SUBTREE_MODIFIED, path, dataBefore, dataAfter);
     }