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