From: Tom Pantelis Date: Fri, 4 May 2018 04:55:37 +0000 (-0400) Subject: Convert DCL tests to use DTCL X-Git-Tag: release/fluorine~99 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=8e4580f8989c7a40861be1c025822ebba4f1cb07 Convert DCL tests to use DTCL Change-Id: I05bd3a9b42e1ab3d9a1e682aaacb585aee313e7a Signed-off-by: Tom Pantelis --- diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingDOMDataBrokerAdapterTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingDOMDataBrokerAdapterTest.java index 3506f4ba19..b01340a789 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingDOMDataBrokerAdapterTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingDOMDataBrokerAdapterTest.java @@ -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 listenerRegistration; + + @Mock + ClusteredDataTreeChangeListener clusteredDataTreeChangeListener; - private static final InstanceIdentifier TOP_PATH = InstanceIdentifier - .create(Top.class); + private static final InstanceIdentifier 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 clusteredDOMListener = ArgumentCaptor - .forClass(ClusteredDOMDataChangeListener.class); - final ArgumentCaptor logicalDatastoreType = ArgumentCaptor - .forClass(LogicalDatastoreType.class); - final ArgumentCaptor dataChangeScope = ArgumentCaptor - .forClass(AsyncDataBroker.DataChangeScope.class); - final ArgumentCaptor 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> 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, DataObject> change) { + bindingListenerReg.close(); + verify(listenerRegistration).close(); } } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1125RegressionTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1125RegressionTest.java index 41c3375b2f..fff82db00b 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1125RegressionTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1125RegressionTest.java @@ -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_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 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, 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 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); } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java index 177aa6b282..93331c763f 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1333DataChangeListenerTest.java @@ -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; *

