2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
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;
15 import org.junit.Test;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
20 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
22 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
25 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
26 import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
27 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
28 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
29 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
30 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
33 public class Bug5830Test {
34 private static final String NS = "foo";
35 private static final String REV = "2016-05-17";
36 private static final QName TASK_CONTAINER = QName.create(NS, REV, "task-container");
37 private static final QName TASK = QName.create(NS, REV, "task");
38 private static final QName TASK_ID = QName.create(NS, REV, "task-id");
39 private static final QName TASK_DATA = QName.create(NS, REV, "task-data");
40 private static final QName OTHER_DATA = QName.create(NS, REV, "other-data");
41 private static final QName MANDATORY_DATA = QName.create(NS, REV, "mandatory-data");
42 private static final QName TASK_MANDATORY_LEAF = QName.create(NS, REV, "task-mandatory-leaf");
43 private static final QName NON_PRESENCE_CONTAINER = QName.create(NS, REV, "non-presence-container");
44 private static final QName NON_PRESENCE_CONTAINER_2 = QName.create(NS, REV, "non-presence-container-2");
45 private static final QName PRESENCE_CONTAINER_2 = QName.create(NS, REV, "presence-container-2");
46 private static final QName MANDATORY_LEAF_2 = QName.create(NS, REV, "mandatory-leaf-2");
48 private static InMemoryDataTree initDataTree(final SchemaContext schemaContext)
49 throws DataValidationFailedException {
50 final InMemoryDataTree inMemoryDataTree = (InMemoryDataTree) InMemoryDataTreeFactory.getInstance().create(
51 TreeType.CONFIGURATION);
52 inMemoryDataTree.setSchemaContext(schemaContext);
54 final MapNode taskNode = Builders.mapBuilder().withNodeIdentifier(new NodeIdentifier(TASK)).build();
55 final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
56 modificationTree.write(YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK), taskNode);
57 modificationTree.ready();
59 inMemoryDataTree.validate(modificationTree);
60 final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
61 inMemoryDataTree.commit(prepare);
62 return inMemoryDataTree;
66 public void testMandatoryNodes() throws ReactorException, DataValidationFailedException {
67 testPresenceContainer();
68 testNonPresenceContainer();
69 testMultipleContainers();
72 private static void testPresenceContainer() throws ReactorException, DataValidationFailedException {
73 final SchemaContext schemaContext = TestModel.createTestContext("/bug5830/foo-presence.yang");
74 assertNotNull("Schema context must not be null.", schemaContext);
76 testContainerIsNotPresent(schemaContext);
78 testContainerIsPresent(schemaContext);
79 fail("Should fail due to missing mandatory node under present presence container.");
80 } catch (final IllegalArgumentException e) {
82 "Node (foo?revision=2016-05-17)task-data is missing mandatory descendant /(foo?revision=2016-05-17)"
83 + "mandatory-data", e.getMessage());
85 testMandatoryDataLeafIsPresent(schemaContext);
88 private static void testNonPresenceContainer() throws ReactorException, DataValidationFailedException {
89 final SchemaContext schemaContext = TestModel.createTestContext("/bug5830/foo-non-presence.yang");
90 assertNotNull("Schema context must not be null.", schemaContext);
93 testContainerIsNotPresent(schemaContext);
94 fail("Should fail due to missing mandatory node.");
95 } catch (final IllegalArgumentException e) {
97 "Node (foo?revision=2016-05-17)task[{(foo?revision=2016-05-17)task-id=123}] is missing mandatory "
98 + "descendant /(foo?revision=2016-05-17)task-data/mandatory-data", e.getMessage());
102 testContainerIsPresent(schemaContext);
103 fail("Should fail due to missing mandatory node.");
104 } catch (final IllegalArgumentException e) {
106 "Node (foo?revision=2016-05-17)task[{(foo?revision=2016-05-17)task-id=123}] is missing mandatory "
107 + "descendant /(foo?revision=2016-05-17)task-data/mandatory-data", e.getMessage());
109 testMandatoryDataLeafIsPresent(schemaContext);
112 private static void testMultipleContainers() throws ReactorException, DataValidationFailedException {
113 final SchemaContext schemaContext = TestModel.createTestContext("/bug5830/foo-multiple.yang");
114 assertNotNull("Schema context must not be null.", schemaContext);
116 testContainerIsNotPresent(schemaContext);
119 testContainerIsPresent(schemaContext);
120 fail("Should fail due to missing mandatory node under present presence container.");
121 } catch (final IllegalArgumentException e) {
122 assertTrue(e.getMessage().startsWith(
123 "Node (foo?revision=2016-05-17)task-data is missing mandatory descendant"));
127 testMandatoryDataLeafIsPresent(schemaContext);
128 fail("Should fail due to missing mandatory node under present presence container.");
129 } catch (final IllegalArgumentException e) {
130 assertEquals("Node (foo?revision=2016-05-17)task-data "
131 + "is missing mandatory descendant /(foo?revision=2016-05-17)non-presence-container/"
132 + "non-presence-container-2/mandatory-leaf-2", e.getMessage());
135 testMandatoryLeaf2IsPresent(schemaContext, false);
138 testMandatoryLeaf2IsPresent(schemaContext, true);
139 fail("Should fail due to missing mandatory node under present presence container.");
140 } catch (final IllegalArgumentException e) {
141 assertEquals("Node (foo?revision=2016-05-17)presence-container-2 is missing mandatory "
142 + "descendant /(foo?revision=2016-05-17)mandatory-leaf-3", e.getMessage());
146 private static void testContainerIsNotPresent(final SchemaContext schemaContext)
147 throws DataValidationFailedException {
148 final InMemoryDataTree inMemoryDataTree = initDataTree(schemaContext);
149 final MapEntryNode taskEntryNode = Builders.mapEntryBuilder()
150 .withNodeIdentifier(new NodeIdentifierWithPredicates(TASK, TASK_ID, "123"))
151 .withChild(ImmutableNodes.leafNode(TASK_ID, "123"))
152 .withChild(ImmutableNodes.leafNode(TASK_MANDATORY_LEAF, "mandatory data")).build();
154 final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
155 modificationTree.write(
156 YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK)
157 .node(new NodeIdentifierWithPredicates(TASK, TASK_ID, "123")), taskEntryNode);
158 modificationTree.ready();
160 inMemoryDataTree.validate(modificationTree);
161 final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
162 inMemoryDataTree.commit(prepare);
165 private static void testContainerIsPresent(final SchemaContext schemaContext) throws DataValidationFailedException {
166 final InMemoryDataTree inMemoryDataTree = initDataTree(schemaContext);
168 final MapEntryNode taskEntryNode = Builders.mapEntryBuilder()
169 .withNodeIdentifier(new NodeIdentifierWithPredicates(TASK, TASK_ID, "123"))
170 .withChild(ImmutableNodes.leafNode(TASK_ID, "123"))
171 .withChild(ImmutableNodes.leafNode(TASK_MANDATORY_LEAF, "mandatory data"))
172 .withChild(createTaskDataContainer(false)).build();
174 final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
175 modificationTree.write(
176 YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK)
177 .node(new NodeIdentifierWithPredicates(TASK, TASK_ID, "123")), taskEntryNode);
178 modificationTree.ready();
180 inMemoryDataTree.validate(modificationTree);
181 final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
182 inMemoryDataTree.commit(prepare);
185 private static void testMandatoryDataLeafIsPresent(final SchemaContext schemaContext)
186 throws DataValidationFailedException {
187 final InMemoryDataTree inMemoryDataTree = initDataTree(schemaContext);
189 final MapEntryNode taskEntryNode = Builders.mapEntryBuilder()
190 .withNodeIdentifier(new NodeIdentifierWithPredicates(TASK, TASK_ID, "123"))
191 .withChild(ImmutableNodes.leafNode(TASK_ID, "123"))
192 .withChild(ImmutableNodes.leafNode(TASK_MANDATORY_LEAF, "mandatory data"))
193 .withChild(createTaskDataContainer(true)).build();
195 final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
196 modificationTree.write(
197 YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK)
198 .node(new NodeIdentifierWithPredicates(TASK, TASK_ID, "123")), taskEntryNode);
199 modificationTree.ready();
201 inMemoryDataTree.validate(modificationTree);
202 final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
203 inMemoryDataTree.commit(prepare);
206 private static void testMandatoryLeaf2IsPresent(final SchemaContext schemaContext, final boolean withPresenceContianer)
207 throws DataValidationFailedException {
208 final InMemoryDataTree inMemoryDataTree = initDataTree(schemaContext);
210 final MapEntryNode taskEntryNode = Builders.mapEntryBuilder()
211 .withNodeIdentifier(new NodeIdentifierWithPredicates(TASK, TASK_ID, "123"))
212 .withChild(ImmutableNodes.leafNode(TASK_ID, "123"))
213 .withChild(ImmutableNodes.leafNode(TASK_MANDATORY_LEAF, "mandatory data"))
214 .withChild(createTaskDataMultipleContainer(withPresenceContianer)).build();
216 final InMemoryDataTreeModification modificationTree = inMemoryDataTree.takeSnapshot().newModification();
217 modificationTree.write(
218 YangInstanceIdentifier.of(TASK_CONTAINER).node(TASK)
219 .node(new NodeIdentifierWithPredicates(TASK, TASK_ID, "123")), taskEntryNode);
220 modificationTree.ready();
222 inMemoryDataTree.validate(modificationTree);
223 final DataTreeCandidate prepare = inMemoryDataTree.prepare(modificationTree);
224 inMemoryDataTree.commit(prepare);
227 private static DataContainerChild<?, ?> createTaskDataContainer(final boolean withMandatoryNode) {
228 final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> taskDataBuilder = Builders.containerBuilder()
229 .withNodeIdentifier(new NodeIdentifier(TASK_DATA))
230 .withChild(ImmutableNodes.leafNode(OTHER_DATA, "foo"));
231 if (withMandatoryNode) {
232 taskDataBuilder.withChild(ImmutableNodes.leafNode(MANDATORY_DATA, "mandatory-data-value"));
234 return taskDataBuilder.build();
237 private static DataContainerChild<?, ?> createTaskDataMultipleContainer(final boolean withPresenceContianer) {
238 final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> nonPresenceContainerBuilder = Builders
240 .withNodeIdentifier(new NodeIdentifier(NON_PRESENCE_CONTAINER))
242 Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(NON_PRESENCE_CONTAINER_2))
243 .withChild(ImmutableNodes.leafNode(MANDATORY_LEAF_2, "mandatory leaf data 2")).build());
245 if (withPresenceContianer) {
246 nonPresenceContainerBuilder.withChild(Builders.containerBuilder()
247 .withNodeIdentifier(new NodeIdentifier(PRESENCE_CONTAINER_2)).build());
250 final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> taskDataBuilder = Builders.containerBuilder()
251 .withNodeIdentifier(new NodeIdentifier(TASK_DATA))
252 .withChild(ImmutableNodes.leafNode(OTHER_DATA, "foo"));
253 taskDataBuilder.withChild(ImmutableNodes.leafNode(MANDATORY_DATA, "mandatory-data-value"));
254 taskDataBuilder.withChild(nonPresenceContainerBuilder.build());
256 return taskDataBuilder.build();