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 org.junit.Test;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.Module;
30 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
31 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
32 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
38 public class DeviationResolutionTest {
41 public void testDeviateNotSupported() throws Exception {
42 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
43 "/deviation-resolution-test/deviation-not-supported");
44 assertNotNull(schemaContext);
46 final Module importedModule = schemaContext.findModule("imported", QName.parseRevision("2017-01-20")).get();
47 final ContainerSchemaNode myContA = (ContainerSchemaNode) importedModule.getDataChildByName(
48 QName.create(importedModule.getQNameModule(), "my-cont-a"));
49 assertNotNull(myContA);
51 assertEquals(1, myContA.getChildNodes().size());
52 assertNotNull(myContA.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-a3")));
54 final ContainerSchemaNode myContB = (ContainerSchemaNode) importedModule.getDataChildByName(
55 QName.create(importedModule.getQNameModule(), "my-cont-b"));
58 final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
59 QName.create(importedModule.getQNameModule(), "my-cont-c"));
60 assertNotNull(myContC);
62 assertEquals(2, myContC.getChildNodes().size());
63 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
64 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
68 public void testDeviateAdd() throws Exception {
69 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
70 sourceForResource("/deviation-resolution-test/deviation-add/foo.yang"),
71 sourceForResource("/deviation-resolution-test/deviation-add/bar.yang"));
72 assertNotNull(schemaContext);
74 final Module barModule = schemaContext.findModule("bar", QName.parseRevision("2017-01-20")).get();
75 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
76 QName.create(barModule.getQNameModule(), "my-leaf-list"));
77 assertNotNull(myLeafList);
79 assertFalse(myLeafList.isConfiguration());
80 assertEquals(3, myLeafList.getDefaults().size());
81 assertEquals(10, myLeafList.getConstraints().getMaxElements().intValue());
82 assertEquals(5, myLeafList.getConstraints().getMinElements().intValue());
83 assertNotNull(myLeafList.getType().getUnits());
85 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
86 QName.create(barModule.getQNameModule(), "my-list"));
87 assertNotNull(myList);
88 assertEquals(2, myList.getUniqueConstraints().size());
90 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
91 QName.create(barModule.getQNameModule(), "my-choice"));
92 assertNotNull(myChoice);
93 assertEquals("c2", myChoice.getDefaultCase());
95 final RpcDefinition myRpc = barModule.getRpcs().iterator().next();
96 final ContainerSchemaNode input = myRpc.getInput();
97 assertEquals(2, input.getConstraints().getMustConstraints().size());
98 final ContainerSchemaNode output = myRpc.getOutput();
99 assertEquals(2, output.getConstraints().getMustConstraints().size());
101 final NotificationDefinition myNotification = barModule.getNotifications().iterator().next();
102 assertEquals(2, myNotification.getConstraints().getMustConstraints().size());
104 final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) barModule.getDataChildByName(
105 QName.create(barModule.getQNameModule(), "my-anyxml"));
106 assertNotNull(myAnyxml);
107 assertTrue(myAnyxml.getConstraints().isMandatory());
108 assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
112 public void testDeviateReplace() throws Exception {
113 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
114 sourceForResource("/deviation-resolution-test/deviation-replace/foo.yang"),
115 sourceForResource("/deviation-resolution-test/deviation-replace/bar.yang"));
116 assertNotNull(schemaContext);
118 final Module barModule = schemaContext.findModule("bar", QName.parseRevision("2017-01-20")).get();
119 assertNotNull(barModule);
121 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
122 QName.create(barModule.getQNameModule(), "my-leaf"));
123 assertNotNull(myLeaf);
125 assertTrue(myLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
126 assertNotNull(myLeaf.getUnits());
127 assertEquals("bytes", myLeaf.getUnits());
128 assertNotNull(myLeaf.getDefault());
129 assertEquals("10", myLeaf.getDefault());
131 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
132 QName.create(barModule.getQNameModule(), "my-leaf-list-test"));
133 assertNotNull(myLeafList);
135 assertEquals(6, myLeafList.getConstraints().getMaxElements().intValue());
136 assertEquals(3, myLeafList.getConstraints().getMinElements().intValue());
137 assertTrue(myLeafList.isConfiguration());
139 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
140 QName.create(barModule.getQNameModule(), "my-choice"));
141 assertNotNull(myChoice);
143 assertFalse(myChoice.getConstraints().isMandatory());
144 assertEquals(1, myChoice.getUnknownSchemaNodes().size());
145 assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
147 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
148 QName.create(barModule.getQNameModule(), "my-cont"));
149 assertNotNull(myCont);
151 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
152 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
153 assertNotNull(myAugLeaf);
154 assertTrue(myAugLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
155 assertNotNull(myAugLeaf.getUnits());
156 assertEquals("seconds", myAugLeaf.getUnits());
157 assertNotNull(myAugLeaf.getDefault());
158 assertEquals("new-def-val", myAugLeaf.getDefault());
159 assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
160 assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
162 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
163 QName.create(barModule.getQNameModule(), "my-used-leaf"));
164 assertNotNull(myUsedLeaf);
165 assertTrue(myUsedLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
166 assertNotNull(myUsedLeaf.getUnits());
167 assertEquals("weeks", myUsedLeaf.getUnits());
168 assertNotNull(myUsedLeaf.getDefault());
169 assertEquals("new-def-val", myUsedLeaf.getDefault());
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", QName.parseRevision("2017-01-20")).get();
182 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
183 QName.create(barModule.getQNameModule(), "my-leaf"));
184 assertNotNull(myLeaf);
186 assertNull(myLeaf.getDefault());
187 assertNull(myLeaf.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.getConstraints().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 assertNull(myAugLeaf.getDefault());
212 assertNull(myAugLeaf.getUnits());
213 assertEquals(0, myAugLeaf.getConstraints().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 assertNull(myUsedLeaf.getDefault());
220 assertNull(myUsedLeaf.getUnits());
221 assertEquals(0, myUsedLeaf.getConstraints().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 public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
349 final PrintStream stdout = System.out;
350 final ByteArrayOutputStream output = new ByteArrayOutputStream();
351 final String testLog;
353 System.setOut(new PrintStream(output, true, "UTF-8"));
355 StmtTestUtils.parseYangSources(
356 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang"),
357 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-2.yang"));
359 testLog = output.toString();
360 assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default" +
361 " in target leaf-list (bar?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple " +
362 "default statements."));
363 System.setOut(stdout);
367 public void shouldLogInvalidDeviateDeleteAttempt() throws Exception {
368 final PrintStream stdout = System.out;
369 final ByteArrayOutputStream output = new ByteArrayOutputStream();
370 final String testLog;
372 System.setOut(new PrintStream(output, true, "UTF-8"));
374 StmtTestUtils.parseYangSources(
375 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid.yang"),
376 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid.yang"));
378 testLog = output.toString();
379 assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units " +
380 "with argument 'seconds' in target node (bar?revision=2017-01-20)my-leaf because it does not exist " +
381 "in the target node."));
382 System.setOut(stdout);
386 public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
388 StmtTestUtils.parseYangSources(
389 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang"),
390 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-3.yang"));
391 fail("An exception should have been thrown.");
392 } catch (final ReactorException ex) {
393 final Throwable cause = ex.getCause();
394 assertTrue(cause instanceof InvalidSubstatementException);
395 assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
400 public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
402 StmtTestUtils.parseYangSources(
403 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang"),
404 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-3.yang"));
405 fail("An exception should have been thrown.");
406 } catch (final ReactorException ex) {
407 final Throwable cause = ex.getCause();
408 assertTrue(cause instanceof InvalidSubstatementException);
409 assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
414 public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
416 StmtTestUtils.parseYangSources(
417 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang"),
418 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid-2.yang"));
419 fail("An exception should have been thrown.");
420 } catch (final ReactorException ex) {
421 final Throwable cause = ex.getCause();
422 assertTrue(cause instanceof InvalidSubstatementException);
423 assertTrue(cause.getMessage().startsWith("CONFIG is not valid for DEVIATE."));