Split out yang-data-tree-impl
[yangtools.git] / data / yang-data-tree-ri / src / test / java / org / opendaylight / yangtools / yang / data / tree / impl / Bug5830Test.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.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13 import static org.junit.Assert.fail;
14
15 import com.google.common.collect.ImmutableMap;
16 import org.junit.Test;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
21 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
23 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.builder.DataContainerNodeBuilder;
26 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
27 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
28 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
29 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
30 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
31 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
32 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
33 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
34 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
35
36 public class Bug5830Test {
37     private static final String NS = "foo";
38     private static final String REV = "2016-05-17";
39     private static final QName TASK_CONTAINER = QName.create(NS, REV, "task-container");
40     private static final QName TASK = QName.create(NS, REV, "task");
41     private static final QName TASK_ID = QName.create(NS, REV, "task-id");
42     private static final QName TASK_DATA = QName.create(NS, REV, "task-data");
43     private static final QName OTHER_DATA = QName.create(NS, REV, "other-data");
44     private static final QName MANDATORY_DATA = QName.create(NS, REV, "mandatory-data");
45     private static final QName TASK_MANDATORY_LEAF = QName.create(NS, REV, "task-mandatory-leaf");
46     private static final QName NON_PRESENCE_CONTAINER = QName.create(NS, REV, "non-presence-container");
47     private static final QName NON_PRESENCE_CONTAINER_2 = QName.create(NS, REV, "non-presence-container-2");
48     private static final QName PRESENCE_CONTAINER_2 = QName.create(NS, REV, "presence-container-2");
49     private static final QName MANDATORY_LEAF_2 = QName.create(NS, REV, "mandatory-leaf-2");
50
51     private static DataTree initDataTree(final EffectiveModelContext schemaContext)
52             throws DataValidationFailedException {
53         DataTree inMemoryDataTree = new InMemoryDataTreeFactory().create(
54                 DataTreeConfiguration.DEFAULT_CONFIGURATION, schemaContext);
55
56         final SystemMapNode taskNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(TASK)).build();
57         final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
58         modificationTree.write(YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK), taskNode);
59         modificationTree.ready();
60
61         inMemoryDataTree.validate(modificationTree);
62         final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
63         inMemoryDataTree.commit(prepare);
64         return inMemoryDataTree;
65     }
66
67     @Test
68     public void testMandatoryNodes() throws DataValidationFailedException {
69         testPresenceContainer();
70         testNonPresenceContainer();
71         testMultipleContainers();
72     }
73
74     private static void testPresenceContainer() throws DataValidationFailedException {
75         final EffectiveModelContext schemaContext = TestModel.createTestContext("/bug-5830/foo-presence.yang");
76         assertNotNull("Schema context must not be null.", schemaContext);
77
78         testContainerIsNotPresent(schemaContext);
79         try {
80             testContainerIsPresent(schemaContext);
81             fail("Should fail due to missing mandatory node under present presence container.");
82         } catch (IllegalArgumentException e) {
83             assertEquals(
84                     "Node (foo?revision=2016-05-17)task-data is missing mandatory descendant /(foo?revision=2016-05-17)"
85                             + "mandatory-data", e.getMessage());
86         }
87         testMandatoryDataLeafIsPresent(schemaContext);
88     }
89
90     private static void testNonPresenceContainer() throws DataValidationFailedException {
91         final EffectiveModelContext schemaContext = TestModel.createTestContext("/bug-5830/foo-non-presence.yang");
92         assertNotNull("Schema context must not be null.", schemaContext);
93
94         try {
95             testContainerIsNotPresent(schemaContext);
96             fail("Should fail due to missing mandatory node.");
97         } catch (IllegalArgumentException e) {
98             assertEquals(
99                     "Node (foo?revision=2016-05-17)task[{(foo?revision=2016-05-17)task-id=123}] is missing mandatory "
100                             + "descendant /(foo?revision=2016-05-17)task-data/mandatory-data", e.getMessage());
101         }
102
103         try {
104             testContainerIsPresent(schemaContext);
105             fail("Should fail due to missing mandatory node.");
106         } catch (IllegalArgumentException e) {
107             assertEquals(
108                     "Node (foo?revision=2016-05-17)task[{(foo?revision=2016-05-17)task-id=123}] is missing mandatory "
109                             + "descendant /(foo?revision=2016-05-17)task-data/mandatory-data", e.getMessage());
110         }
111         testMandatoryDataLeafIsPresent(schemaContext);
112     }
113
114     private static void testMultipleContainers() throws DataValidationFailedException {
115         final EffectiveModelContext schemaContext = TestModel.createTestContext("/bug-5830/foo-multiple.yang");
116         assertNotNull("Schema context must not be null.", schemaContext);
117
118         testContainerIsNotPresent(schemaContext);
119
120         try {
121             testContainerIsPresent(schemaContext);
122             fail("Should fail due to missing mandatory node under present presence container.");
123         } catch (IllegalArgumentException e) {
124             assertTrue(e.getMessage().startsWith(
125                     "Node (foo?revision=2016-05-17)task-data is missing mandatory descendant"));
126         }
127
128         try {
129             testMandatoryDataLeafIsPresent(schemaContext);
130             fail("Should fail due to missing mandatory node under present presence container.");
131         } catch (IllegalArgumentException e) {
132             assertEquals("Node (foo?revision=2016-05-17)task-data "
133                     + "is missing mandatory descendant /(foo?revision=2016-05-17)non-presence-container/"
134                     + "non-presence-container-2/mandatory-leaf-2", e.getMessage());
135         }
136
137         testMandatoryLeaf2IsPresent(schemaContext, false);
138
139         try {
140             testMandatoryLeaf2IsPresent(schemaContext, true);
141             fail("Should fail due to missing mandatory node under present presence container.");
142         } catch (IllegalArgumentException e) {
143             assertEquals(
144                     "Node (foo?revision=2016-05-17)presence-container-2 is missing mandatory "
145                             + "descendant /(foo?revision=2016-05-17)mandatory-leaf-3", e.getMessage());
146         }
147     }
148
149     private static void testContainerIsNotPresent(final EffectiveModelContext schemaContext)
150             throws DataValidationFailedException {
151         final DataTree inMemoryDataTree = initDataTree(schemaContext);
152         final MapEntryNode taskEntryNode = Builders.mapEntryBuilder()
153                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(TASK, ImmutableMap.of(TASK_ID, "123")))
154                 .withChild(ImmutableNodes.leafNode(TASK_ID, "123"))
155                 .withChild(ImmutableNodes.leafNode(TASK_MANDATORY_LEAF, "mandatory data")).build();
156
157         final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
158         modificationTree.write(
159                 YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK)
160                         .node(NodeIdentifierWithPredicates.of(TASK, ImmutableMap.of(TASK_ID, "123"))), taskEntryNode);
161         modificationTree.ready();
162
163         inMemoryDataTree.validate(modificationTree);
164         final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
165         inMemoryDataTree.commit(prepare);
166     }
167
168     private static void testContainerIsPresent(final EffectiveModelContext schemaContext)
169             throws DataValidationFailedException {
170         final DataTree inMemoryDataTree = initDataTree(schemaContext);
171
172         final MapEntryNode taskEntryNode = Builders.mapEntryBuilder()
173                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(TASK, ImmutableMap.of(TASK_ID, "123")))
174                 .withChild(ImmutableNodes.leafNode(TASK_ID, "123"))
175                 .withChild(ImmutableNodes.leafNode(TASK_MANDATORY_LEAF, "mandatory data"))
176                 .withChild(createTaskDataContainer(false)).build();
177
178         final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
179         modificationTree.write(
180                 YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK)
181                         .node(NodeIdentifierWithPredicates.of(TASK, ImmutableMap.of(TASK_ID, "123"))), taskEntryNode);
182         modificationTree.ready();
183
184         inMemoryDataTree.validate(modificationTree);
185         final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
186         inMemoryDataTree.commit(prepare);
187     }
188
189     private static void testMandatoryDataLeafIsPresent(final EffectiveModelContext schemaContext)
190             throws DataValidationFailedException {
191         final DataTree inMemoryDataTree = initDataTree(schemaContext);
192
193         final MapEntryNode taskEntryNode = Builders.mapEntryBuilder()
194                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(TASK, ImmutableMap.of(TASK_ID, "123")))
195                 .withChild(ImmutableNodes.leafNode(TASK_ID, "123"))
196                 .withChild(ImmutableNodes.leafNode(TASK_MANDATORY_LEAF, "mandatory data"))
197                 .withChild(createTaskDataContainer(true)).build();
198
199         final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
200         modificationTree.write(
201                 YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK)
202                         .node(NodeIdentifierWithPredicates.of(TASK, ImmutableMap.of(TASK_ID, "123"))), taskEntryNode);
203         modificationTree.ready();
204
205         inMemoryDataTree.validate(modificationTree);
206         final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
207         inMemoryDataTree.commit(prepare);
208     }
209
210     private static void testMandatoryLeaf2IsPresent(final EffectiveModelContext schemaContext,
211             final boolean withPresenceContianer) throws DataValidationFailedException {
212         final DataTree inMemoryDataTree = initDataTree(schemaContext);
213
214         final MapEntryNode taskEntryNode = Builders.mapEntryBuilder()
215                 .withNodeIdentifier(NodeIdentifierWithPredicates.of(TASK, ImmutableMap.of(TASK_ID, "123")))
216                 .withChild(ImmutableNodes.leafNode(TASK_ID, "123"))
217                 .withChild(ImmutableNodes.leafNode(TASK_MANDATORY_LEAF, "mandatory data"))
218                 .withChild(createTaskDataMultipleContainer(withPresenceContianer)).build();
219
220         final DataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
221         modificationTree.write(
222                 YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK)
223                         .node(NodeIdentifierWithPredicates.of(TASK, ImmutableMap.of(TASK_ID, "123"))), taskEntryNode);
224         modificationTree.ready();
225
226         inMemoryDataTree.validate(modificationTree);
227         final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
228         inMemoryDataTree.commit(prepare);
229     }
230
231     private static DataContainerChild createTaskDataContainer(final boolean withMandatoryNode) {
232         DataContainerNodeBuilder<NodeIdentifier, ContainerNode> taskDataBuilder = Builders.containerBuilder()
233                 .withNodeIdentifier(new NodeIdentifier(TASK_DATA))
234                 .withChild(ImmutableNodes.leafNode(OTHER_DATA, "foo"));
235         if (withMandatoryNode) {
236             taskDataBuilder.withChild(ImmutableNodes.leafNode(MANDATORY_DATA, "mandatory-data-value"));
237         }
238         return taskDataBuilder.build();
239     }
240
241     private static DataContainerChild createTaskDataMultipleContainer(final boolean withPresenceContianer) {
242         DataContainerNodeBuilder<NodeIdentifier, ContainerNode> nonPresenceContainerBuilder = Builders
243                 .containerBuilder()
244                 .withNodeIdentifier(new NodeIdentifier(NON_PRESENCE_CONTAINER))
245                 .withChild(
246                         Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(NON_PRESENCE_CONTAINER_2))
247                                 .withChild(ImmutableNodes.leafNode(MANDATORY_LEAF_2, "mandatory leaf data 2")).build());
248
249         if (withPresenceContianer) {
250             nonPresenceContainerBuilder.withChild(Builders.containerBuilder()
251                     .withNodeIdentifier(new NodeIdentifier(PRESENCE_CONTAINER_2)).build());
252         }
253
254         DataContainerNodeBuilder<NodeIdentifier, ContainerNode> taskDataBuilder = Builders.containerBuilder()
255                 .withNodeIdentifier(new NodeIdentifier(TASK_DATA))
256                 .withChild(ImmutableNodes.leafNode(OTHER_DATA, "foo"));
257         taskDataBuilder.withChild(ImmutableNodes.leafNode(MANDATORY_DATA, "mandatory-data-value"));
258         taskDataBuilder.withChild(nonPresenceContainerBuilder.build());
259
260         return taskDataBuilder.build();
261     }
262 }