2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.data.tree.impl;
10 import static org.junit.jupiter.api.Assertions.assertFalse;
11 import static org.junit.jupiter.api.Assertions.assertThrows;
12 import static org.junit.jupiter.api.Assertions.assertTrue;
14 import org.junit.jupiter.api.BeforeEach;
15 import org.junit.jupiter.api.Test;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.common.QNameModule;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
21 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
22 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
23 import org.opendaylight.yangtools.yang.data.tree.api.ConflictingModificationAppliedException;
24 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
25 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
26 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
27 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
28 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
32 class OrderedListTest {
33 private static final Logger LOG = LoggerFactory.getLogger(OrderedListTest.class);
35 private DataTree inMemoryDataTree;
37 private QNameModule testModule;
38 private QName parentContainer;
39 private QName childContainer;
40 private QName parentOrderedList;
41 private QName childOrderedList;
42 private QName parentKeyLeaf;
43 private QName parentOrdinaryLeaf;
44 private QName childKeyLeaf;
45 private QName childOrdinaryLeaf;
49 testModule = QNameModule.of("ordered-list-modification-test");
50 parentContainer = QName.create(testModule, "parent-container");
51 childContainer = QName.create(testModule, "child-container");
52 parentOrderedList = QName.create(testModule, "parent-ordered-list");
53 childOrderedList = QName.create(testModule, "child-ordered-list");
54 parentKeyLeaf = QName.create(testModule, "parent-key-leaf");
55 childKeyLeaf = QName.create(testModule, "child-key-leaf");
56 parentOrdinaryLeaf = QName.create(testModule, "parent-ordinary-leaf");
57 childOrdinaryLeaf = QName.create(testModule, "child-ordinary-leaf");
58 inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL,
59 YangParserTestUtils.parseYang("""
60 module ordered-list-modification-test {
61 namespace "ordered-list-modification-test";
64 container parent-container {
65 container child-container {
66 list parent-ordered-list {
68 key "parent-key-leaf";
70 leaf parent-key-leaf {
73 leaf parent-ordinary-leaf {
77 list child-ordered-list {
84 leaf child-ordinary-leaf {
95 void testsequentialModifications() throws DataValidationFailedException {
104 public void modification1() throws DataValidationFailedException {
105 final var parentOrderedListNode = ImmutableNodes.newUserMapBuilder()
106 .withNodeIdentifier(new NodeIdentifier(parentOrderedList))
107 .withChild(createParentOrderedListEntry("pkval1", "plfval1"))
108 .withChild(createParentOrderedListEntry("pkval2", "plfval2"))
109 .withChild(createParentOrderedListEntry("pkval3", "plfval3"))
112 final var parentContainerNode = ImmutableNodes.newContainerBuilder()
113 .withNodeIdentifier(new NodeIdentifier(parentContainer))
114 .withChild(ImmutableNodes.newContainerBuilder()
115 .withNodeIdentifier(new NodeIdentifier(childContainer))
116 .withChild(parentOrderedListNode)
120 final var path1 = YangInstanceIdentifier.of(parentContainer);
122 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
123 treeModification.write(path1, parentContainerNode);
125 final var childOrderedListNode = ImmutableNodes.newUserMapBuilder()
126 .withNodeIdentifier(new NodeIdentifier(childOrderedList))
127 .withChild(createChildOrderedListEntry("chkval1", "chlfval1"))
128 .withChild(createChildOrderedListEntry("chkval2", "chlfval2"))
131 final var path2 = YangInstanceIdentifier.of(parentContainer, childContainer, parentOrderedList)
132 .node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
134 treeModification.write(path2, childOrderedListNode);
135 treeModification.ready();
136 inMemoryDataTree.validate(treeModification);
137 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
139 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
140 var readNode = snapshotAfterCommits.readNode(path1);
141 assertTrue(readNode.isPresent());
143 readNode = snapshotAfterCommits.readNode(path2);
144 assertTrue(readNode.isPresent());
147 public void modification2() throws DataValidationFailedException {
148 final var parentOrderedListNode = ImmutableNodes.newUserMapBuilder()
149 .withNodeIdentifier(new NodeIdentifier(parentOrderedList))
150 .withChild(createParentOrderedListEntry("pkval3", "plfval3updated"))
151 .withChild(createParentOrderedListEntry("pkval4", "plfval4"))
152 .withChild(createParentOrderedListEntry("pkval5", "plfval5"))
155 final var parentContainerNode = ImmutableNodes.newContainerBuilder()
156 .withNodeIdentifier(new NodeIdentifier(parentContainer))
157 .withChild(ImmutableNodes.newContainerBuilder()
158 .withNodeIdentifier(new NodeIdentifier(childContainer))
159 .withChild(parentOrderedListNode)
163 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
165 final var path1 = YangInstanceIdentifier.of(parentContainer);
166 treeModification.merge(path1, parentContainerNode);
168 final var childOrderedListNode = ImmutableNodes.newUserMapBuilder()
169 .withNodeIdentifier(new NodeIdentifier(childOrderedList))
170 .withChild(createChildOrderedListEntry("chkval1", "chlfval1updated"))
171 .withChild(createChildOrderedListEntry("chkval2", "chlfval2updated"))
172 .withChild(createChildOrderedListEntry("chkval3", "chlfval3"))
175 final var path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
176 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
177 treeModification.merge(path2, childOrderedListNode);
179 treeModification.ready();
180 inMemoryDataTree.validate(treeModification);
181 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
183 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
184 var readNode = snapshotAfterCommits.readNode(path1);
185 assertTrue(readNode.isPresent());
187 readNode = snapshotAfterCommits.readNode(path2);
188 assertTrue(readNode.isPresent());
191 public void modification3() throws DataValidationFailedException {
192 final var parentOrderedListNode = ImmutableNodes.newUserMapBuilder()
193 .withNodeIdentifier(new NodeIdentifier(parentOrderedList))
194 .withChild(createParentOrderedListEntry("pkval1", "plfval1"))
197 final var parentContainerNode = ImmutableNodes.newContainerBuilder()
198 .withNodeIdentifier(new NodeIdentifier(parentContainer))
199 .withChild(ImmutableNodes.newContainerBuilder()
200 .withNodeIdentifier(new NodeIdentifier(childContainer))
201 .withChild(parentOrderedListNode)
205 final var path1 = YangInstanceIdentifier.of(parentContainer);
207 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
208 treeModification.write(path1, parentContainerNode);
210 final var childOrderedListNode = ImmutableNodes.newUserMapBuilder()
211 .withNodeIdentifier(new NodeIdentifier(childOrderedList))
212 .withChild(createChildOrderedListEntry("chkval1", "chlfval1new"))
215 final var path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
216 .node(parentOrderedList)
217 .node(createParentOrderedListEntryPath("pkval4")).node(childOrderedList);
219 treeModification.merge(path2, childOrderedListNode);
221 final var ex = assertThrows(IllegalArgumentException.class, treeModification::ready);
222 assertTrue(ex.getMessage().contains("Metadata not available for modification ModifiedNode"));
224 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
225 var readNode = snapshotAfterCommits.readNode(path1);
226 assertTrue(readNode.isPresent());
228 readNode = snapshotAfterCommits.readNode(path2);
229 assertFalse(readNode.isPresent());
232 public void modification4() throws DataValidationFailedException {
233 final var treeModification1 = inMemoryDataTree.takeSnapshot().newModification();
234 final var treeModification2 = inMemoryDataTree.takeSnapshot().newModification();
236 final var parentOrderedListNode = ImmutableNodes.newUserMapBuilder()
237 .withNodeIdentifier(new NodeIdentifier(parentOrderedList))
238 .withChild(createParentOrderedListEntry("pkval1", "plfval1"))
241 final var parentOrderedListNode2 = ImmutableNodes.newUserMapBuilder()
242 .withNodeIdentifier(new NodeIdentifier(parentOrderedList))
243 .withChild(createParentOrderedListEntry("pkval2", "plfval2"))
246 final var parentContainerNode = ImmutableNodes.newContainerBuilder()
247 .withNodeIdentifier(new NodeIdentifier(parentContainer))
248 .withChild(ImmutableNodes.newContainerBuilder()
249 .withNodeIdentifier(new NodeIdentifier(childContainer))
250 .withChild(parentOrderedListNode)
254 final var parentContainerNode2 = ImmutableNodes.newContainerBuilder()
255 .withNodeIdentifier(new NodeIdentifier(parentContainer))
256 .withChild(ImmutableNodes.newContainerBuilder()
257 .withNodeIdentifier(new NodeIdentifier(childContainer))
258 .withChild(parentOrderedListNode2)
262 final var path = YangInstanceIdentifier.of(parentContainer);
264 treeModification1.write(path, parentContainerNode);
265 treeModification2.write(path, parentContainerNode2);
266 treeModification1.ready();
267 treeModification2.ready();
269 inMemoryDataTree.validate(treeModification1);
270 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification1));
272 final var ex = assertThrows(ConflictingModificationAppliedException.class,
273 () -> inMemoryDataTree.validate(treeModification2));
274 LOG.debug("ConflictingModificationAppliedException was thrown as expected", ex);
275 assertTrue(ex.getMessage().contains("Node was replaced by other transaction"));
277 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
278 final var readNode = snapshotAfterCommits.readNode(path);
279 assertTrue(readNode.isPresent());
282 public void delete1() throws DataValidationFailedException {
283 final var path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
284 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList)
285 .node(createChildOrderedListEntryPath("chkval1"));
287 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
288 treeModification.delete(path);
289 treeModification.ready();
290 inMemoryDataTree.validate(treeModification);
291 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
293 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
294 final var readNode = snapshotAfterCommits.readNode(path);
295 assertFalse(readNode.isPresent());
298 public void delete2() throws DataValidationFailedException {
299 final var path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
300 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2"));
302 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
303 treeModification.delete(path);
304 treeModification.ready();
305 inMemoryDataTree.validate(treeModification);
306 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
308 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
309 final var readNode = snapshotAfterCommits.readNode(path);
310 assertFalse(readNode.isPresent());
313 private MapEntryNode createParentOrderedListEntry(final String keyValue, final String leafValue) {
314 return ImmutableNodes.newMapEntryBuilder()
315 .withNodeIdentifier(NodeIdentifierWithPredicates.of(parentOrderedList, parentKeyLeaf, keyValue))
316 .withChild(ImmutableNodes.leafNode(parentOrdinaryLeaf, leafValue))
320 private MapEntryNode createChildOrderedListEntry(final String keyValue, final String leafValue) {
321 return ImmutableNodes.newMapEntryBuilder()
322 .withNodeIdentifier(NodeIdentifierWithPredicates.of(childOrderedList, childKeyLeaf, keyValue))
323 .withChild(ImmutableNodes.leafNode(childOrdinaryLeaf, leafValue))
327 private NodeIdentifierWithPredicates createParentOrderedListEntryPath(final String keyValue) {
328 return NodeIdentifierWithPredicates.of(parentOrderedList, parentKeyLeaf, keyValue);
331 private NodeIdentifierWithPredicates createChildOrderedListEntryPath(final String keyValue) {
332 return NodeIdentifierWithPredicates.of(childOrderedList, childKeyLeaf, keyValue);