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.AnydataSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
30 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.Module;
34 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
35 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
36 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
37 import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition;
38 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
39 import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
40 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
42 public class DeviationResolutionTest {
45 public void testDeviateNotSupported() throws Exception {
46 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
47 "/deviation-resolution-test/deviation-not-supported");
48 assertNotNull(schemaContext);
50 final Module importedModule = schemaContext.findModule("imported", Revision.of("2017-01-20")).get();
51 final ContainerSchemaNode myContA = (ContainerSchemaNode) importedModule.getDataChildByName(
52 QName.create(importedModule.getQNameModule(), "my-cont-a"));
53 assertNotNull(myContA);
55 assertEquals(1, myContA.getChildNodes().size());
56 assertNotNull(myContA.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-a3")));
58 final ContainerSchemaNode myContB = (ContainerSchemaNode) importedModule.getDataChildByName(
59 QName.create(importedModule.getQNameModule(), "my-cont-b"));
62 final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
63 QName.create(importedModule.getQNameModule(), "my-cont-c"));
64 assertNotNull(myContC);
66 assertEquals(2, myContC.getChildNodes().size());
67 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
68 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
72 public void testDeviateAdd() throws Exception {
73 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
74 sourceForResource("/deviation-resolution-test/deviation-add/foo.yang"),
75 sourceForResource("/deviation-resolution-test/deviation-add/bar.yang"));
76 assertNotNull(schemaContext);
78 final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
79 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
80 QName.create(barModule.getQNameModule(), "my-leaf-list"));
81 assertNotNull(myLeafList);
83 assertFalse(myLeafList.isConfiguration());
84 assertEquals(3, myLeafList.getDefaults().size());
86 final ElementCountConstraint constraint = myLeafList.getElementCountConstraint().get();
87 assertEquals(10, constraint.getMaxElements().intValue());
88 assertEquals(5, constraint.getMinElements().intValue());
89 assertNotNull(myLeafList.getType().getUnits());
91 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
92 QName.create(barModule.getQNameModule(), "my-list"));
93 assertNotNull(myList);
94 assertEquals(2, myList.getUniqueConstraints().size());
96 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
97 QName.create(barModule.getQNameModule(), "my-choice"));
98 assertNotNull(myChoice);
99 assertEquals("c2", myChoice.getDefaultCase().get().getQName().getLocalName());
101 final RpcDefinition myRpc = barModule.getRpcs().iterator().next();
102 final ContainerSchemaNode input = myRpc.getInput();
103 assertEquals(2, input.getMustConstraints().size());
104 final ContainerSchemaNode output = myRpc.getOutput();
105 assertEquals(2, output.getMustConstraints().size());
107 final NotificationDefinition myNotification = barModule.getNotifications().iterator().next();
108 assertEquals(2, myNotification.getMustConstraints().size());
110 final AnyxmlSchemaNode myAnyxml = (AnyxmlSchemaNode) barModule.getDataChildByName(
111 QName.create(barModule.getQNameModule(), "my-anyxml"));
112 assertNotNull(myAnyxml);
113 assertTrue(myAnyxml.isMandatory());
114 assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
116 final AnydataSchemaNode myAnyData = (AnydataSchemaNode) barModule.findDataChildByName(
117 QName.create(barModule.getQNameModule(), "my-anydata")).orElse(null);
118 assertNotNull(myAnyData);
119 assertTrue(myAnyData.isMandatory());
120 assertEquals(2, myAnyData.getUnknownSchemaNodes().size());
124 public void testDeviateReplace() throws Exception {
125 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
126 sourceForResource("/deviation-resolution-test/deviation-replace/foo.yang"),
127 sourceForResource("/deviation-resolution-test/deviation-replace/bar.yang"));
128 assertNotNull(schemaContext);
130 final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
131 assertNotNull(barModule);
133 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
134 QName.create(barModule.getQNameModule(), "my-leaf"));
135 assertNotNull(myLeaf);
137 assertTrue(myLeaf.getType() instanceof Uint32TypeDefinition);
138 assertEquals(Optional.of("bytes"), myLeaf.getType().getUnits());
139 assertEquals(Optional.of("10"), myLeaf.getType().getDefaultValue());
141 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
142 QName.create(barModule.getQNameModule(), "my-leaf-list-test"));
143 assertNotNull(myLeafList);
145 final ElementCountConstraint constraint = myLeafList.getElementCountConstraint().get();
146 assertEquals(6, constraint.getMaxElements().intValue());
147 assertEquals(3, constraint.getMinElements().intValue());
148 assertTrue(myLeafList.isConfiguration());
150 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
151 QName.create(barModule.getQNameModule(), "my-choice"));
152 assertNotNull(myChoice);
154 assertFalse(myChoice.isMandatory());
155 assertEquals(1, myChoice.getUnknownSchemaNodes().size());
156 assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
158 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
159 QName.create(barModule.getQNameModule(), "my-cont"));
160 assertNotNull(myCont);
162 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
163 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
164 assertNotNull(myAugLeaf);
165 assertTrue(myAugLeaf.getType() instanceof Uint32TypeDefinition);
166 assertEquals(Optional.of("seconds"), myAugLeaf.getType().getUnits());
167 assertEquals(Optional.of("new-def-val"), myAugLeaf.getType().getDefaultValue());
168 assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
169 assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
171 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
172 QName.create(barModule.getQNameModule(), "my-used-leaf"));
173 assertNotNull(myUsedLeaf);
174 assertTrue(myUsedLeaf.getType() instanceof Uint32TypeDefinition);
175 assertEquals(Optional.of("weeks"), myUsedLeaf.getType().getUnits());
176 assertEquals(Optional.of("new-def-val"), myUsedLeaf.getType().getDefaultValue());
177 assertEquals(1, myUsedLeaf.getUnknownSchemaNodes().size());
178 assertEquals("new arg", myUsedLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
182 public void testDeviateDelete() throws Exception {
183 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
184 sourceForResource("/deviation-resolution-test/deviation-delete/foo.yang"),
185 sourceForResource("/deviation-resolution-test/deviation-delete/bar.yang"));
186 assertNotNull(schemaContext);
188 final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
189 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
190 QName.create(barModule.getQNameModule(), "my-leaf"));
191 assertNotNull(myLeaf);
193 assertEquals(Optional.empty(), myLeaf.getType().getDefaultValue());
194 assertEquals(Optional.empty(), myLeaf.getType().getUnits());
195 assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
197 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
198 QName.create(barModule.getQNameModule(), "my-leaf-list"));
199 assertNotNull(myLeafList);
201 assertEquals(0, myLeafList.getDefaults().size());
202 assertEquals(0, myLeafList.getMustConstraints().size());
204 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
205 QName.create(barModule.getQNameModule(), "my-list"));
206 assertNotNull(myList);
208 assertEquals(0, myList.getUniqueConstraints().size());
209 assertEquals(0, myList.getUnknownSchemaNodes().size());
211 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
212 QName.create(barModule.getQNameModule(), "my-cont"));
213 assertNotNull(myCont);
215 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
216 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
217 assertNotNull(myAugLeaf);
218 assertEquals(Optional.empty(), myAugLeaf.getType().getDefaultValue());
219 assertEquals(Optional.empty(), myAugLeaf.getType().getUnits());
220 assertEquals(0, myAugLeaf.getMustConstraints().size());
221 assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
223 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
224 QName.create(barModule.getQNameModule(), "my-used-leaf"));
225 assertNotNull(myUsedLeaf);
226 assertEquals(Optional.empty(), myUsedLeaf.getType().getDefaultValue());
227 assertEquals(Optional.empty(), myUsedLeaf.getType().getUnits());
228 assertEquals(0, myUsedLeaf.getMustConstraints().size());
229 assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
233 public void shouldFailOnInvalidYang10Model() throws Exception {
235 StmtTestUtils.parseYangSources(
236 sourceForResource("/deviation-resolution-test/deviation-add/foo10-invalid.yang"),
237 sourceForResource("/deviation-resolution-test/deviation-add/bar10-invalid.yang"));
238 fail("An exception should have been thrown.");
239 } catch (final ReactorException ex) {
240 final Throwable cause = ex.getCause();
241 assertTrue(cause instanceof InvalidSubstatementException);
242 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
247 public void shouldFailOnInvalidYang10Model2() throws Exception {
249 StmtTestUtils.parseYangSources(
250 sourceForResource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang"),
251 sourceForResource("/deviation-resolution-test/deviation-delete/bar10-invalid.yang"));
252 fail("An exception should have been thrown.");
253 } catch (final ReactorException ex) {
254 final Throwable cause = ex.getCause();
255 assertTrue(cause instanceof InvalidSubstatementException);
256 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
261 public void shouldFailOnInvalidDeviationTarget() throws Exception {
263 StmtTestUtils.parseYangSources(sourceForResource(
264 "/deviation-resolution-test/foo-invalid-deviation-target.yang"),
265 sourceForResource("/deviation-resolution-test/bar.yang"));
266 fail("An exception should have been thrown.");
267 } catch (final ReactorException ex) {
268 final Throwable cause = ex.getCause();
269 assertTrue(cause instanceof InferenceException);
270 assertTrue(cause.getMessage().startsWith("(bar?revision=2017-01-20)my-cont is not a valid deviation "
271 + "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
276 public void shouldFailOnInvalidDeviationPath() throws Exception {
278 StmtTestUtils.parseYangSources(
279 sourceForResource("/deviation-resolution-test/foo-invalid-deviation-path.yang"),
280 sourceForResource("/deviation-resolution-test/bar.yang"));
281 fail("An exception should have been thrown.");
282 } catch (final ReactorException ex) {
283 final Throwable cause = ex.getCause().getCause();
284 assertTrue(cause instanceof InferenceException);
285 assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(bar?revision=2017-01-20)"
286 + "invalid, (bar?revision=2017-01-20)path]}' not found"));
291 public void shouldFailOnInvalidDeviateAdd() throws Exception {
293 StmtTestUtils.parseYangSources(
294 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid.yang"),
295 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid.yang"));
296 fail("An exception should have been thrown.");
297 } catch (final ReactorException ex) {
298 final Throwable cause = ex.getCause();
299 assertTrue(cause instanceof InferenceException);
300 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
301 + ":yin:1)config to target node (bar?revision=2017-01-20)my-leaf because it is already defined in"
302 + " target and can appear only once."));
307 public void shouldFailOnInvalidDeviateAdd2() throws Exception {
309 StmtTestUtils.parseYangSources(
310 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang"),
311 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-2.yang"));
312 fail("An exception should have been thrown.");
313 } catch (final ReactorException ex) {
314 final Throwable cause = ex.getCause();
315 assertTrue(cause instanceof InferenceException);
316 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
317 + ":yin:1)default to target node (bar?revision=2017-01-20)my-leaf because it is already defined in"
318 + " target and can appear only once."));
323 public void shouldFailOnInvalidDeviateAdd3() throws Exception {
325 StmtTestUtils.parseYangSources(
326 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-4.yang"),
327 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-4.yang"));
328 fail("An exception should have been thrown.");
329 } catch (final ReactorException ex) {
330 final Throwable cause = ex.getCause();
331 assertTrue(cause instanceof InferenceException);
332 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
333 + ":yin:1)default to target node (bar?revision=2017-02-01)my-used-leaf because it is already "
334 + "defined in target and can appear only once."));
339 public void shouldFailOnInvalidDeviateReplace() throws Exception {
341 StmtTestUtils.parseYangSources(
342 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid.yang"),
343 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid.yang"));
344 fail("An exception should have been thrown.");
345 } catch (final ReactorException ex) {
346 final Throwable cause = ex.getCause();
347 assertTrue(cause instanceof InferenceException);
348 assertTrue(cause.getMessage().startsWith("Deviation cannot replace substatement "
349 + "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (bar?revision=2017-01-20)my-leaf "
350 + "because it does not exist in target node."));
355 @SuppressWarnings("checkstyle:regexpSinglelineJava")
356 public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
357 final PrintStream stdout = System.out;
358 final ByteArrayOutputStream output = new ByteArrayOutputStream();
359 final String testLog;
361 System.setOut(new PrintStream(output, true, "UTF-8"));
363 StmtTestUtils.parseYangSources(
364 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang"),
365 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-2.yang"));
367 testLog = output.toString();
368 System.setOut(stdout);
369 assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default"
370 + " in target leaf-list (bar?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple "
371 + "default statements."));
375 @SuppressWarnings("checkstyle:regexpSinglelineJava")
376 public void shouldLogInvalidDeviateDeleteAttempt() throws Exception {
377 final PrintStream stdout = System.out;
378 final ByteArrayOutputStream output = new ByteArrayOutputStream();
379 final String testLog;
381 System.setOut(new PrintStream(output, true, "UTF-8"));
383 StmtTestUtils.parseYangSources(
384 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid.yang"),
385 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid.yang"));
387 testLog = output.toString();
388 System.setOut(stdout);
389 assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units "
390 + "with argument 'seconds' in target node (bar?revision=2017-01-20)my-leaf because it does not exist "
391 + "in the target node."));
395 public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
397 StmtTestUtils.parseYangSources(
398 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang"),
399 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-3.yang"));
400 fail("An exception should have been thrown.");
401 } catch (final ReactorException ex) {
402 final Throwable cause = ex.getCause();
403 assertTrue(cause instanceof InvalidSubstatementException);
404 assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
409 public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
411 StmtTestUtils.parseYangSources(
412 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang"),
413 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-3.yang"));
414 fail("An exception should have been thrown.");
415 } catch (final ReactorException ex) {
416 final Throwable cause = ex.getCause();
417 assertTrue(cause instanceof InvalidSubstatementException);
418 assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
423 public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
425 StmtTestUtils.parseYangSources(
426 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang"),
427 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid-2.yang"));
428 fail("An exception should have been thrown.");
429 } catch (final ReactorException ex) {
430 final Throwable cause = ex.getCause();
431 assertTrue(cause instanceof InvalidSubstatementException);
432 assertTrue(cause.getMessage().startsWith("CONFIG is not valid for DEVIATE."));