2 * Copyright (c) 2017 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
9 package org.opendaylight.yangtools.yang.stmt;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertFalse;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertNull;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17 import static org.opendaylight.yangtools.yang.stmt.StmtTestUtils.sourceForResource;
19 import java.io.ByteArrayOutputStream;
20 import java.io.PrintStream;
21 import java.util.Optional;
22 import org.junit.Test;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.common.Revision;
25 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
29 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.Module;
33 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
34 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
35 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
36 import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition;
37 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
38 import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
39 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
41 public class DeviationResolutionTest {
44 public void testDeviateNotSupported() throws Exception {
45 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
46 "/deviation-resolution-test/deviation-not-supported");
47 assertNotNull(schemaContext);
49 final Module importedModule = schemaContext.findModule("imported", Revision.of("2017-01-20")).get();
50 final ContainerSchemaNode myContA = (ContainerSchemaNode) importedModule.getDataChildByName(
51 QName.create(importedModule.getQNameModule(), "my-cont-a"));
52 assertNotNull(myContA);
54 assertEquals(1, myContA.getChildNodes().size());
55 assertNotNull(myContA.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-a3")));
57 final ContainerSchemaNode myContB = (ContainerSchemaNode) importedModule.getDataChildByName(
58 QName.create(importedModule.getQNameModule(), "my-cont-b"));
61 final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
62 QName.create(importedModule.getQNameModule(), "my-cont-c"));
63 assertNotNull(myContC);
65 assertEquals(2, myContC.getChildNodes().size());
66 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
67 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
71 public void testDeviateAdd() throws Exception {
72 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
73 sourceForResource("/deviation-resolution-test/deviation-add/foo.yang"),
74 sourceForResource("/deviation-resolution-test/deviation-add/bar.yang"));
75 assertNotNull(schemaContext);
77 final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
78 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
79 QName.create(barModule.getQNameModule(), "my-leaf-list"));
80 assertNotNull(myLeafList);
82 assertFalse(myLeafList.isConfiguration());
83 assertEquals(3, myLeafList.getDefaults().size());
85 final ElementCountConstraint constraint = myLeafList.getElementCountConstraint().get();
86 assertEquals(10, constraint.getMaxElements().intValue());
87 assertEquals(5, constraint.getMinElements().intValue());
88 assertNotNull(myLeafList.getType().getUnits());
90 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
91 QName.create(barModule.getQNameModule(), "my-list"));
92 assertNotNull(myList);
93 assertEquals(2, myList.getUniqueConstraints().size());
95 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
96 QName.create(barModule.getQNameModule(), "my-choice"));
97 assertNotNull(myChoice);
98 assertEquals("c2", myChoice.getDefaultCase().get().getQName().getLocalName());
100 final RpcDefinition myRpc = barModule.getRpcs().iterator().next();
101 final ContainerSchemaNode input = myRpc.getInput();
102 assertEquals(2, input.getMustConstraints().size());
103 final ContainerSchemaNode output = myRpc.getOutput();
104 assertEquals(2, output.getMustConstraints().size());
106 final NotificationDefinition myNotification = barModule.getNotifications().iterator().next();
107 assertEquals(2, myNotification.getMustConstraints().size());
109 final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) barModule.getDataChildByName(
110 QName.create(barModule.getQNameModule(), "my-anyxml"));
111 assertNotNull(myAnyxml);
112 assertTrue(myAnyxml.isMandatory());
113 assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
117 public void testDeviateReplace() throws Exception {
118 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
119 sourceForResource("/deviation-resolution-test/deviation-replace/foo.yang"),
120 sourceForResource("/deviation-resolution-test/deviation-replace/bar.yang"));
121 assertNotNull(schemaContext);
123 final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
124 assertNotNull(barModule);
126 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
127 QName.create(barModule.getQNameModule(), "my-leaf"));
128 assertNotNull(myLeaf);
130 assertTrue(myLeaf.getType() instanceof Uint32TypeDefinition);
131 assertEquals(Optional.of("bytes"), myLeaf.getType().getUnits());
132 assertEquals(Optional.of("10"), myLeaf.getType().getDefaultValue());
134 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
135 QName.create(barModule.getQNameModule(), "my-leaf-list-test"));
136 assertNotNull(myLeafList);
138 final ElementCountConstraint constraint = myLeafList.getElementCountConstraint().get();
139 assertEquals(6, constraint.getMaxElements().intValue());
140 assertEquals(3, constraint.getMinElements().intValue());
141 assertTrue(myLeafList.isConfiguration());
143 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
144 QName.create(barModule.getQNameModule(), "my-choice"));
145 assertNotNull(myChoice);
147 assertFalse(myChoice.isMandatory());
148 assertEquals(1, myChoice.getUnknownSchemaNodes().size());
149 assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
151 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
152 QName.create(barModule.getQNameModule(), "my-cont"));
153 assertNotNull(myCont);
155 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
156 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
157 assertNotNull(myAugLeaf);
158 assertTrue(myAugLeaf.getType() instanceof Uint32TypeDefinition);
159 assertEquals(Optional.of("seconds"), myAugLeaf.getType().getUnits());
160 assertEquals(Optional.of("new-def-val"), myAugLeaf.getType().getDefaultValue());
161 assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
162 assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
164 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
165 QName.create(barModule.getQNameModule(), "my-used-leaf"));
166 assertNotNull(myUsedLeaf);
167 assertTrue(myUsedLeaf.getType() instanceof Uint32TypeDefinition);
168 assertEquals(Optional.of("weeks"), myUsedLeaf.getType().getUnits());
169 assertEquals(Optional.of("new-def-val"), myUsedLeaf.getType().getDefaultValue());
170 assertEquals(1, myUsedLeaf.getUnknownSchemaNodes().size());
171 assertEquals("new arg", myUsedLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
175 public void testDeviateDelete() throws Exception {
176 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
177 sourceForResource("/deviation-resolution-test/deviation-delete/foo.yang"),
178 sourceForResource("/deviation-resolution-test/deviation-delete/bar.yang"));
179 assertNotNull(schemaContext);
181 final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
182 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
183 QName.create(barModule.getQNameModule(), "my-leaf"));
184 assertNotNull(myLeaf);
186 assertEquals(Optional.empty(), myLeaf.getType().getDefaultValue());
187 assertEquals(Optional.empty(), myLeaf.getType().getUnits());
188 assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
190 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
191 QName.create(barModule.getQNameModule(), "my-leaf-list"));
192 assertNotNull(myLeafList);
194 assertEquals(0, myLeafList.getDefaults().size());
195 assertEquals(0, myLeafList.getMustConstraints().size());
197 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
198 QName.create(barModule.getQNameModule(), "my-list"));
199 assertNotNull(myList);
201 assertEquals(0, myList.getUniqueConstraints().size());
202 assertEquals(0, myList.getUnknownSchemaNodes().size());
204 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
205 QName.create(barModule.getQNameModule(), "my-cont"));
206 assertNotNull(myCont);
208 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
209 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
210 assertNotNull(myAugLeaf);
211 assertEquals(Optional.empty(), myAugLeaf.getType().getDefaultValue());
212 assertEquals(Optional.empty(), myAugLeaf.getType().getUnits());
213 assertEquals(0, myAugLeaf.getMustConstraints().size());
214 assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
216 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
217 QName.create(barModule.getQNameModule(), "my-used-leaf"));
218 assertNotNull(myUsedLeaf);
219 assertEquals(Optional.empty(), myUsedLeaf.getType().getDefaultValue());
220 assertEquals(Optional.empty(), myUsedLeaf.getType().getUnits());
221 assertEquals(0, myUsedLeaf.getMustConstraints().size());
222 assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
226 public void shouldFailOnInvalidYang10Model() throws Exception {
228 StmtTestUtils.parseYangSources(
229 sourceForResource("/deviation-resolution-test/deviation-add/foo10-invalid.yang"),
230 sourceForResource("/deviation-resolution-test/deviation-add/bar10-invalid.yang"));
231 fail("An exception should have been thrown.");
232 } catch (final ReactorException ex) {
233 final Throwable cause = ex.getCause();
234 assertTrue(cause instanceof InvalidSubstatementException);
235 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
240 public void shouldFailOnInvalidYang10Model2() throws Exception {
242 StmtTestUtils.parseYangSources(
243 sourceForResource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang"),
244 sourceForResource("/deviation-resolution-test/deviation-delete/bar10-invalid.yang"));
245 fail("An exception should have been thrown.");
246 } catch (final ReactorException ex) {
247 final Throwable cause = ex.getCause();
248 assertTrue(cause instanceof InvalidSubstatementException);
249 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
254 public void shouldFailOnInvalidDeviationTarget() throws Exception {
256 StmtTestUtils.parseYangSources(sourceForResource(
257 "/deviation-resolution-test/foo-invalid-deviation-target.yang"),
258 sourceForResource("/deviation-resolution-test/bar.yang"));
259 fail("An exception should have been thrown.");
260 } catch (final ReactorException ex) {
261 final Throwable cause = ex.getCause();
262 assertTrue(cause instanceof InferenceException);
263 assertTrue(cause.getMessage().startsWith("(bar?revision=2017-01-20)my-cont is not a valid deviation "
264 + "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
269 public void shouldFailOnInvalidDeviationPath() throws Exception {
271 StmtTestUtils.parseYangSources(
272 sourceForResource("/deviation-resolution-test/foo-invalid-deviation-path.yang"),
273 sourceForResource("/deviation-resolution-test/bar.yang"));
274 fail("An exception should have been thrown.");
275 } catch (final ReactorException ex) {
276 final Throwable cause = ex.getCause().getCause();
277 assertTrue(cause instanceof InferenceException);
278 assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(bar?revision=2017-01-20)"
279 + "invalid, (bar?revision=2017-01-20)path]}' not found"));
284 public void shouldFailOnInvalidDeviateAdd() throws Exception {
286 StmtTestUtils.parseYangSources(
287 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid.yang"),
288 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid.yang"));
289 fail("An exception should have been thrown.");
290 } catch (final ReactorException ex) {
291 final Throwable cause = ex.getCause();
292 assertTrue(cause instanceof InferenceException);
293 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
294 + ":yin:1)config to target node (bar?revision=2017-01-20)my-leaf because it is already defined in"
295 + " target and can appear only once."));
300 public void shouldFailOnInvalidDeviateAdd2() throws Exception {
302 StmtTestUtils.parseYangSources(
303 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang"),
304 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-2.yang"));
305 fail("An exception should have been thrown.");
306 } catch (final ReactorException ex) {
307 final Throwable cause = ex.getCause();
308 assertTrue(cause instanceof InferenceException);
309 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
310 + ":yin:1)default to target node (bar?revision=2017-01-20)my-leaf because it is already defined in"
311 + " target and can appear only once."));
316 public void shouldFailOnInvalidDeviateAdd3() throws Exception {
318 StmtTestUtils.parseYangSources(
319 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-4.yang"),
320 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-4.yang"));
321 fail("An exception should have been thrown.");
322 } catch (final ReactorException ex) {
323 final Throwable cause = ex.getCause();
324 assertTrue(cause instanceof InferenceException);
325 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
326 + ":yin:1)default to target node (bar?revision=2017-02-01)my-used-leaf because it is already "
327 + "defined in target and can appear only once."));
332 public void shouldFailOnInvalidDeviateReplace() throws Exception {
334 StmtTestUtils.parseYangSources(
335 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid.yang"),
336 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid.yang"));
337 fail("An exception should have been thrown.");
338 } catch (final ReactorException ex) {
339 final Throwable cause = ex.getCause();
340 assertTrue(cause instanceof InferenceException);
341 assertTrue(cause.getMessage().startsWith("Deviation cannot replace substatement "
342 + "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (bar?revision=2017-01-20)my-leaf "
343 + "because it does not exist in target node."));
348 @SuppressWarnings("checkstyle:regexpSinglelineJava")
349 public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
350 final PrintStream stdout = System.out;
351 final ByteArrayOutputStream output = new ByteArrayOutputStream();
352 final String testLog;
354 System.setOut(new PrintStream(output, true, "UTF-8"));
356 StmtTestUtils.parseYangSources(
357 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang"),
358 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-2.yang"));
360 testLog = output.toString();
361 System.setOut(stdout);
362 assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default"
363 + " in target leaf-list (bar?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple "
364 + "default statements."));
368 @SuppressWarnings("checkstyle:regexpSinglelineJava")
369 public void shouldLogInvalidDeviateDeleteAttempt() throws Exception {
370 final PrintStream stdout = System.out;
371 final ByteArrayOutputStream output = new ByteArrayOutputStream();
372 final String testLog;
374 System.setOut(new PrintStream(output, true, "UTF-8"));
376 StmtTestUtils.parseYangSources(
377 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid.yang"),
378 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid.yang"));
380 testLog = output.toString();
381 System.setOut(stdout);
382 assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units "
383 + "with argument 'seconds' in target node (bar?revision=2017-01-20)my-leaf because it does not exist "
384 + "in the target node."));
388 public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
390 StmtTestUtils.parseYangSources(
391 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang"),
392 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-3.yang"));
393 fail("An exception should have been thrown.");
394 } catch (final ReactorException ex) {
395 final Throwable cause = ex.getCause();
396 assertTrue(cause instanceof InvalidSubstatementException);
397 assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
402 public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
404 StmtTestUtils.parseYangSources(
405 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang"),
406 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-3.yang"));
407 fail("An exception should have been thrown.");
408 } catch (final ReactorException ex) {
409 final Throwable cause = ex.getCause();
410 assertTrue(cause instanceof InvalidSubstatementException);
411 assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
416 public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
418 StmtTestUtils.parseYangSources(
419 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang"),
420 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid-2.yang"));
421 fail("An exception should have been thrown.");
422 } catch (final ReactorException ex) {
423 final Throwable cause = ex.getCause();
424 assertTrue(cause instanceof InvalidSubstatementException);
425 assertTrue(cause.getMessage().startsWith("CONFIG is not valid for DEVIATE."));