Split out yang-data-tree-impl
[yangtools.git] / data / yang-data-tree-ri / src / test / java / org / opendaylight / yangtools / yang / data / tree / impl / OrderedListTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.data.tree.impl;
9
10 import static org.junit.Assert.assertFalse;
11 import static org.junit.Assert.assertTrue;
12 import static org.junit.Assert.fail;
13
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;
39
40 public class OrderedListTest {
41     private static final Logger LOG = LoggerFactory.getLogger(OrderedListTest.class);
42
43     private DataTree inMemoryDataTree;
44
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;
54
55     @Before
56     public void setup() {
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"));
68     }
69
70     @Test
71     public void testsequentialModifications() throws DataValidationFailedException {
72         modification1();
73         modification2();
74         delete1();
75         delete2();
76         modification3();
77         modification4();
78     }
79
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();
86
87         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
88                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
89                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
90                 .build();
91
92         YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
93
94         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
95         treeModification.write(path1, parentContainerNode);
96
97         UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
98                 new NodeIdentifier(childOrderedList))
99                 .withChild(createChildOrderedListEntry("chkval1", "chlfval1"))
100                 .withChild(createChildOrderedListEntry("chkval2", "chlfval2")).build();
101
102         YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
103                 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
104
105         treeModification.write(path2, childOrderedListNode);
106         treeModification.ready();
107         inMemoryDataTree.validate(treeModification);
108         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
109
110         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
111         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
112         assertTrue(readNode.isPresent());
113
114         readNode = snapshotAfterCommits.readNode(path2);
115         assertTrue(readNode.isPresent());
116     }
117
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();
124
125         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
126                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
127                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
128                 .build();
129
130         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
131
132         YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
133         treeModification.merge(path1, parentContainerNode);
134
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();
140
141         YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
142                 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
143         treeModification.merge(path2, childOrderedListNode);
144
145         treeModification.ready();
146         inMemoryDataTree.validate(treeModification);
147         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
148
149         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
150         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
151         assertTrue(readNode.isPresent());
152
153         readNode = snapshotAfterCommits.readNode(path2);
154         assertTrue(readNode.isPresent());
155     }
156
157     public void modification3() throws DataValidationFailedException {
158         UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
159                 new NodeIdentifier(parentOrderedList))
160                 .withChild(createParentOrderedListEntry("pkval1", "plfval1")).build();
161
162         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
163                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
164                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
165                 .build();
166
167         YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
168
169         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
170         treeModification.write(path1, parentContainerNode);
171
172         UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
173                 new NodeIdentifier(childOrderedList))
174                 .withChild(createChildOrderedListEntry("chkval1", "chlfval1new")).build();
175
176         YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
177                 .node(parentOrderedList)
178                 .node(createParentOrderedListEntryPath("pkval4")).node(childOrderedList);
179
180         treeModification.merge(path2, childOrderedListNode);
181
182         try {
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"));
190         }
191
192         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
193         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
194         assertTrue(readNode.isPresent());
195
196         readNode = snapshotAfterCommits.readNode(path2);
197         assertFalse(readNode.isPresent());
198     }
199
200     public void modification4() throws DataValidationFailedException {
201         DataTreeModification treeModification1 = inMemoryDataTree.takeSnapshot().newModification();
202         DataTreeModification treeModification2 = inMemoryDataTree.takeSnapshot().newModification();
203
204         UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
205             new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval1", "plfval1"))
206                 .build();
207
208         UserMapNode parentOrderedListNode2 = Builders.orderedMapBuilder().withNodeIdentifier(
209             new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval2", "plfval2"))
210                 .build();
211
212         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
213                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
214                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
215                 .build();
216
217         ContainerNode parentContainerNode2 = Builders.containerBuilder().withNodeIdentifier(
218                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
219                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode2).build())
220                 .build();
221
222         YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer);
223
224         treeModification1.write(path, parentContainerNode);
225         treeModification2.write(path, parentContainerNode2);
226         treeModification1.ready();
227         treeModification2.ready();
228
229         inMemoryDataTree.validate(treeModification1);
230         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification1));
231
232         try {
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"));
239         }
240
241         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
242         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
243         assertTrue(readNode.isPresent());
244     }
245
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"));
250
251         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
252         treeModification.delete(path);
253         treeModification.ready();
254         inMemoryDataTree.validate(treeModification);
255         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
256
257         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
258         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
259         assertFalse(readNode.isPresent());
260     }
261
262     public void delete2() throws DataValidationFailedException {
263         YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
264                 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2"));
265
266         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
267         treeModification.delete(path);
268         treeModification.ready();
269         inMemoryDataTree.validate(treeModification);
270         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
271
272         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
273         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
274         assertFalse(readNode.isPresent());
275     }
276
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();
282     }
283
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();
289     }
290
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);
295     }
296
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);
301     }
302 }