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.Assert.assertFalse;
11 import static org.junit.Assert.assertTrue;
12 import static org.junit.Assert.fail;
14 import com.google.common.collect.ImmutableMap;
15 import java.util.Optional;
16 import org.junit.Before;
17 import org.junit.Test;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.common.QNameModule;
20 import org.opendaylight.yangtools.yang.common.XMLNamespace;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
24 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.UserMapNode;
28 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
29 import org.opendaylight.yangtools.yang.data.tree.api.ConflictingModificationAppliedException;
30 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
31 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
32 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
33 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeSnapshot;
34 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
35 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
36 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
40 public class OrderedListTest {
41 private static final Logger LOG = LoggerFactory.getLogger(OrderedListTest.class);
43 private DataTree inMemoryDataTree;
45 private QNameModule testModule;
46 private QName parentContainer;
47 private QName childContainer;
48 private QName parentOrderedList;
49 private QName childOrderedList;
50 private QName parentKeyLeaf;
51 private QName parentOrdinaryLeaf;
52 private QName childKeyLeaf;
53 private QName childOrdinaryLeaf;
57 testModule = QNameModule.create(XMLNamespace.of("ordered-list-modification-test"));
58 parentContainer = QName.create(testModule, "parent-container");
59 childContainer = QName.create(testModule, "child-container");
60 parentOrderedList = QName.create(testModule, "parent-ordered-list");
61 childOrderedList = QName.create(testModule, "child-ordered-list");
62 parentKeyLeaf = QName.create(testModule, "parent-key-leaf");
63 childKeyLeaf = QName.create(testModule, "child-key-leaf");
64 parentOrdinaryLeaf = QName.create(testModule, "parent-ordinary-leaf");
65 childOrdinaryLeaf = QName.create(testModule, "child-ordinary-leaf");
66 inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL,
67 YangParserTestUtils.parseYang("""
68 module ordered-list-modification-test {
69 namespace "ordered-list-modification-test";
72 container parent-container {
73 container child-container {
74 list parent-ordered-list {
76 key "parent-key-leaf";
78 leaf parent-key-leaf {
81 leaf parent-ordinary-leaf {
85 list child-ordered-list {
92 leaf child-ordinary-leaf {
103 public void testsequentialModifications() throws DataValidationFailedException {
112 public void modification1() throws DataValidationFailedException {
113 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
114 new NodeIdentifier(parentOrderedList))
115 .withChild(createParentOrderedListEntry("pkval1", "plfval1"))
116 .withChild(createParentOrderedListEntry("pkval2", "plfval2"))
117 .withChild(createParentOrderedListEntry("pkval3", "plfval3")).build();
119 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
120 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
121 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
124 YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
126 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
127 treeModification.write(path1, parentContainerNode);
129 UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
130 new NodeIdentifier(childOrderedList))
131 .withChild(createChildOrderedListEntry("chkval1", "chlfval1"))
132 .withChild(createChildOrderedListEntry("chkval2", "chlfval2")).build();
134 YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer, childContainer, parentOrderedList)
135 .node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
137 treeModification.write(path2, childOrderedListNode);
138 treeModification.ready();
139 inMemoryDataTree.validate(treeModification);
140 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
142 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
143 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
144 assertTrue(readNode.isPresent());
146 readNode = snapshotAfterCommits.readNode(path2);
147 assertTrue(readNode.isPresent());
150 public void modification2() throws DataValidationFailedException {
151 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
152 new NodeIdentifier(parentOrderedList))
153 .withChild(createParentOrderedListEntry("pkval3", "plfval3updated"))
154 .withChild(createParentOrderedListEntry("pkval4", "plfval4"))
155 .withChild(createParentOrderedListEntry("pkval5", "plfval5")).build();
157 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
158 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
159 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
162 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
164 YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
165 treeModification.merge(path1, parentContainerNode);
167 UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
168 new NodeIdentifier(childOrderedList))
169 .withChild(createChildOrderedListEntry("chkval1", "chlfval1updated"))
170 .withChild(createChildOrderedListEntry("chkval2", "chlfval2updated"))
171 .withChild(createChildOrderedListEntry("chkval3", "chlfval3")).build();
173 YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
174 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
175 treeModification.merge(path2, childOrderedListNode);
177 treeModification.ready();
178 inMemoryDataTree.validate(treeModification);
179 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
181 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
182 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
183 assertTrue(readNode.isPresent());
185 readNode = snapshotAfterCommits.readNode(path2);
186 assertTrue(readNode.isPresent());
189 public void modification3() throws DataValidationFailedException {
190 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
191 new NodeIdentifier(parentOrderedList))
192 .withChild(createParentOrderedListEntry("pkval1", "plfval1")).build();
194 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
195 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
196 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
199 YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
201 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
202 treeModification.write(path1, parentContainerNode);
204 UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
205 new NodeIdentifier(childOrderedList))
206 .withChild(createChildOrderedListEntry("chkval1", "chlfval1new")).build();
208 YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
209 .node(parentOrderedList)
210 .node(createParentOrderedListEntryPath("pkval4")).node(childOrderedList);
212 treeModification.merge(path2, childOrderedListNode);
215 treeModification.ready();
216 fail("Exception should have been thrown.");
217 inMemoryDataTree.validate(treeModification);
218 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
219 } catch (final IllegalArgumentException ex) {
220 LOG.debug("IllegalArgumentException was thrown as expected", ex);
221 assertTrue(ex.getMessage().contains("Metadata not available for modification ModifiedNode"));
224 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
225 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
226 assertTrue(readNode.isPresent());
228 readNode = snapshotAfterCommits.readNode(path2);
229 assertFalse(readNode.isPresent());
232 public void modification4() throws DataValidationFailedException {
233 DataTreeModification treeModification1 = inMemoryDataTree.takeSnapshot().newModification();
234 DataTreeModification treeModification2 = inMemoryDataTree.takeSnapshot().newModification();
236 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
237 new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval1", "plfval1"))
240 UserMapNode parentOrderedListNode2 = Builders.orderedMapBuilder().withNodeIdentifier(
241 new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval2", "plfval2"))
244 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
245 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
246 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
249 ContainerNode parentContainerNode2 = Builders.containerBuilder().withNodeIdentifier(
250 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
251 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode2).build())
254 YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer);
256 treeModification1.write(path, parentContainerNode);
257 treeModification2.write(path, parentContainerNode2);
258 treeModification1.ready();
259 treeModification2.ready();
261 inMemoryDataTree.validate(treeModification1);
262 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification1));
265 inMemoryDataTree.validate(treeModification2);
266 fail("Exception should have been thrown.");
267 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification2));
268 } catch (ConflictingModificationAppliedException ex) {
269 LOG.debug("ConflictingModificationAppliedException was thrown as expected", ex);
270 assertTrue(ex.getMessage().contains("Node was replaced by other transaction"));
273 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
274 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
275 assertTrue(readNode.isPresent());
278 public void delete1() throws DataValidationFailedException {
279 YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
280 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList)
281 .node(createChildOrderedListEntryPath("chkval1"));
283 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
284 treeModification.delete(path);
285 treeModification.ready();
286 inMemoryDataTree.validate(treeModification);
287 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
289 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
290 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
291 assertFalse(readNode.isPresent());
294 public void delete2() throws DataValidationFailedException {
295 YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
296 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2"));
298 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
299 treeModification.delete(path);
300 treeModification.ready();
301 inMemoryDataTree.validate(treeModification);
302 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
304 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
305 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
306 assertFalse(readNode.isPresent());
309 private MapEntryNode createParentOrderedListEntry(final String keyValue, final String leafValue) {
310 return Builders.mapEntryBuilder().withNodeIdentifier(NodeIdentifierWithPredicates.of(parentOrderedList,
311 parentKeyLeaf, keyValue))
312 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(parentOrdinaryLeaf))
313 .withValue(leafValue).build()).build();
316 private MapEntryNode createChildOrderedListEntry(final String keyValue, final String leafValue) {
317 return Builders.mapEntryBuilder().withNodeIdentifier(NodeIdentifierWithPredicates.of(childOrderedList,
318 childKeyLeaf, keyValue))
319 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(childOrdinaryLeaf))
320 .withValue(leafValue).build()).build();
323 private NodeIdentifierWithPredicates createParentOrderedListEntryPath(final String keyValue) {
324 ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
325 ImmutableMap<QName, Object> keys = builder.put(parentKeyLeaf, keyValue).build();
326 return NodeIdentifierWithPredicates.of(parentOrderedList, keys);
329 private NodeIdentifierWithPredicates createChildOrderedListEntryPath(final String keyValue) {
330 ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
331 ImmutableMap<QName, Object> keys = builder.put(childKeyLeaf, keyValue).build();
332 return NodeIdentifierWithPredicates.of(childOrderedList, keys);