* 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_PATH = InstanceIdentifier.create(Top.class); - private static final InstanceIdentifier AUGMENT_WILDCARD = TOP_PATH.child(TopLevelList.class).augmentation( - TreeComplexUsesAugment.class); + private static final InstanceIdentifier AUGMENT_WILDCARD = + TOP_PATH.child(TopLevelList.class).augmentation(TreeComplexUsesAugment.class); - public void writeTopWithListItem(final LogicalDatastoreType store) { + @Override + protected Iterable 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 listener = createListener(CONFIGURATION, TOP_PATH, added(TOP_PATH, topWithListItem())); writeTopWithListItem(CONFIGURATION); - AsyncDataChangeEvent, 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, DataObject> event = listener.event(); + TestListener 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, DataObject> event = listener.event(); + Top top = writeTopWithListItem(CONFIGURATION); + TestListener 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 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, DataObject> event = listener.event(); - - assertEmpty(event.getCreatedData()); - - assertContains(event.getUpdatedData(), path(TOP_FOO_KEY, TreeComplexUsesAugment.class)); + TestListener 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(); } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java index ca6c78f0cf..728e292afe 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug1418AugmentationTest.java @@ -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 = InstanceIdentifier.create(Top.class); private static final InstanceIdentifier TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY); private static final InstanceIdentifier 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 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 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, 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 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, 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 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, 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 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, 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 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, 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(); } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug2562DeserializedUnkeyedListTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug2562DeserializedUnkeyedListTest.java index 57d390b176..6d6b16e129 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug2562DeserializedUnkeyedListTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug2562DeserializedUnkeyedListTest.java @@ -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_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 barRootList = new ArrayList<>(); - barRootList.add(barRoot); - final Fooroot fooRoot = new FoorootBuilder().setBarroot(barRootList).build(); - final ArrayList 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 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, 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 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(); } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug3090MultiKeyList.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug3090MultiKeyList.java index 3b883b418f..92f00b5f79 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug3090MultiKeyList.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug3090MultiKeyList.java @@ -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_PATH = InstanceIdentifier.create(Root.class); - private void write(final LogicalDatastoreType store) { - final ReadWriteTransaction readWriteTransaction = getDataBroker().newReadWriteTransaction(); + @Override + protected Iterable getModuleInfos() throws Exception { + return ImmutableSet.of(BindingReflections.getModuleInfo(Root.class)); + } + @Test + public void listWithMultiKeyTest() { final List 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 listener = createListener(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, + match(ModificationType.WRITE, ROOT_PATH, dataBefore -> dataBefore == null, + (Function) 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, 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 expListInRoot = new HashSet<>(expected.getListInRoot()); + Set actualListInRoot = actual.getListInRoot().stream() + .map(list -> new ListInRootBuilder(list).build()).collect(Collectors.toSet()); + return expListInRoot.equals(actualListInRoot); } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug4513Test.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug4513Test.java index 82da42786d..4a84c319f7 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug4513Test.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/Bug4513Test.java @@ -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 wildCard = InstanceIdentifier.builder(ListenerTest.class) - .child(ListItem.class).build(); - ListenerRegistration reg = getDataBroker().registerDataChangeListener( - LogicalDatastoreType.OPERATIONAL, wildCard, listener, AsyncDataBroker.DataChangeScope.SUBTREE); - - final ListItem item = writeListItem(); - - ArgumentCaptor 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 diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ListInsertionDataChangeListenerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ListInsertionDataChangeListenerTest.java index b2451391bc..36240fe2b2 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ListInsertionDataChangeListenerTest.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ListInsertionDataChangeListenerTest.java @@ -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 = InstanceIdentifier.create(Top.class); private static final InstanceIdentifier WILDCARDED = TOP.child(TopLevelList.class); private static final InstanceIdentifier TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY); private static final InstanceIdentifier TOP_BAR = TOP.child(TopLevelList.class, TOP_BAR_KEY); + @Override + protected Iterable 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 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 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 fooListener = createListener(CONFIGURATION, TOP_FOO, + added(TOP_FOO, topFoo), deleted(TOP_FOO, topFoo)); + + // Listener for bar list items. + final TestListener 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, DataObject> top = topListener.event(); - final AsyncDataChangeEvent, DataObject> all = allListener.event(); - final AsyncDataChangeEvent, DataObject> foo = fooListener.event(); - final AsyncDataChangeEvent, 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 topListener = createListener(CONFIGURATION, TOP, + added(TOP, top(topLevelList(TOP_FOO_KEY))), topSubtreeModified(topFoo, topBar)); + final TestListener allListener = createListener(CONFIGURATION, WILDCARDED, + added(TOP_FOO, topFoo), added(TOP_BAR, topBar)); + final TestListener fooListener = createListener(CONFIGURATION, TOP_FOO, + added(TOP_FOO, topFoo)); + final TestListener 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 topListener = createListener(CONFIGURATION, TOP, + added(TOP, top(topLevelList(TOP_FOO_KEY))), topSubtreeModified(topFoo, topBar)); + final TestListener allListener = createListener(CONFIGURATION, WILDCARDED, + added(TOP_FOO, topFoo), added(TOP_BAR, topBar)); + final TestListener fooListener = createListener(CONFIGURATION, TOP_FOO, + added(TOP_FOO, topFoo)); + final TestListener 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 topListener = createListener(CONFIGURATION, TOP, + added(TOP, top(topLevelList(TOP_FOO_KEY))), topSubtreeModified(topFoo, topBar)); + final TestListener allListener = createListener(CONFIGURATION, WILDCARDED, + added(TOP_FOO, topFoo), added(TOP_BAR, topBar)); + final TestListener fooListener = createListener(CONFIGURATION, TOP_FOO, + added(TOP_FOO, topFoo)); + final TestListener 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, Boolean> topSubtreeModified(TopLevelList topFoo, TopLevelList topBar) { + return match(ModificationType.SUBTREE_MODIFIED, TOP, + (Function) dataBefore -> Objects.equals(top(topFoo), dataBefore), + dataAfter -> { + Set expList = new HashSet<>(top(topBar, topFoo).getTopLevelList()); + Set 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 index 2a5c0e8332..0000000000 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractDataChangeListenerTest.java +++ /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, 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, DataObject> arg) { - if (capture) { - event.set(arg); - } else { - initialEventLatch.countDown(); - } - } - - public AsyncDataChangeEvent, 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 index 0000000000..f2b5f936cc --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/AbstractDataTreeChangeListenerTest.java @@ -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 implements DataTreeChangeListener { + + private final List> accumulatedChanges = new ArrayList<>(); + private final SettableFuture>> future = SettableFuture.create(); + private final Function, Boolean>[] matchers; + private final int expChangeCount; + + private TestListener(Function, Boolean>[] matchers) { + this.expChangeCount = matchers.length; + this.matchers = matchers; + } + + @Override + public void onDataTreeChanged(Collection> changes) { + synchronized (accumulatedChanges) { + accumulatedChanges.addAll(changes); + if (expChangeCount == accumulatedChanges.size()) { + future.set(new ArrayList<>(accumulatedChanges)); + } + } + } + + public Collection> changes() { + try { + final Collection> 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> changes = new ArrayList<>(changes()); + Iterator> iter = changes.iterator(); + while (iter.hasNext()) { + DataTreeModification dataTreeModification = iter.next(); + for (Function, Boolean> matcher: matchers) { + if (matcher.apply(dataTreeModification)) { + iter.remove(); + break; + } + } + } + + if (!changes.isEmpty()) { + DataTreeModification 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 TestListener createListener(final LogicalDatastoreType store, + final InstanceIdentifier path, Function, Boolean>... matchers) { + TestListener listener = new TestListener<>(matchers); + getDataBroker().registerDataTreeChangeListener(new DataTreeIdentifier<>(store, path), listener); + return listener; + } + + public static Function, Boolean> match( + ModificationType type, InstanceIdentifier path, Function checkDataBefore, + Function checkDataAfter) { + return modification -> type == modification.getRootNode().getModificationType() + && path.equals(modification.getRootPath().getRootIdentifier()) + && checkDataBefore.apply(modification.getRootNode().getDataBefore()) + && checkDataAfter.apply(modification.getRootNode().getDataAfter()); + } + + public static Function, Boolean> match( + ModificationType type, InstanceIdentifier path, T expDataBefore, T expDataAfter) { + return match(type, path, dataBefore -> Objects.equals(expDataBefore, dataBefore), + (Function) dataAfter -> Objects.equals(expDataAfter, dataAfter)); + } + + public static Function, Boolean> added( + InstanceIdentifier path, T data) { + return match(ModificationType.WRITE, path, null, data); + } + + public static Function, Boolean> replaced( + InstanceIdentifier path, T dataBefore, T dataAfter) { + return match(ModificationType.WRITE, path, dataBefore, dataAfter); + } + + public static Function, Boolean> deleted( + InstanceIdentifier path, T dataBefore) { + return match(ModificationType.DELETE, path, dataBefore, null); + } + + public static Function, Boolean> subtreeModified( + InstanceIdentifier path, T dataBefore, T dataAfter) { + return match(ModificationType.SUBTREE_MODIFIED, path, dataBefore, dataAfter); + } +} diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java index e9f0b203a7..48872a865c 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java @@ -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 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, DataObject>> eventFuture = - SettableFuture.create(); - dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, DEEP_WILDCARDED_PATH, - dataChangeEvent -> eventFuture.set(dataChangeEvent), DataChangeScope.SUBTREE); + final TestListener 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, 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, DataObject>> eventFuture = - SettableFuture.create(); - dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, DEEP_WILDCARDED_PATH, - dataChangeEvent -> eventFuture.set(dataChangeEvent), DataChangeScope.SUBTREE); + final TestListener 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, DataObject>> eventFuture = - SettableFuture.create(); - dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, DEEP_WILDCARDED_PATH, - dataChangeEvent -> eventFuture.set(dataChangeEvent), DataChangeScope.SUBTREE); - assertFalse(eventFuture.isDone()); + final TestListener 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, 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, 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)); - } - } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java index 213f62e8b3..be22d83586 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java @@ -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 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, 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 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, 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(); } - } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java index aba648cdac..4a76ad97fd 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java @@ -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 AUGMENT_TLL_PATH = InstanceIdentifier .builder(Top.class).child(TopLevelList.class, TLL_KEY).augmentation(TreeComplexUsesAugment.class).build(); + @Override + protected Iterable getModuleInfos() throws Exception { + return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class), + BindingReflections.getModuleInfo(TreeComplexUsesAugment.class)); + } + @Test public void writeNodeListenAugment() throws Exception { - final SettableFuture, DataObject>> event = SettableFuture.create(); - DataBroker dataBroker = testContext.getDataBroker(); - ListenerRegistration dclRegistration = - dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, AUGMENT_WILDCARDED_PATH, - change -> event.set(change), DataChangeScope.SUBTREE); + DataBroker dataBroker = getDataBroker(); + + final TreeComplexUsesAugment treeComplexUsesAugment = treeComplexUsesAugment("one"); + + final TestListener 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, 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()); } diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java index eafa2dc62d..852c4e4886 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java @@ -159,8 +159,7 @@ public interface AsyncWriteTransaction

, D> extends AsyncTransa * ({@link AsyncConfigurationCommitHandler}) if the transaction changes the data tree. * *

- * 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. * *

Example usage:

diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/compat/LegacyDOMDataBrokerAdapterTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/compat/LegacyDOMDataBrokerAdapterTest.java index 738a87c686..dfc0ae1c92 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/compat/LegacyDOMDataBrokerAdapterTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/databroker/compat/LegacyDOMDataBrokerAdapterTest.java @@ -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 mockReg = mock(ListenerRegistration.class); - doReturn(mockReg).when(mockConfigStore).registerChangeListener( - TestModel.TEST_PATH, listener, DataChangeScope.ONE); - - ListenerRegistration reg = adapter.registerDataChangeListener( - LogicalDatastoreType.CONFIGURATION, TestModel.TEST_PATH, listener, DataChangeScope.ONE); - assertEquals("ListenerRegistration", mockReg, reg); - - verify(mockConfigStore).registerChangeListener(TestModel.TEST_PATH, listener, DataChangeScope.ONE); - } - @Test @Deprecated public void testSubmit() throws Exception { diff --git a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMBrokerTest.java b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMBrokerTest.java index 519c364050..b2fb3c2c3e 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMBrokerTest.java +++ b/opendaylight/md-sal/sal-dom-broker/src/test/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMBrokerTest.java @@ -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 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 caughtCommitEx = new AtomicReference<>(); - final CountDownLatch commitCompletedLatch = new CountDownLatch(1); - - TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() { - @Override - public void onDataChanged(final AsyncDataChangeEvent> change) { - - DOMDataWriteTransaction writeTx = domBroker.newWriteOnlyTransaction(); - writeTx.put(OPERATIONAL, TestModel.TEST2_PATH, ImmutableNodes.containerNode(TestModel.TEST2_QNAME)); - Futures.addCallback(writeTx.submit(), new FutureCallback() { - @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 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 caughtCommitEx = new AtomicReference<>(); - - TestDOMDataChangeListener dcListener = new TestDOMDataChangeListener() { - @Override - public void onDataChanged(final AsyncDataChangeEvent> 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 caughtEx = submitTxAsync(writeTx); - - dcListener.waitForChange(); - - if (caughtEx.get() != null) { - throw caughtEx.get(); - } - - if (caughtCommitEx.get() != null) { - throw caughtCommitEx.get(); - } - } - @SuppressWarnings("checkstyle:IllegalCatch") AtomicReference submitTxAsync(final DOMDataWriteTransaction writeTx) { final AtomicReference caughtEx = new AtomicReference<>(); @@ -358,21 +217,6 @@ public class DOMBrokerTest { return caughtEx; } - static class TestDOMDataChangeListener implements DOMDataChangeListener { - - volatile AsyncDataChangeEvent> capturedChange; - private final CountDownLatch latch = new CountDownLatch(1); - - @Override - public void onDataChanged(final AsyncDataChangeEvent> 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 { diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDataChangeListenerTest.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDataTreeChangeListenerTest.java similarity index 98% rename from opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDataChangeListenerTest.java rename to opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDataTreeChangeListenerTest.java index 1146458171..b7d7948976 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDataChangeListenerTest.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDataTreeChangeListenerTest.java @@ -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); diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DatastoreTestTask.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DatastoreTestTask.java index ed17aa55cf..a62c0ba88f 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DatastoreTestTask.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DatastoreTestTask.java @@ -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> 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> listener) { - this.changeListener = listener; + @SafeVarargs + public final DatastoreTestTask changeListener(final YangInstanceIdentifier path, + Function... 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 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 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 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 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 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> 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> { + private final class ChangeEventListener implements DOMDataTreeChangeListener { + + final SettableFuture> future = SettableFuture.create(); + final Collection accumulatedChanges = new ArrayList<>(); + final Function[] matchers; + final int expChangeCount; - protected final SettableFuture>> - receivedChange = SettableFuture.create(); + ChangeEventListener(Function[] matchers) { + this.expChangeCount = matchers.length; + this.matchers = matchers; + } + + Collection changes() { + try { + Collection 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 changes = new ArrayList<>(changes()); + Iterator iter = changes.iterator(); + while (iter.hasNext()) { + DataTreeCandidate dataTreeModification = iter.next(); + for (Function 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> change) { - if (postSetup) { - receivedChange.set(change); + public void onDataTreeChanged(Collection changes) { + synchronized (accumulatedChanges) { + accumulatedChanges.addAll(changes); + if (expChangeCount == accumulatedChanges.size()) { + future.set(new ArrayList<>(accumulatedChanges)); + } } } } diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DefaultDataChangeListenerTestSuite.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DefaultDataTreeChangeListenerTestSuite.java similarity index 54% rename from opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DefaultDataChangeListenerTestSuite.java rename to opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DefaultDataTreeChangeListenerTestSuite.java index 74014493fa..2e9204420c 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DefaultDataChangeListenerTestSuite.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/DefaultDataTreeChangeListenerTestSuite.java @@ -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); } diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/RootScopeSubtreeTest.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/RootScopeSubtreeTest.java index 7d496568c6..c5af4067fc 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/RootScopeSubtreeTest.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/RootScopeSubtreeTest.java @@ -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> 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> 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> 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> 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> 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> 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> 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> 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(); } } diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeBaseTest.java b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeBaseTest.java index b9ce0accf8..23c35f3ed3 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeBaseTest.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeBaseTest.java @@ -7,140 +7,95 @@ */ 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> 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> 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> 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> 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> 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 index 02797c2761..0000000000 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeOneTest.java +++ /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> 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> 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> 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> 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> 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 index 31a9f9c979..0000000000 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/WildcardedScopeSubtreeTest.java +++ /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> 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> 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> 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> 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> 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> 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> 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> change = task.getChangeEvent(); - - assertContains(change.getCreatedData(), path(FOO_SIBLING)); - assertNotContains(change.getUpdatedData(), path(FOO), TOP_LEVEL); - assertEmpty(change.getRemovedPaths()); - } -}