--- /dev/null
+/*
+ * Copyright (c) 2015 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.mdsal.binding.dom.adapter;
+
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.path;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.topLevelList;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+
+/**
+ * Regression test suite for Bug 1125 - Can't detect switch disconnection
+ * https://bugs.opendaylight.org/show_bug.cgi?id=1125.
+ */
+public class Bug1125RegressionTest extends AbstractDataTreeChangeListenerTest {
+ private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
+ private static final InstanceIdentifier<TopLevelList> TOP_FOO_PATH = TOP_PATH
+ .child(TopLevelList.class, TOP_FOO_KEY);
+
+ private static final InstanceIdentifier<TreeComplexUsesAugment> FOO_AUGMENT_PATH = TOP_FOO_PATH
+ .augmentation(TreeComplexUsesAugment.class);
+
+ private static final InstanceIdentifier<TreeComplexUsesAugment> WILDCARDED_AUGMENT_PATH = TOP_PATH
+ .child(TopLevelList.class).augmentation(
+ TreeComplexUsesAugment.class);
+
+ @Override
+ protected Set<YangModuleInfo> getModuleInfos() throws Exception {
+ return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+ BindingReflections.getModuleInfo(TreeComplexUsesAugment.class));
+ }
+
+ @Test
+ public void deleteAndListenAugment() {
+ deleteAndListenAugment(TOP_PATH);
+
+ deleteAndListenAugment(TOP_FOO_PATH);
+
+ deleteAndListenAugment(FOO_AUGMENT_PATH);
+ }
+
+ private void deleteAndListenAugment(final InstanceIdentifier<?> path) {
+ TreeComplexUsesAugment augment = writeInitialState();
+ TestListener<TreeComplexUsesAugment> listener = createListener(LogicalDatastoreType.OPERATIONAL,
+ WILDCARDED_AUGMENT_PATH, added(FOO_AUGMENT_PATH, augment), deleted(FOO_AUGMENT_PATH, augment));
+ WriteTransaction tx = getDataBroker().newWriteOnlyTransaction();
+ tx.delete(LogicalDatastoreType.OPERATIONAL, path);
+ assertCommit(tx.commit());
+ listener.verify();
+ }
+
+ private TreeComplexUsesAugment writeInitialState() {
+ WriteTransaction initialTx = getDataBroker().newWriteOnlyTransaction();
+ initialTx.put(LogicalDatastoreType.OPERATIONAL, TOP_PATH, new TopBuilder().build());
+ TreeComplexUsesAugment fooAugment = new TreeComplexUsesAugmentBuilder()
+ .setContainerWithUses(new ContainerWithUsesBuilder().setLeafFromGrouping("foo").build())
+ .build();
+ initialTx.put(LogicalDatastoreType.OPERATIONAL, path(TOP_FOO_KEY), topLevelList(TOP_FOO_KEY, fooAugment));
+ assertCommit(initialTx.commit());
+ return fooAugment;
+ }
+}
--- /dev/null
+/*
+ * 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.mdsal.binding.dom.adapter;
+
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.USES_ONE_KEY;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.USES_TWO_KEY;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.complexUsesAugment;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.path;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
+import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+
+/**
+ * This testsuite tries to replicate bug 1333 and tests regresion of it using test-model with similar construction as
+ * one reported.
+ *
+ * <p>
+ * See https://bugs.opendaylight.org/show_bug.cgi?id=1333 for Bug Description
+ */
+public class Bug1333DataChangeListenerTest extends AbstractDataTreeChangeListenerTest {
+ private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> AUGMENT_WILDCARD =
+ TOP_PATH.child(TopLevelList.class).augmentation(TreeComplexUsesAugment.class);
+
+ @Override
+ protected Set<YangModuleInfo> getModuleInfos() throws Exception {
+ return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+ BindingReflections.getModuleInfo(TreeComplexUsesAugment.class));
+ }
+
+ private static 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 = topWithListItem();
+ tx.put(store, TOP_PATH, topItem);
+ assertCommit(tx.commit());
+ return topItem;
+ }
+
+ public void deleteItem(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
+ ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
+ tx.delete(store, path);
+ assertCommit(tx.commit());
+ }
+
+ @Test
+ public void writeTopWithListItemAugmentedListenTopSubtree() {
+ TestListener<Top> listener = createListener(CONFIGURATION, TOP_PATH, added(TOP_PATH, topWithListItem()));
+
+ writeTopWithListItem(CONFIGURATION);
+
+ listener.verify();
+ }
+
+ @Test
+ public void writeTopWithListItemAugmentedListenAugmentSubtreeWildcarded() {
+ TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, AUGMENT_WILDCARD,
+ added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)));
+
+ writeTopWithListItem(CONFIGURATION);
+
+ listener.verify();
+ }
+
+ @Test
+ public void deleteAugmentChildListenTopSubtree() {
+ Top top = writeTopWithListItem(CONFIGURATION);
+
+ TestListener<Top> listener = createListener(CONFIGURATION, TOP_PATH, added(TOP_PATH, top),
+ subtreeModified(TOP_PATH, top, top(topLevelList(TOP_FOO_KEY, complexUsesAugment(USES_TWO_KEY)))));
+
+ InstanceIdentifier<ListViaUses> deletePath = path(TOP_FOO_KEY, USES_ONE_KEY);
+ deleteItem(CONFIGURATION, deletePath);
+
+ listener.verify();
+ }
+
+ @Test
+ public void deleteAugmentChildListenAugmentSubtreeWildcarded() {
+ writeTopWithListItem(CONFIGURATION);
+
+ TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, AUGMENT_WILDCARD,
+ added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY)),
+ subtreeModified(path(TOP_FOO_KEY, TreeComplexUsesAugment.class),
+ complexUsesAugment(USES_ONE_KEY, USES_TWO_KEY), complexUsesAugment(USES_TWO_KEY)));
+
+ InstanceIdentifier<?> deletePath = path(TOP_FOO_KEY, USES_ONE_KEY);
+ deleteItem(CONFIGURATION, deletePath);
+
+ listener.verify();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014, 2015 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.mdsal.binding.dom.adapter;
+
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.complexUsesAugment;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.leafOnlyUsesAugment;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.path;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+
+public class Bug1418AugmentationTest extends AbstractDataTreeChangeListenerTest {
+ private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
+ private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
+ private static final InstanceIdentifier<TreeLeafOnlyUsesAugment> SIMPLE_AUGMENT =
+ TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeLeafOnlyUsesAugment.class);
+ private static final InstanceIdentifier<TreeComplexUsesAugment> COMPLEX_AUGMENT =
+ TOP.child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeComplexUsesAugment.class);
+ private static final ListViaUsesKey LIST_VIA_USES_KEY =
+ new ListViaUsesKey("list key");
+ private static final ListViaUsesKey LIST_VIA_USES_KEY_MOD =
+ new ListViaUsesKey("list key modified");
+
+ @Override
+ protected Set<YangModuleInfo> getModuleInfos() throws Exception {
+ return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class),
+ BindingReflections.getModuleInfo(TreeComplexUsesAugment.class),
+ BindingReflections.getModuleInfo(TreeLeafOnlyUsesAugment.class));
+ }
+
+ @Test
+ public void leafOnlyAugmentationCreatedTest() {
+ TreeLeafOnlyUsesAugment leafOnlyUsesAugment = leafOnlyUsesAugment("test leaf");
+ final TestListener<TreeLeafOnlyUsesAugment> listener = createListener(CONFIGURATION, SIMPLE_AUGMENT,
+ added(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugment));
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(CONFIGURATION, TOP, top());
+ writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugment);
+ assertCommit(writeTx.commit());
+
+ listener.verify();
+ }
+
+ @Test
+ public void leafOnlyAugmentationUpdatedTest() {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ 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.commit());
+
+ TreeLeafOnlyUsesAugment leafOnlyUsesAugmentAfter = leafOnlyUsesAugment("test leaf changed");
+ final TestListener<TreeLeafOnlyUsesAugment> listener = createListener(CONFIGURATION, SIMPLE_AUGMENT,
+ added(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugmentBefore),
+ replaced(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugmentBefore,
+ leafOnlyUsesAugmentAfter));
+
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(CONFIGURATION, SIMPLE_AUGMENT, leafOnlyUsesAugmentAfter);
+ assertCommit(writeTx.commit());
+
+ listener.verify();
+ }
+
+ @Test
+ public void leafOnlyAugmentationDeletedTest() {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ 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.commit());
+
+ final TestListener<TreeLeafOnlyUsesAugment> listener = createListener(CONFIGURATION, SIMPLE_AUGMENT,
+ added(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugment),
+ deleted(path(TOP_FOO_KEY, TreeLeafOnlyUsesAugment.class), leafOnlyUsesAugment));
+
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.delete(CONFIGURATION, SIMPLE_AUGMENT);
+ assertCommit(writeTx.commit());
+
+ listener.verify();
+ }
+
+ @Test
+ public void complexAugmentationCreatedTest() {
+ TreeComplexUsesAugment complexUsesAugment = complexUsesAugment(LIST_VIA_USES_KEY);
+ final TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, COMPLEX_AUGMENT,
+ added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugment));
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(CONFIGURATION, TOP, top());
+ writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugment);
+ assertCommit(writeTx.commit());
+
+ listener.verify();
+ }
+
+ @Test
+ public void complexAugmentationUpdatedTest() {
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(CONFIGURATION, TOP, top());
+ writeTx.put(CONFIGURATION, TOP_FOO, topLevelList(new TopLevelListKey(TOP_FOO_KEY)));
+ TreeComplexUsesAugment complexUsesAugmentBefore = complexUsesAugment(LIST_VIA_USES_KEY);
+ writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugmentBefore);
+ assertCommit(writeTx.commit());
+
+ TreeComplexUsesAugment complexUsesAugmentAfter = complexUsesAugment(LIST_VIA_USES_KEY_MOD);
+
+ final TestListener<TreeComplexUsesAugment> listener = createListener(CONFIGURATION, COMPLEX_AUGMENT,
+ added(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugmentBefore),
+ replaced(path(TOP_FOO_KEY, TreeComplexUsesAugment.class), complexUsesAugmentBefore,
+ complexUsesAugmentAfter));
+
+ writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(CONFIGURATION, COMPLEX_AUGMENT, complexUsesAugmentAfter);
+ assertCommit(writeTx.commit());
+
+ listener.verify();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.mdsal.binding.dom.adapter;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Arrays;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
+import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.Root;
+import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.RootBuilder;
+import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.Fooroot;
+import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.FoorootBuilder;
+import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.fooroot.Barroot;
+import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.fooroot.BarrootBuilder;
+import org.opendaylight.yang.gen.v1.opendaylight.test.bug._2562.namespace.rev160101.root.fooroot.BarrootKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+
+public class Bug2562DeserializedUnkeyedListTest extends AbstractDataTreeChangeListenerTest {
+ private static final InstanceIdentifier<Root> ROOT_PATH = InstanceIdentifier.create(Root.class);
+
+ @Override
+ protected Set<YangModuleInfo> getModuleInfos() throws Exception {
+ return ImmutableSet.of(BindingReflections.getModuleInfo(Root.class));
+ }
+
+ @Test
+ public void writeListToList2562Root() {
+ final Barroot barRoot = new BarrootBuilder().setType(2).setValue(2).withKey(new BarrootKey(2)).build();
+ final Fooroot fooRoot = new FoorootBuilder().setBarroot(Arrays.asList(barRoot)).build();
+ final Root root = new RootBuilder().setFooroot(Arrays.asList(fooRoot)).build();
+
+ final TestListener<Root> listenerRoot = createListener(LogicalDatastoreType.CONFIGURATION, ROOT_PATH,
+ added(ROOT_PATH, root));
+
+ final ReadWriteTransaction readWriteTransaction = getDataBroker().newReadWriteTransaction();
+ readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, root);
+ assertCommit(readWriteTransaction.commit());
+
+ listenerRoot.verify();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.mdsal.binding.dom.adapter;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
+import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+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.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+
+public class Bug3090MultiKeyList extends AbstractDataTreeChangeListenerTest {
+ private static final InstanceIdentifier<Root> ROOT_PATH = InstanceIdentifier.create(Root.class);
+
+ @Override
+ protected Set<YangModuleInfo> getModuleInfos() throws Exception {
+ return ImmutableSet.of(BindingReflections.getModuleInfo(Root.class));
+ }
+
+ @Test
+ public void listWithMultiKeyTest() {
+ final List<ListInRoot> listInRoots = new ArrayList<>();
+ for (int i = 0; i < 10; i++) {
+ listInRoots.add(new ListInRootBuilder()
+ .setLeafA("leaf a" + i)
+ .setLeafC("leaf c" + i)
+ .setLeafB("leaf b" + i)
+ .build()
+ );
+ }
+
+ final Root root = new RootBuilder().setListInRoot(listInRoots).build();
+
+ final TestListener<Root> listener = createListener(LogicalDatastoreType.CONFIGURATION, ROOT_PATH,
+ match(ModificationType.WRITE, ROOT_PATH, Objects::isNull,
+ (Function<Root, Boolean>) dataAfter -> checkData(root, dataAfter)));
+
+ final ReadWriteTransaction readWriteTransaction = getDataBroker().newReadWriteTransaction();
+ readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, ROOT_PATH, root);
+ assertCommit(readWriteTransaction.commit());
+
+ listener.verify();
+ }
+
+ private static boolean checkData(final Root expected, final Root actual) {
+ if (actual == null) {
+ return false;
+ }
+
+ Set<ListInRoot> expListInRoot = new HashSet<>(expected.getListInRoot().values());
+ Set<ListInRoot> actualListInRoot = actual.getListInRoot().values().stream()
+ .map(list -> new ListInRootBuilder(list).build()).collect(Collectors.toSet());
+ return expListInRoot.equals(actualListInRoot);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.mdsal.binding.dom.adapter;
+
+import java.util.ArrayList;
+import org.junit.Test;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataBrokerTest;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Bug4494Test extends AbstractDataBrokerTest {
+ @Test
+ public void testDelete() throws Exception {
+ DataBroker dataBroker = getDataBroker();
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+ ArrayList<TopLevelList> list = new ArrayList<>();
+ list.add(new TopLevelListBuilder().setName("name").build());
+ TopBuilder builder = new TopBuilder().setTopLevelList(list);
+ writeTransaction.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Top.class), builder.build());
+ assertCommit(writeTransaction.commit());
+
+ InstanceIdentifier<TopLevelList> id = InstanceIdentifier.builder(Top.class)
+ .child(TopLevelList.class, new TopLevelListKey("name")).build();
+
+ ReadWriteTransaction writeTransaction1 = dataBroker.newReadWriteTransaction();
+
+ writeTransaction1.delete(LogicalDatastoreType.OPERATIONAL, id);
+ assertCommit(writeTransaction1.commit());
+ ReadWriteTransaction writeTransaction2 = dataBroker.newReadWriteTransaction();
+
+ writeTransaction2.delete(LogicalDatastoreType.OPERATIONAL, id);
+ assertCommit(writeTransaction2.commit());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc., 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.mdsal.binding.dom.adapter;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataBrokerTest;
+import org.opendaylight.mdsal.common.api.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.listener.rev150825.listener.test.ListItem;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.listener.rev150825.listener.test.ListItemBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.Uint32;
+
+/**
+ * Regression test suite for https://bugs.opendaylight.org/show_bug.cgi?id=4513 - Change event is empty when
+ * Homogeneous composite key is used homogeneous composite key is used.
+ */
+public class Bug4513Test extends AbstractDataBrokerTest {
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Test
+ public void testDataTreeChangeListener() {
+ DataBroker dataBroker = getDataBroker();
+
+ DataTreeChangeListener<ListItem> listener = mock(DataTreeChangeListener.class);
+ InstanceIdentifier<ListItem> wildCard = InstanceIdentifier.builder(ListenerTest.class)
+ .child(ListItem.class).build();
+ ListenerRegistration<DataTreeChangeListener<ListItem>> reg = dataBroker.registerDataTreeChangeListener(
+ DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, wildCard), listener);
+
+ final ListItem item = writeListItem();
+
+ ArgumentCaptor<Collection> captor = ArgumentCaptor.forClass(Collection.class);
+
+ verify(listener, timeout(100)).onDataTreeChanged(captor.capture());
+
+ Collection<DataTreeModification<ListItem>> mods = captor.getValue();
+ assertEquals("ListItem", item, mods.iterator().next().getRootNode().getDataAfter());
+ }
+
+ private ListItem writeListItem() {
+ WriteTransaction writeTransaction = getDataBroker().newWriteOnlyTransaction();
+ final ListItem item = new ListItemBuilder().setSip("name").setOp(Uint32.valueOf(43)).build();
+ ListenerTestBuilder builder = new ListenerTestBuilder().setListItem(Arrays.asList(item));
+ writeTransaction.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(
+ ListenerTest.class).build(), builder.build());
+ assertCommit(writeTransaction.commit());
+ return item;
+ }
+}
--- /dev/null
+/*
+ * 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.mdsal.binding.dom.adapter;
+
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.TOP_BAR_KEY;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.TOP_FOO_KEY;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.mdsal.binding.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
+
+import com.google.common.collect.ImmutableSet;
+import java.util.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.mdsal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
+import org.opendaylight.mdsal.binding.api.WriteTransaction;
+import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataTreeChangeListenerTest;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+
+/**
+ * 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 AbstractDataTreeChangeListenerTest {
+ private static final InstanceIdentifier<Top> TOP = InstanceIdentifier.create(Top.class);
+ private static final InstanceIdentifier<TopLevelList> WILDCARDED = TOP.child(TopLevelList.class);
+ private static final InstanceIdentifier<TopLevelList> TOP_FOO = TOP.child(TopLevelList.class, TOP_FOO_KEY);
+ private static final InstanceIdentifier<TopLevelList> TOP_BAR = TOP.child(TopLevelList.class, TOP_BAR_KEY);
+
+ @Override
+ protected Set<YangModuleInfo> getModuleInfos() throws Exception {
+ return ImmutableSet.of(BindingReflections.getModuleInfo(Top.class));
+ }
+
+ @Before
+ public void setupWithDataBroker() {
+ WriteTransaction initialTx = getDataBroker().newWriteOnlyTransaction();
+ initialTx.put(CONFIGURATION, TOP, top(topLevelList(TOP_FOO_KEY)));
+ assertCommit(initialTx.commit());
+ }
+
+ @Test
+ public void replaceTopNodeSubtreeListeners() {
+ final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
+ final Top top = top(topBar);
+ final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
+
+ // Listener for TOP element
+ final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+ added(TOP, top(topLevelList(TOP_FOO_KEY))), replaced(TOP, top(topFoo), top));
+
+ // Listener for all list items. This one should see Foo item deleted and Bar item added.
+ final TestListener<TopLevelList> allListener = createListener(CONFIGURATION, WILDCARDED,
+ added(TOP_FOO, topFoo), added(TOP_BAR, topBar), deleted(TOP_FOO, topFoo));
+
+ // Listener for all Foo item. This one should see only Foo item deleted.
+ final TestListener<TopLevelList> fooListener = createListener(CONFIGURATION, TOP_FOO,
+ added(TOP_FOO, topFoo), deleted(TOP_FOO, topFoo));
+
+ // Listener for bar list items.
+ final TestListener<TopLevelList> barListener = createListener(CONFIGURATION, TOP_BAR,
+ added(TOP_BAR, topBar));
+
+ ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
+ writeTx.put(CONFIGURATION, TOP, top);
+ assertCommit(writeTx.commit());
+
+ topListener.verify();
+ allListener.verify();
+ fooListener.verify();
+ barListener.verify();
+ }
+
+ @Test
+ public void mergeTopNodeSubtreeListeners() {
+ final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
+ final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
+
+ final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+ added(TOP, top(topLevelList(TOP_FOO_KEY))), topSubtreeModified(topFoo, topBar));
+ final TestListener<TopLevelList> allListener = createListener(CONFIGURATION, WILDCARDED,
+ added(TOP_FOO, topFoo), added(TOP_BAR, topBar));
+ final TestListener<TopLevelList> fooListener = createListener(CONFIGURATION, TOP_FOO,
+ added(TOP_FOO, topFoo));
+ final TestListener<TopLevelList> barListener = createListener(CONFIGURATION, TOP_BAR,
+ added(TOP_BAR, topBar));
+
+ ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
+ writeTx.merge(CONFIGURATION, TOP, top(topLevelList(TOP_BAR_KEY)));
+ assertCommit(writeTx.commit());
+
+ topListener.verify();
+ allListener.verify();
+ fooListener.verify();
+ barListener.verify();
+ }
+
+ @Test
+ public void putTopBarNodeSubtreeListeners() {
+ final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
+ final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
+
+ final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+ added(TOP, top(topLevelList(TOP_FOO_KEY))), topSubtreeModified(topFoo, topBar));
+ final TestListener<TopLevelList> allListener = createListener(CONFIGURATION, WILDCARDED,
+ added(TOP_FOO, topFoo), added(TOP_BAR, topBar));
+ final TestListener<TopLevelList> fooListener = createListener(CONFIGURATION, TOP_FOO,
+ added(TOP_FOO, topFoo));
+ final TestListener<TopLevelList> barListener = createListener(CONFIGURATION, TOP_BAR,
+ added(TOP_BAR, topBar));
+
+ ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
+ writeTx.put(CONFIGURATION, TOP_BAR, topLevelList(TOP_BAR_KEY));
+ assertCommit(writeTx.commit());
+
+ topListener.verify();
+ allListener.verify();
+ fooListener.verify();
+ barListener.verify();
+ }
+
+ @Test
+ public void mergeTopBarNodeSubtreeListeners() {
+ final TopLevelList topBar = topLevelList(TOP_BAR_KEY);
+ final TopLevelList topFoo = topLevelList(TOP_FOO_KEY);
+
+ final TestListener<Top> topListener = createListener(CONFIGURATION, TOP,
+ added(TOP, top(topLevelList(TOP_FOO_KEY))), topSubtreeModified(topFoo, topBar));
+ final TestListener<TopLevelList> allListener = createListener(CONFIGURATION, WILDCARDED,
+ added(TOP_FOO, topFoo), added(TOP_BAR, topBar));
+ final TestListener<TopLevelList> fooListener = createListener(CONFIGURATION, TOP_FOO,
+ added(TOP_FOO, topFoo));
+ final TestListener<TopLevelList> barListener = createListener(CONFIGURATION, TOP_BAR,
+ added(TOP_BAR, topBar));
+
+ ReadWriteTransaction writeTx = getDataBroker().newReadWriteTransaction();
+ writeTx.merge(CONFIGURATION, TOP_BAR, topLevelList(TOP_BAR_KEY));
+ assertCommit(writeTx.commit());
+
+ topListener.verify();
+ allListener.verify();
+ fooListener.verify();
+ barListener.verify();
+ }
+
+ private static Function<DataTreeModification<Top>, Boolean> topSubtreeModified(final TopLevelList topFoo,
+ final TopLevelList topBar) {
+ return match(ModificationType.SUBTREE_MODIFIED, TOP,
+ (Function<Top, Boolean>) dataBefore -> Objects.equals(top(topFoo), dataBefore),
+ dataAfter -> {
+ Set<TopLevelList> expList = new HashSet<>(top(topBar, topFoo).getTopLevelList().values());
+ Set<TopLevelList> actualList = dataAfter.getTopLevelList().values().stream()
+ .map(list -> new TopLevelListBuilder(list).build()).collect(Collectors.toSet());
+ return expList.equals(actualList);
+ });
+ }
+}
--- /dev/null
+/*
+ * 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.mdsal.binding.dom.adapter.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.mdsal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Abstract base that provides a DTCL for verification.
+ *
+ * @author Thomas Pantelis
+ */
+public class AbstractDataTreeChangeListenerTest extends AbstractConcurrentDataBrokerTest {
+ protected static final class TestListener<T extends DataObject> implements DataTreeChangeListener<T> {
+ private final SettableFuture<Collection<DataTreeModification<T>>> future = SettableFuture.create();
+ private final List<DataTreeModification<T>> accumulatedChanges = new ArrayList<>();
+ private final Function<DataTreeModification<T>, Boolean>[] matchers;
+ private final int expChangeCount;
+
+ private TestListener(final Function<DataTreeModification<T>, Boolean>[] matchers) {
+ this.expChangeCount = matchers.length;
+ this.matchers = matchers;
+ }
+
+ @Override
+ public void onDataTreeChanged(final Collection<DataTreeModification<T>> changes) {
+ synchronized (accumulatedChanges) {
+ accumulatedChanges.addAll(changes);
+ if (expChangeCount == accumulatedChanges.size()) {
+ future.set(new ArrayList<>(accumulatedChanges));
+ }
+ }
+ }
+
+ public Collection<DataTreeModification<T>> changes() {
+ try {
+ final Collection<DataTreeModification<T>> changes = future.get(5, TimeUnit.SECONDS);
+ Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
+ return changes;
+ } catch (InterruptedException | TimeoutException | ExecutionException e) {
+ throw new AssertionError(String.format(
+ "Data tree change notifications not received. Expected: %s. Actual: %s - %s",
+ expChangeCount, accumulatedChanges.size(), accumulatedChanges), e);
+ }
+ }
+
+ public void verify() {
+ Collection<DataTreeModification<T>> changes = new ArrayList<>(changes());
+ Iterator<DataTreeModification<T>> iter = changes.iterator();
+ while (iter.hasNext()) {
+ DataTreeModification<T> dataTreeModification = iter.next();
+ for (Function<DataTreeModification<T>, Boolean> matcher: matchers) {
+ if (matcher.apply(dataTreeModification)) {
+ iter.remove();
+ break;
+ }
+ }
+ }
+
+ if (!changes.isEmpty()) {
+ DataTreeModification<T> mod = changes.iterator().next();
+ fail(String.format("Received unexpected notification: type: %s, path: %s, before: %s, after: %s",
+ mod.getRootNode().getModificationType(), mod.getRootPath().getRootIdentifier(),
+ mod.getRootNode().getDataBefore(), mod.getRootNode().getDataAfter()));
+ }
+ }
+
+ public boolean hasChanges() {
+ synchronized (accumulatedChanges) {
+ return !accumulatedChanges.isEmpty();
+ }
+ }
+ }
+
+ protected AbstractDataTreeChangeListenerTest() {
+ super(true);
+ }
+
+ @SafeVarargs
+ protected final <T extends DataObject> TestListener<T> createListener(final LogicalDatastoreType store,
+ final InstanceIdentifier<T> path, final Function<DataTreeModification<T>, Boolean>... matchers) {
+ TestListener<T> listener = new TestListener<>(matchers);
+ getDataBroker().registerDataTreeChangeListener(DataTreeIdentifier.create(store, path), listener);
+ return listener;
+ }
+
+ public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> match(
+ final ModificationType type, final InstanceIdentifier<T> path, final Function<T, Boolean> checkDataBefore,
+ final Function<T, Boolean> checkDataAfter) {
+ return modification -> type == modification.getRootNode().getModificationType()
+ && path.equals(modification.getRootPath().getRootIdentifier())
+ && checkDataBefore.apply(modification.getRootNode().getDataBefore())
+ && checkDataAfter.apply(modification.getRootNode().getDataAfter());
+ }
+
+ public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> match(final ModificationType type,
+ final InstanceIdentifier<T> path, final T expDataBefore, final T expDataAfter) {
+ return match(type, path, dataBefore -> Objects.equals(expDataBefore, dataBefore),
+ (Function<T, Boolean>) dataAfter -> Objects.equals(expDataAfter, dataAfter));
+ }
+
+ public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> added(
+ final InstanceIdentifier<T> path, final T data) {
+ return match(ModificationType.WRITE, path, null, data);
+ }
+
+ public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> replaced(
+ final InstanceIdentifier<T> path, final T dataBefore, final T dataAfter) {
+ return match(ModificationType.WRITE, path, dataBefore, dataAfter);
+ }
+
+ public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> deleted(
+ final InstanceIdentifier<T> path, final T dataBefore) {
+ return match(ModificationType.DELETE, path, dataBefore, null);
+ }
+
+ public static <T extends DataObject> Function<DataTreeModification<T>, Boolean> subtreeModified(
+ final InstanceIdentifier<T> path, final T dataBefore, final T dataAfter) {
+ return match(ModificationType.SUBTREE_MODIFIED, path, dataBefore, dataAfter);
+ }
+}
--- /dev/null
+module listener-container {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:listener";
+ prefix "test";
+
+ revision "2015-08-25" {
+ description
+ "Initial revision.";
+ }
+
+ container listener-test {
+ list list-item {
+ key "sip op";
+ leaf sip {
+ type string;
+ }
+ leaf op {
+ type uint32;
+ }
+ }
+ }
+}
--- /dev/null
+module opendaylight-test-bug-2562 {
+ yang-version 1;
+ namespace "opendaylight-test-bug-2562:namespace";
+ prefix "ty";
+ revision "2016-01-01" {
+ description
+ "bug 2562 Binding Data Codec: Incorrectly deserialized unkeyed list from NormalizedNode";
+ }
+
+ container root {
+ list fooroot {
+ list barroot {
+ key "type";
+ leaf type { type int32; }
+ leaf value { type int32; }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+module opendaylight-test-bug-3090 {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:opendaylight-test-bug-3090";
+ prefix "rpc";
+
+ description
+ "Test model for Bug 3090 - An AsyncDataChangeEvent instance's getCreatedData() method can't get data if list has multi-key";
+
+ revision "2016-01-01" {
+ description
+ "Bug 3090";
+ }
+
+ container root {
+ list list-in-root {
+ key "leaf-c leaf-a leaf-b";
+ leaf leaf-a {
+ type string;
+ }
+ leaf leaf-b {
+ type string;
+ }
+ leaf leaf-c {
+ type string;
+ }
+ }
+ }
+}
\ No newline at end of file