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.parseYangResource("/ordered-list-modification-test.yang"));
71 public void testsequentialModifications() throws DataValidationFailedException {
80 public void modification1() throws DataValidationFailedException {
81 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
82 new NodeIdentifier(parentOrderedList))
83 .withChild(createParentOrderedListEntry("pkval1", "plfval1"))
84 .withChild(createParentOrderedListEntry("pkval2", "plfval2"))
85 .withChild(createParentOrderedListEntry("pkval3", "plfval3")).build();
87 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
88 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
89 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
92 YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
94 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
95 treeModification.write(path1, parentContainerNode);
97 UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
98 new NodeIdentifier(childOrderedList))
99 .withChild(createChildOrderedListEntry("chkval1", "chlfval1"))
100 .withChild(createChildOrderedListEntry("chkval2", "chlfval2")).build();
102 YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
103 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
105 treeModification.write(path2, childOrderedListNode);
106 treeModification.ready();
107 inMemoryDataTree.validate(treeModification);
108 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
110 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
111 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
112 assertTrue(readNode.isPresent());
114 readNode = snapshotAfterCommits.readNode(path2);
115 assertTrue(readNode.isPresent());
118 public void modification2() throws DataValidationFailedException {
119 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
120 new NodeIdentifier(parentOrderedList))
121 .withChild(createParentOrderedListEntry("pkval3", "plfval3updated"))
122 .withChild(createParentOrderedListEntry("pkval4", "plfval4"))
123 .withChild(createParentOrderedListEntry("pkval5", "plfval5")).build();
125 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
126 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
127 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
130 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
132 YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
133 treeModification.merge(path1, parentContainerNode);
135 UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
136 new NodeIdentifier(childOrderedList))
137 .withChild(createChildOrderedListEntry("chkval1", "chlfval1updated"))
138 .withChild(createChildOrderedListEntry("chkval2", "chlfval2updated"))
139 .withChild(createChildOrderedListEntry("chkval3", "chlfval3")).build();
141 YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
142 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
143 treeModification.merge(path2, childOrderedListNode);
145 treeModification.ready();
146 inMemoryDataTree.validate(treeModification);
147 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
149 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
150 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
151 assertTrue(readNode.isPresent());
153 readNode = snapshotAfterCommits.readNode(path2);
154 assertTrue(readNode.isPresent());
157 public void modification3() throws DataValidationFailedException {
158 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
159 new NodeIdentifier(parentOrderedList))
160 .withChild(createParentOrderedListEntry("pkval1", "plfval1")).build();
162 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
163 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
164 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
167 YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
169 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
170 treeModification.write(path1, parentContainerNode);
172 UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
173 new NodeIdentifier(childOrderedList))
174 .withChild(createChildOrderedListEntry("chkval1", "chlfval1new")).build();
176 YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
177 .node(parentOrderedList)
178 .node(createParentOrderedListEntryPath("pkval4")).node(childOrderedList);
180 treeModification.merge(path2, childOrderedListNode);
183 treeModification.ready();
184 fail("Exception should have been thrown.");
185 inMemoryDataTree.validate(treeModification);
186 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
187 } catch (final IllegalArgumentException ex) {
188 LOG.debug("IllegalArgumentException was thrown as expected", ex);
189 assertTrue(ex.getMessage().contains("Metadata not available for modification ModifiedNode"));
192 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
193 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
194 assertTrue(readNode.isPresent());
196 readNode = snapshotAfterCommits.readNode(path2);
197 assertFalse(readNode.isPresent());
200 public void modification4() throws DataValidationFailedException {
201 DataTreeModification treeModification1 = inMemoryDataTree.takeSnapshot().newModification();
202 DataTreeModification treeModification2 = inMemoryDataTree.takeSnapshot().newModification();
204 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
205 new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval1", "plfval1"))
208 UserMapNode parentOrderedListNode2 = Builders.orderedMapBuilder().withNodeIdentifier(
209 new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval2", "plfval2"))
212 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
213 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
214 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
217 ContainerNode parentContainerNode2 = Builders.containerBuilder().withNodeIdentifier(
218 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
219 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode2).build())
222 YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer);
224 treeModification1.write(path, parentContainerNode);
225 treeModification2.write(path, parentContainerNode2);
226 treeModification1.ready();
227 treeModification2.ready();
229 inMemoryDataTree.validate(treeModification1);
230 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification1));
233 inMemoryDataTree.validate(treeModification2);
234 fail("Exception should have been thrown.");
235 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification2));
236 } catch (ConflictingModificationAppliedException ex) {
237 LOG.debug("ConflictingModificationAppliedException was thrown as expected", ex);
238 assertTrue(ex.getMessage().contains("Node was replaced by other transaction"));
241 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
242 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
243 assertTrue(readNode.isPresent());
246 public void delete1() throws DataValidationFailedException {
247 YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
248 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList)
249 .node(createChildOrderedListEntryPath("chkval1"));
251 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
252 treeModification.delete(path);
253 treeModification.ready();
254 inMemoryDataTree.validate(treeModification);
255 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
257 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
258 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
259 assertFalse(readNode.isPresent());
262 public void delete2() throws DataValidationFailedException {
263 YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
264 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2"));
266 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
267 treeModification.delete(path);
268 treeModification.ready();
269 inMemoryDataTree.validate(treeModification);
270 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
272 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
273 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
274 assertFalse(readNode.isPresent());
277 private MapEntryNode createParentOrderedListEntry(final String keyValue, final String leafValue) {
278 return Builders.mapEntryBuilder().withNodeIdentifier(NodeIdentifierWithPredicates.of(parentOrderedList,
279 parentKeyLeaf, keyValue))
280 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(parentOrdinaryLeaf))
281 .withValue(leafValue).build()).build();
284 private MapEntryNode createChildOrderedListEntry(final String keyValue, final String leafValue) {
285 return Builders.mapEntryBuilder().withNodeIdentifier(NodeIdentifierWithPredicates.of(childOrderedList,
286 childKeyLeaf, keyValue))
287 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(childOrdinaryLeaf))
288 .withValue(leafValue).build()).build();
291 private NodeIdentifierWithPredicates createParentOrderedListEntryPath(final String keyValue) {
292 ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
293 ImmutableMap<QName, Object> keys = builder.put(parentKeyLeaf, keyValue).build();
294 return NodeIdentifierWithPredicates.of(parentOrderedList, keys);
297 private NodeIdentifierWithPredicates createChildOrderedListEntryPath(final String keyValue) {
298 ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
299 ImmutableMap<QName, Object> keys = builder.put(childKeyLeaf, keyValue).build();
300 return NodeIdentifierWithPredicates.of(childOrderedList, keys);