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.impl.schema.tree;
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.api.schema.tree.ConflictingModificationAppliedException;
29 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
30 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
31 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
32 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
33 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
34 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
35 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 public class OrderedListTest {
40 private static final Logger LOG = LoggerFactory.getLogger(OrderedListTest.class);
42 private DataTree inMemoryDataTree;
44 private QNameModule testModule;
45 private QName parentContainer;
46 private QName childContainer;
47 private QName parentOrderedList;
48 private QName childOrderedList;
49 private QName parentKeyLeaf;
50 private QName parentOrdinaryLeaf;
51 private QName childKeyLeaf;
52 private QName childOrdinaryLeaf;
56 testModule = QNameModule.create(XMLNamespace.of("ordered-list-modification-test"));
57 parentContainer = QName.create(testModule, "parent-container");
58 childContainer = QName.create(testModule, "child-container");
59 parentOrderedList = QName.create(testModule, "parent-ordered-list");
60 childOrderedList = QName.create(testModule, "child-ordered-list");
61 parentKeyLeaf = QName.create(testModule, "parent-key-leaf");
62 childKeyLeaf = QName.create(testModule, "child-key-leaf");
63 parentOrdinaryLeaf = QName.create(testModule, "parent-ordinary-leaf");
64 childOrdinaryLeaf = QName.create(testModule, "child-ordinary-leaf");
65 inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL,
66 YangParserTestUtils.parseYangResource("/ordered-list-modification-test.yang"));
70 public void testsequentialModifications() throws DataValidationFailedException {
79 public void modification1() throws DataValidationFailedException {
80 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
81 new NodeIdentifier(parentOrderedList))
82 .withChild(createParentOrderedListEntry("pkval1", "plfval1"))
83 .withChild(createParentOrderedListEntry("pkval2", "plfval2"))
84 .withChild(createParentOrderedListEntry("pkval3", "plfval3")).build();
86 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
87 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
88 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
91 YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
93 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
94 treeModification.write(path1, parentContainerNode);
96 UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
97 new NodeIdentifier(childOrderedList))
98 .withChild(createChildOrderedListEntry("chkval1", "chlfval1"))
99 .withChild(createChildOrderedListEntry("chkval2", "chlfval2")).build();
101 YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
102 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
104 treeModification.write(path2, childOrderedListNode);
105 treeModification.ready();
106 inMemoryDataTree.validate(treeModification);
107 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
109 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
110 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
111 assertTrue(readNode.isPresent());
113 readNode = snapshotAfterCommits.readNode(path2);
114 assertTrue(readNode.isPresent());
117 public void modification2() throws DataValidationFailedException {
118 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
119 new NodeIdentifier(parentOrderedList))
120 .withChild(createParentOrderedListEntry("pkval3", "plfval3updated"))
121 .withChild(createParentOrderedListEntry("pkval4", "plfval4"))
122 .withChild(createParentOrderedListEntry("pkval5", "plfval5")).build();
124 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
125 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
126 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
129 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
131 YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
132 treeModification.merge(path1, parentContainerNode);
134 UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
135 new NodeIdentifier(childOrderedList))
136 .withChild(createChildOrderedListEntry("chkval1", "chlfval1updated"))
137 .withChild(createChildOrderedListEntry("chkval2", "chlfval2updated"))
138 .withChild(createChildOrderedListEntry("chkval3", "chlfval3")).build();
140 YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
141 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
142 treeModification.merge(path2, childOrderedListNode);
144 treeModification.ready();
145 inMemoryDataTree.validate(treeModification);
146 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
148 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
149 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
150 assertTrue(readNode.isPresent());
152 readNode = snapshotAfterCommits.readNode(path2);
153 assertTrue(readNode.isPresent());
156 public void modification3() throws DataValidationFailedException {
157 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
158 new NodeIdentifier(parentOrderedList))
159 .withChild(createParentOrderedListEntry("pkval1", "plfval1")).build();
161 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
162 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
163 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
166 YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
168 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
169 treeModification.write(path1, parentContainerNode);
171 UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
172 new NodeIdentifier(childOrderedList))
173 .withChild(createChildOrderedListEntry("chkval1", "chlfval1new")).build();
175 YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
176 .node(parentOrderedList)
177 .node(createParentOrderedListEntryPath("pkval4")).node(childOrderedList);
179 treeModification.merge(path2, childOrderedListNode);
182 treeModification.ready();
183 fail("Exception should have been thrown.");
184 inMemoryDataTree.validate(treeModification);
185 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
186 } catch (final IllegalArgumentException ex) {
187 LOG.debug("IllegalArgumentException was thrown as expected", ex);
188 assertTrue(ex.getMessage().contains("Metadata not available for modification ModifiedNode"));
191 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
192 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
193 assertTrue(readNode.isPresent());
195 readNode = snapshotAfterCommits.readNode(path2);
196 assertFalse(readNode.isPresent());
199 public void modification4() throws DataValidationFailedException {
200 DataTreeModification treeModification1 = inMemoryDataTree.takeSnapshot().newModification();
201 DataTreeModification treeModification2 = inMemoryDataTree.takeSnapshot().newModification();
203 UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
204 new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval1", "plfval1"))
207 UserMapNode parentOrderedListNode2 = Builders.orderedMapBuilder().withNodeIdentifier(
208 new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval2", "plfval2"))
211 ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
212 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
213 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
216 ContainerNode parentContainerNode2 = Builders.containerBuilder().withNodeIdentifier(
217 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
218 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode2).build())
221 YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer);
223 treeModification1.write(path, parentContainerNode);
224 treeModification2.write(path, parentContainerNode2);
225 treeModification1.ready();
226 treeModification2.ready();
228 inMemoryDataTree.validate(treeModification1);
229 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification1));
232 inMemoryDataTree.validate(treeModification2);
233 fail("Exception should have been thrown.");
234 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification2));
235 } catch (ConflictingModificationAppliedException ex) {
236 LOG.debug("ConflictingModificationAppliedException was thrown as expected", ex);
237 assertTrue(ex.getMessage().contains("Node was replaced by other transaction"));
240 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
241 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
242 assertTrue(readNode.isPresent());
245 public void delete1() throws DataValidationFailedException {
246 YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
247 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList)
248 .node(createChildOrderedListEntryPath("chkval1"));
250 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
251 treeModification.delete(path);
252 treeModification.ready();
253 inMemoryDataTree.validate(treeModification);
254 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
256 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
257 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
258 assertFalse(readNode.isPresent());
261 public void delete2() throws DataValidationFailedException {
262 YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
263 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2"));
265 DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
266 treeModification.delete(path);
267 treeModification.ready();
268 inMemoryDataTree.validate(treeModification);
269 inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
271 DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
272 Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
273 assertFalse(readNode.isPresent());
276 private MapEntryNode createParentOrderedListEntry(final String keyValue, final String leafValue) {
277 return Builders.mapEntryBuilder().withNodeIdentifier(NodeIdentifierWithPredicates.of(parentOrderedList,
278 parentKeyLeaf, keyValue))
279 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(parentOrdinaryLeaf))
280 .withValue(leafValue).build()).build();
283 private MapEntryNode createChildOrderedListEntry(final String keyValue, final String leafValue) {
284 return Builders.mapEntryBuilder().withNodeIdentifier(NodeIdentifierWithPredicates.of(childOrderedList,
285 childKeyLeaf, keyValue))
286 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(childOrdinaryLeaf))
287 .withValue(leafValue).build()).build();
290 private NodeIdentifierWithPredicates createParentOrderedListEntryPath(final String keyValue) {
291 ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
292 ImmutableMap<QName, Object> keys = builder.put(parentKeyLeaf, keyValue).build();
293 return NodeIdentifierWithPredicates.of(parentOrderedList, keys);
296 private NodeIdentifierWithPredicates createChildOrderedListEntryPath(final String keyValue) {
297 ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
298 ImmutableMap<QName, Object> keys = builder.put(childKeyLeaf, keyValue).build();
299 return NodeIdentifierWithPredicates.of(childOrderedList, keys);