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.assertTrue;
12 import static org.junit.jupiter.api.Assertions.fail;
14 import com.google.common.collect.ImmutableMap;
15 import org.junit.jupiter.api.BeforeEach;
16 import org.junit.jupiter.api.Test;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.common.XMLNamespace;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
23 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
24 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
25 import org.opendaylight.yangtools.yang.data.tree.api.ConflictingModificationAppliedException;
26 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
27 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
28 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
29 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
30 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 class OrderedListTest {
35 private static final Logger LOG = LoggerFactory.getLogger(OrderedListTest.class);
37 private DataTree inMemoryDataTree;
39 private QNameModule testModule;
40 private QName parentContainer;
41 private QName childContainer;
42 private QName parentOrderedList;
43 private QName childOrderedList;
44 private QName parentKeyLeaf;
45 private QName parentOrdinaryLeaf;
46 private QName childKeyLeaf;
47 private QName childOrdinaryLeaf;
51 testModule = QNameModule.create(XMLNamespace.of("ordered-list-modification-test"));
52 parentContainer = QName.create(testModule, "parent-container");
53 childContainer = QName.create(testModule, "child-container");
54 parentOrderedList = QName.create(testModule, "parent-ordered-list");
55 childOrderedList = QName.create(testModule, "child-ordered-list");
56 parentKeyLeaf = QName.create(testModule, "parent-key-leaf");
57 childKeyLeaf = QName.create(testModule, "child-key-leaf");
58 parentOrdinaryLeaf = QName.create(testModule, "parent-ordinary-leaf");
59 childOrdinaryLeaf = QName.create(testModule, "child-ordinary-leaf");
60 inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL,
61 YangParserTestUtils.parseYang("""
62 module ordered-list-modification-test {
63 namespace "ordered-list-modification-test";
66 container parent-container {
67 container child-container {
68 list parent-ordered-list {
70 key "parent-key-leaf";
72 leaf parent-key-leaf {
75 leaf parent-ordinary-leaf {
79 list child-ordered-list {
86 leaf child-ordinary-leaf {
97 void testsequentialModifications() throws DataValidationFailedException {
106 public void modification1() throws DataValidationFailedException {
107 final var parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
108 new NodeIdentifier(parentOrderedList))
109 .withChild(createParentOrderedListEntry("pkval1", "plfval1"))
110 .withChild(createParentOrderedListEntry("pkval2", "plfval2"))
111 .withChild(createParentOrderedListEntry("pkval3", "plfval3")).build();
113 final var parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
114 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
115 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
118 final var path1 = YangInstanceIdentifier.of(parentContainer);
120 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
121 treeModification.write(path1, parentContainerNode);
123 final var childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
124 new NodeIdentifier(childOrderedList))
125 .withChild(createChildOrderedListEntry("chkval1", "chlfval1"))
126 .withChild(createChildOrderedListEntry("chkval2", "chlfval2")).build();
128 final var path2 = YangInstanceIdentifier.of(parentContainer, childContainer, parentOrderedList)
129 .node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
131 treeModification.write(path2, childOrderedListNode);
132 treeModification.ready();
133 inMemoryDataTree.validate(treeModification);
134 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
136 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
137 var readNode = snapshotAfterCommits.readNode(path1);
138 assertTrue(readNode.isPresent());
140 readNode = snapshotAfterCommits.readNode(path2);
141 assertTrue(readNode.isPresent());
144 public void modification2() throws DataValidationFailedException {
145 final var parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
146 new NodeIdentifier(parentOrderedList))
147 .withChild(createParentOrderedListEntry("pkval3", "plfval3updated"))
148 .withChild(createParentOrderedListEntry("pkval4", "plfval4"))
149 .withChild(createParentOrderedListEntry("pkval5", "plfval5")).build();
151 final var parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
152 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
153 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
156 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
158 final var path1 = YangInstanceIdentifier.of(parentContainer);
159 treeModification.merge(path1, parentContainerNode);
161 final var childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
162 new NodeIdentifier(childOrderedList))
163 .withChild(createChildOrderedListEntry("chkval1", "chlfval1updated"))
164 .withChild(createChildOrderedListEntry("chkval2", "chlfval2updated"))
165 .withChild(createChildOrderedListEntry("chkval3", "chlfval3")).build();
167 final var path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
168 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
169 treeModification.merge(path2, childOrderedListNode);
171 treeModification.ready();
172 inMemoryDataTree.validate(treeModification);
173 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
175 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
176 var readNode = snapshotAfterCommits.readNode(path1);
177 assertTrue(readNode.isPresent());
179 readNode = snapshotAfterCommits.readNode(path2);
180 assertTrue(readNode.isPresent());
183 public void modification3() throws DataValidationFailedException {
184 final var parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
185 new NodeIdentifier(parentOrderedList))
186 .withChild(createParentOrderedListEntry("pkval1", "plfval1")).build();
188 final var parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
189 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
190 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
193 final var path1 = YangInstanceIdentifier.of(parentContainer);
195 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
196 treeModification.write(path1, parentContainerNode);
198 final var childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
199 new NodeIdentifier(childOrderedList))
200 .withChild(createChildOrderedListEntry("chkval1", "chlfval1new")).build();
202 final var path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
203 .node(parentOrderedList)
204 .node(createParentOrderedListEntryPath("pkval4")).node(childOrderedList);
206 treeModification.merge(path2, childOrderedListNode);
209 treeModification.ready();
210 fail("Exception should have been thrown.");
211 inMemoryDataTree.validate(treeModification);
212 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
213 } catch (final IllegalArgumentException ex) {
214 LOG.debug("IllegalArgumentException was thrown as expected", ex);
215 assertTrue(ex.getMessage().contains("Metadata not available for modification ModifiedNode"));
218 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
219 var readNode = snapshotAfterCommits.readNode(path1);
220 assertTrue(readNode.isPresent());
222 readNode = snapshotAfterCommits.readNode(path2);
223 assertFalse(readNode.isPresent());
226 public void modification4() throws DataValidationFailedException {
227 final var treeModification1 = inMemoryDataTree.takeSnapshot().newModification();
228 final var treeModification2 = inMemoryDataTree.takeSnapshot().newModification();
230 final var parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
231 new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval1", "plfval1"))
234 final var parentOrderedListNode2 = Builders.orderedMapBuilder().withNodeIdentifier(
235 new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval2", "plfval2"))
238 final var parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
239 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
240 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
243 final var parentContainerNode2 = Builders.containerBuilder().withNodeIdentifier(
244 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
245 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode2).build())
248 final var path = YangInstanceIdentifier.of(parentContainer);
250 treeModification1.write(path, parentContainerNode);
251 treeModification2.write(path, parentContainerNode2);
252 treeModification1.ready();
253 treeModification2.ready();
255 inMemoryDataTree.validate(treeModification1);
256 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification1));
259 inMemoryDataTree.validate(treeModification2);
260 fail("Exception should have been thrown.");
261 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification2));
262 } catch (ConflictingModificationAppliedException ex) {
263 LOG.debug("ConflictingModificationAppliedException was thrown as expected", ex);
264 assertTrue(ex.getMessage().contains("Node was replaced by other transaction"));
267 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
268 final var readNode = snapshotAfterCommits.readNode(path);
269 assertTrue(readNode.isPresent());
272 public void delete1() throws DataValidationFailedException {
273 final var path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
274 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList)
275 .node(createChildOrderedListEntryPath("chkval1"));
277 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
278 treeModification.delete(path);
279 treeModification.ready();
280 inMemoryDataTree.validate(treeModification);
281 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
283 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
284 final var readNode = snapshotAfterCommits.readNode(path);
285 assertFalse(readNode.isPresent());
288 public void delete2() throws DataValidationFailedException {
289 final var path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
290 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2"));
292 final var treeModification = inMemoryDataTree.takeSnapshot().newModification();
293 treeModification.delete(path);
294 treeModification.ready();
295 inMemoryDataTree.validate(treeModification);
296 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
298 final var snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
299 final var readNode = snapshotAfterCommits.readNode(path);
300 assertFalse(readNode.isPresent());
303 private MapEntryNode createParentOrderedListEntry(final String keyValue, final String leafValue) {
304 return Builders.mapEntryBuilder().withNodeIdentifier(NodeIdentifierWithPredicates.of(parentOrderedList,
305 parentKeyLeaf, keyValue))
306 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(parentOrdinaryLeaf))
307 .withValue(leafValue).build()).build();
310 private MapEntryNode createChildOrderedListEntry(final String keyValue, final String leafValue) {
311 return Builders.mapEntryBuilder().withNodeIdentifier(NodeIdentifierWithPredicates.of(childOrderedList,
312 childKeyLeaf, keyValue))
313 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(childOrdinaryLeaf))
314 .withValue(leafValue).build()).build();
317 private NodeIdentifierWithPredicates createParentOrderedListEntryPath(final String keyValue) {
318 ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
319 ImmutableMap<QName, Object> keys = builder.put(parentKeyLeaf, keyValue).build();
320 return NodeIdentifierWithPredicates.of(parentOrderedList, keys);
323 private NodeIdentifierWithPredicates createChildOrderedListEntryPath(final String keyValue) {
324 ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
325 ImmutableMap<QName, Object> keys = builder.put(childKeyLeaf, keyValue).build();
326 return NodeIdentifierWithPredicates.of(childOrderedList, keys);