Bug 3899: Milestone: Increase test coverage for Yangtools
[yangtools.git] / yang / yang-data-impl / src / test / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / 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
9 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
10
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertTrue;
13 import static org.junit.Assert.fail;
14
15 import com.google.common.base.Optional;
16 import com.google.common.collect.ImmutableMap;
17 import java.io.File;
18 import java.net.URI;
19 import org.junit.Before;
20 import org.junit.Test;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.common.QNameModule;
23 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
32 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
33 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
34 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
35 import org.opendaylight.yangtools.yang.data.api.schema.tree.TipProducingDataTree;
36 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
37 import org.opendaylight.yangtools.yang.data.impl.RetestUtils;
38 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
39 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 public class OrderedListTest {
44     private Logger LOG = LoggerFactory.getLogger(OrderedListTest.class);
45
46     private TipProducingDataTree inMemoryDataTree;
47     private SchemaContext context;
48
49     private QNameModule testModule;
50     private QName parentContainer;
51     private QName childContainer;
52     private QName parentOrderedList;
53     private QName childOrderedList;
54     private QName parentKeyLeaf;
55     private QName parentOrdinaryLeaf;
56     private QName childKeyLeaf;
57     private QName childOrdinaryLeaf;
58
59     @Before
60     public void setup() throws Exception {
61         final File resourceFile = new File(Bug4295Test.class.getResource("/ordered-list-modification-test.yang")
62                 .toURI());
63         context = RetestUtils.parseYangSources(resourceFile);
64         testModule = QNameModule.create(new URI("ordered-list-modification-test"),
65                 SimpleDateFormatUtil.getRevisionFormat().parse("1970-01-01"));
66         parentContainer = QName.create(testModule, "parent-container");
67         childContainer = QName.create(testModule, "child-container");
68         parentOrderedList = QName.create(testModule, "parent-ordered-list");
69         childOrderedList = QName.create(testModule, "child-ordered-list");
70         parentKeyLeaf = QName.create(testModule, "parent-key-leaf");
71         childKeyLeaf = QName.create(testModule, "child-key-leaf");
72         parentOrdinaryLeaf = QName.create(testModule, "parent-ordinary-leaf");
73         childOrdinaryLeaf = QName.create(testModule, "child-ordinary-leaf");
74         inMemoryDataTree = InMemoryDataTreeFactory.getInstance().create(TreeType.OPERATIONAL);
75         inMemoryDataTree.setSchemaContext(context);
76     }
77
78     @Test
79     public void testsequentialModifications() throws DataValidationFailedException {
80         modification1();
81         modification2();
82         delete1();
83         delete2();
84         modification3();
85         modification4();
86     }
87
88     public void modification1() throws DataValidationFailedException {
89         OrderedMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
90                 new NodeIdentifier(parentOrderedList))
91                 .withChild(createParentOrderedListEntry("pkval1", "plfval1"))
92                 .withChild(createParentOrderedListEntry("pkval2", "plfval2"))
93                 .withChild(createParentOrderedListEntry("pkval3", "plfval3")).build();
94
95         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
96                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
97                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
98                 .build();
99
100         YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
101
102         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
103         treeModification.write(path1, parentContainerNode);
104
105         OrderedMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
106                 new NodeIdentifier(childOrderedList))
107                 .withChild(createChildOrderedListEntry("chkval1", "chlfval1"))
108                 .withChild(createChildOrderedListEntry("chkval2", "chlfval2")).build();
109
110         YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer)
111                 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
112
113         treeModification.write(path2, childOrderedListNode);
114         treeModification.ready();
115         inMemoryDataTree.validate(treeModification);
116         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
117
118         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
119         Optional<NormalizedNode<?, ?>> readNode = snapshotAfterCommits.readNode(path1);
120         assertTrue(readNode.isPresent());
121
122         readNode = snapshotAfterCommits.readNode(path2);
123         assertTrue(readNode.isPresent());
124     }
125
126     public void modification2() throws DataValidationFailedException {
127         OrderedMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
128                 new NodeIdentifier(parentOrderedList))
129                 .withChild(createParentOrderedListEntry("pkval3", "plfval3updated"))
130                 .withChild(createParentOrderedListEntry("pkval4", "plfval4"))
131                 .withChild(createParentOrderedListEntry("pkval5", "plfval5")).build();
132
133         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
134                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
135                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
136                 .build();
137
138         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
139
140         YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
141         treeModification.merge(path1, parentContainerNode);
142
143         OrderedMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
144                 new NodeIdentifier(childOrderedList))
145                 .withChild(createChildOrderedListEntry("chkval1", "chlfval1updated"))
146                 .withChild(createChildOrderedListEntry("chkval2", "chlfval2updated"))
147                 .withChild(createChildOrderedListEntry("chkval3", "chlfval3")).build();
148
149         YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer).node
150                 (parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList);
151         treeModification.merge(path2, childOrderedListNode);
152
153         treeModification.ready();
154         inMemoryDataTree.validate(treeModification);
155         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
156
157         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
158         Optional<NormalizedNode<?, ?>> readNode = snapshotAfterCommits.readNode(path1);
159         assertTrue(readNode.isPresent());
160
161         readNode = snapshotAfterCommits.readNode(path2);
162         assertTrue(readNode.isPresent());
163     }
164
165     public void modification3() throws DataValidationFailedException {
166         OrderedMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
167                 new NodeIdentifier(parentOrderedList))
168                 .withChild(createParentOrderedListEntry("pkval1", "plfval1")).build();
169
170         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
171                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
172                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build())
173                 .build();
174
175         YangInstanceIdentifier path1 = YangInstanceIdentifier.of(parentContainer);
176
177         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
178         treeModification.write(path1, parentContainerNode);
179
180         OrderedMapNode childOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(
181                 new NodeIdentifier(childOrderedList))
182                 .withChild(createChildOrderedListEntry("chkval1", "chlfval1new")).build();
183
184         YangInstanceIdentifier path2 = YangInstanceIdentifier.of(parentContainer).node(childContainer).node
185                 (parentOrderedList)
186                 .node(createParentOrderedListEntryPath("pkval4")).node(childOrderedList);
187
188         treeModification.merge(path2, childOrderedListNode);
189
190         try {
191             treeModification.ready();
192             fail("Exception should have been thrown.");
193             inMemoryDataTree.validate(treeModification);
194             inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
195         } catch (final IllegalArgumentException ex) {
196             LOG.debug("IllegalArgumentException was thrown as expected: {}", ex);
197             assertTrue(ex.getMessage().contains("Metadata not available for modification NodeModification"));
198         }
199
200         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
201         Optional<NormalizedNode<?, ?>> readNode = snapshotAfterCommits.readNode(path1);
202         assertTrue(readNode.isPresent());
203
204         readNode = snapshotAfterCommits.readNode(path2);
205         assertFalse(readNode.isPresent());
206     }
207
208     public void modification4() throws DataValidationFailedException {
209         DataTreeModification treeModification1 = inMemoryDataTree.takeSnapshot().newModification();
210         DataTreeModification treeModification2 = inMemoryDataTree.takeSnapshot().newModification();
211
212         OrderedMapNode parentOrderedListNode = Builders.orderedMapBuilder().withNodeIdentifier(new
213                 NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval1",
214                 "plfval1")).build();
215
216         OrderedMapNode parentOrderedListNode2 = Builders.orderedMapBuilder().withNodeIdentifier(new
217                 NodeIdentifier(parentOrderedList)).withChild(createParentOrderedListEntry("pkval2",
218                 "plfval2")).build();
219
220         ContainerNode parentContainerNode = Builders.containerBuilder().withNodeIdentifier(
221                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
222                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode).build()).build();
223
224         ContainerNode parentContainerNode2 = Builders.containerBuilder().withNodeIdentifier(
225                 new NodeIdentifier(parentContainer)).withChild(Builders.containerBuilder()
226                 .withNodeIdentifier(new NodeIdentifier(childContainer)).withChild(parentOrderedListNode2).build())
227                 .build();
228
229         YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer);
230
231         treeModification1.write(path, parentContainerNode);
232         treeModification2.write(path, parentContainerNode2);
233         treeModification1.ready();
234         treeModification2.ready();
235
236         inMemoryDataTree.validate(treeModification1);
237         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification1));
238
239         try {
240             inMemoryDataTree.validate(treeModification2);
241             fail("Exception should have been thrown.");
242             inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification2));
243         } catch (ConflictingModificationAppliedException ex) {
244             LOG.debug("ConflictingModificationAppliedException was thrown as expected: {}", ex);
245             assertTrue(ex.getMessage().contains("Node was replaced by other transaction"));
246         }
247
248         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
249         Optional<NormalizedNode<?, ?>> readNode = snapshotAfterCommits.readNode(path);
250         assertTrue(readNode.isPresent());
251     }
252
253     public void delete1() throws DataValidationFailedException {
254         YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
255                 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2")).node(childOrderedList)
256                 .node(createChildOrderedListEntryPath("chkval1"));
257
258         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
259         treeModification.delete(path);
260         treeModification.ready();
261         inMemoryDataTree.validate(treeModification);
262         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
263
264         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
265         Optional<NormalizedNode<?, ?>> readNode = snapshotAfterCommits.readNode(path);
266         assertFalse(readNode.isPresent());
267     }
268
269     public void delete2() throws DataValidationFailedException {
270         YangInstanceIdentifier path = YangInstanceIdentifier.of(parentContainer).node(childContainer)
271                 .node(parentOrderedList).node(createParentOrderedListEntryPath("pkval2"));
272
273         DataTreeModification treeModification = inMemoryDataTree.takeSnapshot().newModification();
274         treeModification.delete(path);
275         treeModification.ready();
276         inMemoryDataTree.validate(treeModification);
277         inMemoryDataTree.commit(inMemoryDataTree.prepare(treeModification));
278
279         DataTreeSnapshot snapshotAfterCommits = inMemoryDataTree.takeSnapshot();
280         Optional<NormalizedNode<?, ?>> readNode = snapshotAfterCommits.readNode(path);
281         assertFalse(readNode.isPresent());
282     }
283
284     private MapEntryNode createParentOrderedListEntry(String keyValue, String leafValue) {
285         return Builders.mapEntryBuilder().withNodeIdentifier(new NodeIdentifierWithPredicates(parentOrderedList,
286                 parentKeyLeaf, keyValue))
287                 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(parentOrdinaryLeaf)).withValue
288                         (leafValue).build()).build();
289     }
290
291     private MapEntryNode createChildOrderedListEntry(String keyValue, String leafValue) {
292         return Builders.mapEntryBuilder().withNodeIdentifier(new NodeIdentifierWithPredicates(childOrderedList,
293                 childKeyLeaf, keyValue))
294                 .withChild(Builders.leafBuilder().withNodeIdentifier(NodeIdentifier.create(childOrdinaryLeaf)).withValue
295                         (leafValue).build()).build();
296     }
297
298     private NodeIdentifierWithPredicates createParentOrderedListEntryPath(String keyValue) {
299         ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
300         ImmutableMap<QName, Object> keys = builder.put(parentKeyLeaf, keyValue).build();
301         return new NodeIdentifierWithPredicates(parentOrderedList, keys);
302     }
303
304     private NodeIdentifierWithPredicates createChildOrderedListEntryPath(String keyValue) {
305         ImmutableMap.Builder<QName, Object> builder = ImmutableMap.builder();
306         ImmutableMap<QName, Object> keys = builder.put(childKeyLeaf, keyValue).build();
307         return new NodeIdentifierWithPredicates(childOrderedList, keys);
308     }
309 }