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;
21 import java.io.PrintStream;
22 import java.util.Date;
23 import org.junit.Test;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
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.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.UnsignedIntegerTypeDefinition;
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 Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
51 final Module importedModule = schemaContext.findModuleByName("imported", revision);
52 assertNotNull(importedModule);
54 final ContainerSchemaNode myContA = (ContainerSchemaNode) importedModule.getDataChildByName(
55 QName.create(importedModule.getQNameModule(), "my-cont-a"));
56 assertNotNull(myContA);
58 assertEquals(1, myContA.getChildNodes().size());
59 assertNotNull(myContA.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-a3")));
61 final ContainerSchemaNode myContB = (ContainerSchemaNode) importedModule.getDataChildByName(
62 QName.create(importedModule.getQNameModule(), "my-cont-b"));
65 final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
66 QName.create(importedModule.getQNameModule(), "my-cont-c"));
67 assertNotNull(myContC);
69 assertEquals(2, myContC.getChildNodes().size());
70 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
71 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
75 public void testDeviateAdd() throws Exception {
76 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
77 sourceForResource("/deviation-resolution-test/deviation-add/foo.yang"),
78 sourceForResource("/deviation-resolution-test/deviation-add/bar.yang"));
79 assertNotNull(schemaContext);
81 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
83 final Module barModule = schemaContext.findModuleByName("bar", revision);
84 assertNotNull(barModule);
86 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
87 QName.create(barModule.getQNameModule(), "my-leaf-list"));
88 assertNotNull(myLeafList);
90 assertFalse(myLeafList.isConfiguration());
91 assertEquals(3, myLeafList.getDefaults().size());
92 assertEquals(10, myLeafList.getConstraints().getMaxElements().intValue());
93 assertEquals(5, myLeafList.getConstraints().getMinElements().intValue());
94 assertNotNull(myLeafList.getType().getUnits());
96 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
97 QName.create(barModule.getQNameModule(), "my-list"));
98 assertNotNull(myList);
99 assertEquals(2, myList.getUniqueConstraints().size());
101 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
102 QName.create(barModule.getQNameModule(), "my-choice"));
103 assertNotNull(myChoice);
104 assertEquals("c2", myChoice.getDefaultCase());
106 final RpcDefinition myRpc = barModule.getRpcs().iterator().next();
107 final ContainerSchemaNode input = myRpc.getInput();
108 assertEquals(2, input.getConstraints().getMustConstraints().size());
109 final ContainerSchemaNode output = myRpc.getOutput();
110 assertEquals(2, output.getConstraints().getMustConstraints().size());
112 final NotificationDefinition myNotification = barModule.getNotifications().iterator().next();
113 assertEquals(2, myNotification.getConstraints().getMustConstraints().size());
115 final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) barModule.getDataChildByName(
116 QName.create(barModule.getQNameModule(), "my-anyxml"));
117 assertNotNull(myAnyxml);
118 assertTrue(myAnyxml.getConstraints().isMandatory());
119 assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
123 public void testDeviateReplace() throws Exception {
124 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
125 sourceForResource("/deviation-resolution-test/deviation-replace/foo.yang"),
126 sourceForResource("/deviation-resolution-test/deviation-replace/bar.yang"));
127 assertNotNull(schemaContext);
129 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
131 final Module barModule = schemaContext.findModuleByName("bar", revision);
132 assertNotNull(barModule);
134 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
135 QName.create(barModule.getQNameModule(), "my-leaf"));
136 assertNotNull(myLeaf);
138 assertTrue(myLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
139 assertNotNull(myLeaf.getUnits());
140 assertEquals("bytes", myLeaf.getUnits());
141 assertNotNull(myLeaf.getDefault());
142 assertEquals("10", myLeaf.getDefault());
144 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
145 QName.create(barModule.getQNameModule(), "my-leaf-list-test"));
146 assertNotNull(myLeafList);
148 assertEquals(6, myLeafList.getConstraints().getMaxElements().intValue());
149 assertEquals(3, myLeafList.getConstraints().getMinElements().intValue());
150 assertTrue(myLeafList.isConfiguration());
152 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
153 QName.create(barModule.getQNameModule(), "my-choice"));
154 assertNotNull(myChoice);
156 assertFalse(myChoice.getConstraints().isMandatory());
157 assertEquals(1, myChoice.getUnknownSchemaNodes().size());
158 assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
160 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
161 QName.create(barModule.getQNameModule(), "my-cont"));
162 assertNotNull(myCont);
164 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
165 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
166 assertNotNull(myAugLeaf);
167 assertTrue(myAugLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
168 assertNotNull(myAugLeaf.getUnits());
169 assertEquals("seconds", myAugLeaf.getUnits());
170 assertNotNull(myAugLeaf.getDefault());
171 assertEquals("new-def-val", myAugLeaf.getDefault());
172 assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
173 assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
175 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
176 QName.create(barModule.getQNameModule(), "my-used-leaf"));
177 assertNotNull(myUsedLeaf);
178 assertTrue(myUsedLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
179 assertNotNull(myUsedLeaf.getUnits());
180 assertEquals("weeks", myUsedLeaf.getUnits());
181 assertNotNull(myUsedLeaf.getDefault());
182 assertEquals("new-def-val", myUsedLeaf.getDefault());
183 assertEquals(1, myUsedLeaf.getUnknownSchemaNodes().size());
184 assertEquals("new arg", myUsedLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
188 public void testDeviateDelete() throws Exception {
189 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
190 sourceForResource("/deviation-resolution-test/deviation-delete/foo.yang"),
191 sourceForResource("/deviation-resolution-test/deviation-delete/bar.yang"));
192 assertNotNull(schemaContext);
194 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
196 final Module barModule = schemaContext.findModuleByName("bar", revision);
197 assertNotNull(barModule);
199 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
200 QName.create(barModule.getQNameModule(), "my-leaf"));
201 assertNotNull(myLeaf);
203 assertNull(myLeaf.getDefault());
204 assertNull(myLeaf.getUnits());
205 assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
207 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
208 QName.create(barModule.getQNameModule(), "my-leaf-list"));
209 assertNotNull(myLeafList);
211 assertEquals(0, myLeafList.getDefaults().size());
212 assertEquals(0, myLeafList.getConstraints().getMustConstraints().size());
214 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
215 QName.create(barModule.getQNameModule(), "my-list"));
216 assertNotNull(myList);
218 assertEquals(0, myList.getUniqueConstraints().size());
219 assertEquals(0, myList.getUnknownSchemaNodes().size());
221 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
222 QName.create(barModule.getQNameModule(), "my-cont"));
223 assertNotNull(myCont);
225 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
226 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
227 assertNotNull(myAugLeaf);
228 assertNull(myAugLeaf.getDefault());
229 assertNull(myAugLeaf.getUnits());
230 assertEquals(0, myAugLeaf.getConstraints().getMustConstraints().size());
231 assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
233 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
234 QName.create(barModule.getQNameModule(), "my-used-leaf"));
235 assertNotNull(myUsedLeaf);
236 assertNull(myUsedLeaf.getDefault());
237 assertNull(myUsedLeaf.getUnits());
238 assertEquals(0, myUsedLeaf.getConstraints().getMustConstraints().size());
239 assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
243 public void shouldFailOnInvalidYang10Model() throws Exception {
245 StmtTestUtils.parseYangSources(
246 sourceForResource("/deviation-resolution-test/deviation-add/foo10-invalid.yang"),
247 sourceForResource("/deviation-resolution-test/deviation-add/bar10-invalid.yang"));
248 fail("An exception should have been thrown.");
249 } catch (final ReactorException ex) {
250 final Throwable cause = ex.getCause();
251 assertTrue(cause instanceof InvalidSubstatementException);
252 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
257 public void shouldFailOnInvalidYang10Model2() throws Exception {
259 StmtTestUtils.parseYangSources(
260 sourceForResource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang"),
261 sourceForResource("/deviation-resolution-test/deviation-delete/bar10-invalid.yang"));
262 fail("An exception should have been thrown.");
263 } catch (final ReactorException ex) {
264 final Throwable cause = ex.getCause();
265 assertTrue(cause instanceof InvalidSubstatementException);
266 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
271 public void shouldFailOnInvalidDeviationTarget() throws Exception {
273 StmtTestUtils.parseYangSources(sourceForResource(
274 "/deviation-resolution-test/foo-invalid-deviation-target.yang"),
275 sourceForResource("/deviation-resolution-test/bar.yang"));
276 fail("An exception should have been thrown.");
277 } catch (final ReactorException ex) {
278 final Throwable cause = ex.getCause();
279 assertTrue(cause instanceof InferenceException);
280 assertTrue(cause.getMessage().startsWith("(bar?revision=2017-01-20)my-cont is not a valid deviation " +
281 "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
286 public void shouldFailOnInvalidDeviationPath() throws Exception {
288 StmtTestUtils.parseYangSources(
289 sourceForResource("/deviation-resolution-test/foo-invalid-deviation-path.yang"),
290 sourceForResource("/deviation-resolution-test/bar.yang"));
291 fail("An exception should have been thrown.");
292 } catch (final ReactorException ex) {
293 final Throwable cause = ex.getCause().getCause();
294 assertTrue(cause instanceof InferenceException);
295 assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(bar?revision=2017-01-20)" +
296 "invalid, (bar?revision=2017-01-20)path]}' not found"));
301 public void shouldFailOnInvalidDeviateAdd() throws Exception {
303 StmtTestUtils.parseYangSources(
304 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid.yang"),
305 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid.yang"));
306 fail("An exception should have been thrown.");
307 } catch (final ReactorException ex) {
308 final Throwable cause = ex.getCause();
309 assertTrue(cause instanceof InferenceException);
310 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
311 ":yin:1)config to target node (bar?revision=2017-01-20)my-leaf because it is already defined in" +
312 " target and can appear only once."));
317 public void shouldFailOnInvalidDeviateAdd2() throws Exception {
319 StmtTestUtils.parseYangSources(
320 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang"),
321 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-2.yang"));
322 fail("An exception should have been thrown.");
323 } catch (final ReactorException ex) {
324 final Throwable cause = ex.getCause();
325 assertTrue(cause instanceof InferenceException);
326 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
327 ":yin:1)default to target node (bar?revision=2017-01-20)my-leaf because it is already defined in" +
328 " target and can appear only once."));
333 public void shouldFailOnInvalidDeviateAdd3() throws Exception {
335 StmtTestUtils.parseYangSources(
336 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-4.yang"),
337 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-4.yang"));
338 fail("An exception should have been thrown.");
339 } catch (final ReactorException ex) {
340 final Throwable cause = ex.getCause();
341 assertTrue(cause instanceof InferenceException);
342 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
343 ":yin:1)default to target node (bar?revision=2017-02-01)my-used-leaf because it is already " +
344 "defined in target and can appear only once."));
349 public void shouldFailOnInvalidDeviateReplace() throws Exception {
351 StmtTestUtils.parseYangSources(
352 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid.yang"),
353 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid.yang"));
354 fail("An exception should have been thrown.");
355 } catch (final ReactorException ex) {
356 final Throwable cause = ex.getCause();
357 assertTrue(cause instanceof InferenceException);
358 assertTrue(cause.getMessage().startsWith("Deviation cannot replace substatement " +
359 "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (bar?revision=2017-01-20)my-leaf " +
360 "because it does not exist in target node."));
365 public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
366 final PrintStream stdout = System.out;
367 final ByteArrayOutputStream output = new ByteArrayOutputStream();
368 final String testLog;
370 System.setOut(new PrintStream(output, true, "UTF-8"));
372 StmtTestUtils.parseYangSources(
373 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang"),
374 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-2.yang"));
376 testLog = output.toString();
377 assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default" +
378 " in target leaf-list (bar?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple " +
379 "default statements."));
380 System.setOut(stdout);
384 public void shouldLogInvalidDeviateDeleteAttempt() throws Exception {
385 final PrintStream stdout = System.out;
386 final ByteArrayOutputStream output = new ByteArrayOutputStream();
387 final String testLog;
389 System.setOut(new PrintStream(output, true, "UTF-8"));
391 StmtTestUtils.parseYangSources(
392 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid.yang"),
393 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid.yang"));
395 testLog = output.toString();
396 assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units " +
397 "with argument 'seconds' in target node (bar?revision=2017-01-20)my-leaf because it does not exist " +
398 "in the target node."));
399 System.setOut(stdout);
403 public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
405 StmtTestUtils.parseYangSources(
406 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang"),
407 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-3.yang"));
408 fail("An exception should have been thrown.");
409 } catch (final ReactorException ex) {
410 final Throwable cause = ex.getCause();
411 assertTrue(cause instanceof InvalidSubstatementException);
412 assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
417 public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
419 StmtTestUtils.parseYangSources(
420 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang"),
421 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-3.yang"));
422 fail("An exception should have been thrown.");
423 } catch (final ReactorException ex) {
424 final Throwable cause = ex.getCause();
425 assertTrue(cause instanceof InvalidSubstatementException);
426 assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
431 public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
433 StmtTestUtils.parseYangSources(
434 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang"),
435 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid-2.yang"));
436 fail("An exception should have been thrown.");
437 } catch (final ReactorException ex) {
438 final Throwable cause = ex.getCause();
439 assertTrue(cause instanceof InvalidSubstatementException);
440 assertTrue(cause.getMessage().startsWith("CONFIG is not valid for DEVIATE."));