d0ca71bbcbf4b772b981d745f9a1593c6fe179c3
[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.parseYang("""
68                 module ordered-list-modification-test {
69                   namespace "ordered-list-modification-test";
70                   prefix "olmt";
71
72                   container parent-container {
73                     container child-container {
74                       list parent-ordered-list {
75                         ordered-by user;
76                         key "parent-key-leaf";
77
78                         leaf parent-key-leaf {
79                           type string;
80                         }
81                         leaf parent-ordinary-leaf {
82                           type string;
83                         }
84
85                         list child-ordered-list {
86                           ordered-by user;
87                           key "child-key-leaf";
88
89                           leaf child-key-leaf {
90                             type string;
91                           }
92                           leaf child-ordinary-leaf {
93                             type string;
94                           }
95                         }
96                       }
97                     }
98                   }
99                 }"""));
100     }
101
102     @Test
103     public void testsequentialModifications() throws DataValidationFailedException {
104         modification1();
105         modification2();
106         delete1();
107         delete2();
108         modification3();
109         modification4();
110     }
111
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();
118
119         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
120                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
121                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
122                 .build();
123
124         YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
125
126         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
127         treeModification.write(path1, parentContainerNode);
128
129         UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
130                 new NodeIdentifier(childOrderedList))
131                 .withChild(createChildOrderedListEntry("chkval1", "chlfval1"))
132                 .withChild(createChildOrderedListEntry("chkval2", "chlfval2")).build();
133
134         YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer, childContainer, parentOrderedList)
135             .node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
136
137         treeModification.write(path2, childOrderedListNode);
138         treeModification.ready();
139         inMemoryDataTree.validate(treeModification);
140         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
141
142         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
143         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
144         assertTrue(readNode.isPresent());
145
146         readNode = snapshotAfterCommits.readNode(path2);
147         assertTrue(readNode.isPresent());
148     }
149
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();
156
157         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
158                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
159                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
160                 .build();
161
162         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
163
164         YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
165         treeModification.merge(path1, parentContainerNode);
166
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();
172
173         YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
174                 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
175         treeModification.merge(path2, childOrderedListNode);
176
177         treeModification.ready();
178         inMemoryDataTree.validate(treeModification);
179         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
180
181         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
182         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
183         assertTrue(readNode.isPresent());
184
185         readNode = snapshotAfterCommits.readNode(path2);
186         assertTrue(readNode.isPresent());
187     }
188
189     public void modification3() throws DataValidationFailedException {
190         UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
191                 new NodeIdentifier(parentOrderedList))
192                 .withChild(createParentOrderedListEntry("pkval1", "plfval1")).build();
193
194         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
195                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
196                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
197                 .build();
198
199         YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
200
201         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
202         treeModification.write(path1, parentContainerNode);
203
204         UserMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
205                 new NodeIdentifier(childOrderedList))
206                 .withChild(createChildOrderedListEntry("chkval1", "chlfval1new")).build();
207
208         YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
209                 .node(parentOrderedList)
210                 .node(createParentOrderedListEntryPath("pkval4")).node(childOrderedList);
211
212         treeModification.merge(path2, childOrderedListNode);
213
214         try {
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"));
222         }
223
224         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
225         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path1);
226         assertTrue(readNode.isPresent());
227
228         readNode = snapshotAfterCommits.readNode(path2);
229         assertFalse(readNode.isPresent());
230     }
231
232     public void modification4() throws DataValidationFailedException {
233         DataTreeModification treeModification1 = inMemoryDataTree.takeSnapshot().newModification();
234         DataTreeModification treeModification2 = inMemoryDataTree.takeSnapshot().newModification();
235
236         UserMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
237             new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval1", "plfval1"))
238                 .build();
239
240         UserMapNode parentOrderedListNode2 = Builders.orderedMapBuilder().withNodeIdentifier(
241             new NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval2", "plfval2"))
242                 .build();
243
244         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
245                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
246                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
247                 .build();
248
249         ContainerNode parentContainerNode2 = Builders.containerBuilder().withNodeIdentifier(
250                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
251                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode2).build())
252                 .build();
253
254         YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer);
255
256         treeModification1.write(path, parentContainerNode);
257         treeModification2.write(path, parentContainerNode2);
258         treeModification1.ready();
259         treeModification2.ready();
260
261         inMemoryDataTree.validate(treeModification1);
262         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification1));
263
264         try {
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"));
271         }
272
273         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
274         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
275         assertTrue(readNode.isPresent());
276     }
277
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"));
282
283         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
284         treeModification.delete(path);
285         treeModification.ready();
286         inMemoryDataTree.validate(treeModification);
287         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
288
289         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
290         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
291         assertFalse(readNode.isPresent());
292     }
293
294     public void delete2() throws DataValidationFailedException {
295         YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
296                 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2"));
297
298         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
299         treeModification.delete(path);
300         treeModification.ready();
301         inMemoryDataTree.validate(treeModification);
302         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
303
304         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
305         Optional<NormalizedNode> readNode = snapshotAfterCommits.readNode(path);
306         assertFalse(readNode.isPresent());
307     }
308
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();
314     }
315
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();
321     }
322
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);
327     }
328
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);
333     }
334 }