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.common.Revision;
24 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.Module;
31 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
32 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
33 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
34 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
37 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
39 public class DeviationResolutionTest {
42 public void testDeviateNotSupported() throws Exception {
43 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
44 "/deviation-resolution-test/deviation-not-supported");
45 assertNotNull(schemaContext);
47 final Module importedModule = schemaContext.findModule("imported", Revision.valueOf("2017-01-20")).get();
48 final ContainerSchemaNode myContA = (ContainerSchemaNode) importedModule.getDataChildByName(
49 QName.create(importedModule.getQNameModule(), "my-cont-a"));
50 assertNotNull(myContA);
52 assertEquals(1, myContA.getChildNodes().size());
53 assertNotNull(myContA.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-a3")));
55 final ContainerSchemaNode myContB = (ContainerSchemaNode) importedModule.getDataChildByName(
56 QName.create(importedModule.getQNameModule(), "my-cont-b"));
59 final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
60 QName.create(importedModule.getQNameModule(), "my-cont-c"));
61 assertNotNull(myContC);
63 assertEquals(2, myContC.getChildNodes().size());
64 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
65 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
69 public void testDeviateAdd() throws Exception {
70 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
71 sourceForResource("/deviation-resolution-test/deviation-add/foo.yang"),
72 sourceForResource("/deviation-resolution-test/deviation-add/bar.yang"));
73 assertNotNull(schemaContext);
75 final Module barModule = schemaContext.findModule("bar", Revision.valueOf("2017-01-20")).get();
76 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
77 QName.create(barModule.getQNameModule(), "my-leaf-list"));
78 assertNotNull(myLeafList);
80 assertFalse(myLeafList.isConfiguration());
81 assertEquals(3, myLeafList.getDefaults().size());
82 assertEquals(10, myLeafList.getConstraints().getMaxElements().intValue());
83 assertEquals(5, myLeafList.getConstraints().getMinElements().intValue());
84 assertNotNull(myLeafList.getType().getUnits());
86 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
87 QName.create(barModule.getQNameModule(), "my-list"));
88 assertNotNull(myList);
89 assertEquals(2, myList.getUniqueConstraints().size());
91 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
92 QName.create(barModule.getQNameModule(), "my-choice"));
93 assertNotNull(myChoice);
94 assertEquals("c2", myChoice.getDefaultCase());
96 final RpcDefinition myRpc = barModule.getRpcs().iterator().next();
97 final ContainerSchemaNode input = myRpc.getInput();
98 assertEquals(2, input.getConstraints().getMustConstraints().size());
99 final ContainerSchemaNode output = myRpc.getOutput();
100 assertEquals(2, output.getConstraints().getMustConstraints().size());
102 final NotificationDefinition myNotification = barModule.getNotifications().iterator().next();
103 assertEquals(2, myNotification.getConstraints().getMustConstraints().size());
105 final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) barModule.getDataChildByName(
106 QName.create(barModule.getQNameModule(), "my-anyxml"));
107 assertNotNull(myAnyxml);
108 assertTrue(myAnyxml.getConstraints().isMandatory());
109 assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
113 public void testDeviateReplace() throws Exception {
114 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
115 sourceForResource("/deviation-resolution-test/deviation-replace/foo.yang"),
116 sourceForResource("/deviation-resolution-test/deviation-replace/bar.yang"));
117 assertNotNull(schemaContext);
119 final Module barModule = schemaContext.findModule("bar", Revision.valueOf("2017-01-20")).get();
120 assertNotNull(barModule);
122 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
123 QName.create(barModule.getQNameModule(), "my-leaf"));
124 assertNotNull(myLeaf);
126 assertTrue(myLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
127 assertNotNull(myLeaf.getUnits());
128 assertEquals("bytes", myLeaf.getUnits());
129 assertNotNull(myLeaf.getDefault());
130 assertEquals("10", myLeaf.getDefault());
132 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
133 QName.create(barModule.getQNameModule(), "my-leaf-list-test"));
134 assertNotNull(myLeafList);
136 assertEquals(6, myLeafList.getConstraints().getMaxElements().intValue());
137 assertEquals(3, myLeafList.getConstraints().getMinElements().intValue());
138 assertTrue(myLeafList.isConfiguration());
140 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
141 QName.create(barModule.getQNameModule(), "my-choice"));
142 assertNotNull(myChoice);
144 assertFalse(myChoice.getConstraints().isMandatory());
145 assertEquals(1, myChoice.getUnknownSchemaNodes().size());
146 assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
148 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
149 QName.create(barModule.getQNameModule(), "my-cont"));
150 assertNotNull(myCont);
152 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
153 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
154 assertNotNull(myAugLeaf);
155 assertTrue(myAugLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
156 assertNotNull(myAugLeaf.getUnits());
157 assertEquals("seconds", myAugLeaf.getUnits());
158 assertNotNull(myAugLeaf.getDefault());
159 assertEquals("new-def-val", myAugLeaf.getDefault());
160 assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
161 assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
163 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
164 QName.create(barModule.getQNameModule(), "my-used-leaf"));
165 assertNotNull(myUsedLeaf);
166 assertTrue(myUsedLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
167 assertNotNull(myUsedLeaf.getUnits());
168 assertEquals("weeks", myUsedLeaf.getUnits());
169 assertNotNull(myUsedLeaf.getDefault());
170 assertEquals("new-def-val", myUsedLeaf.getDefault());
171 assertEquals(1, myUsedLeaf.getUnknownSchemaNodes().size());
172 assertEquals("new arg", myUsedLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
176 public void testDeviateDelete() throws Exception {
177 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
178 sourceForResource("/deviation-resolution-test/deviation-delete/foo.yang"),
179 sourceForResource("/deviation-resolution-test/deviation-delete/bar.yang"));
180 assertNotNull(schemaContext);
182 final Module barModule = schemaContext.findModule("bar", Revision.valueOf("2017-01-20")).get();
183 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
184 QName.create(barModule.getQNameModule(), "my-leaf"));
185 assertNotNull(myLeaf);
187 assertNull(myLeaf.getDefault());
188 assertNull(myLeaf.getUnits());
189 assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
191 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
192 QName.create(barModule.getQNameModule(), "my-leaf-list"));
193 assertNotNull(myLeafList);
195 assertEquals(0, myLeafList.getDefaults().size());
196 assertEquals(0, myLeafList.getConstraints().getMustConstraints().size());
198 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
199 QName.create(barModule.getQNameModule(), "my-list"));
200 assertNotNull(myList);
202 assertEquals(0, myList.getUniqueConstraints().size());
203 assertEquals(0, myList.getUnknownSchemaNodes().size());
205 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
206 QName.create(barModule.getQNameModule(), "my-cont"));
207 assertNotNull(myCont);
209 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
210 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
211 assertNotNull(myAugLeaf);
212 assertNull(myAugLeaf.getDefault());
213 assertNull(myAugLeaf.getUnits());
214 assertEquals(0, myAugLeaf.getConstraints().getMustConstraints().size());
215 assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
217 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
218 QName.create(barModule.getQNameModule(), "my-used-leaf"));
219 assertNotNull(myUsedLeaf);
220 assertNull(myUsedLeaf.getDefault());
221 assertNull(myUsedLeaf.getUnits());
222 assertEquals(0, myUsedLeaf.getConstraints().getMustConstraints().size());
223 assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
227 public void shouldFailOnInvalidYang10Model() throws Exception {
229 StmtTestUtils.parseYangSources(
230 sourceForResource("/deviation-resolution-test/deviation-add/foo10-invalid.yang"),
231 sourceForResource("/deviation-resolution-test/deviation-add/bar10-invalid.yang"));
232 fail("An exception should have been thrown.");
233 } catch (final ReactorException ex) {
234 final Throwable cause = ex.getCause();
235 assertTrue(cause instanceof InvalidSubstatementException);
236 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
241 public void shouldFailOnInvalidYang10Model2() throws Exception {
243 StmtTestUtils.parseYangSources(
244 sourceForResource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang"),
245 sourceForResource("/deviation-resolution-test/deviation-delete/bar10-invalid.yang"));
246 fail("An exception should have been thrown.");
247 } catch (final ReactorException ex) {
248 final Throwable cause = ex.getCause();
249 assertTrue(cause instanceof InvalidSubstatementException);
250 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
255 public void shouldFailOnInvalidDeviationTarget() throws Exception {
257 StmtTestUtils.parseYangSources(sourceForResource(
258 "/deviation-resolution-test/foo-invalid-deviation-target.yang"),
259 sourceForResource("/deviation-resolution-test/bar.yang"));
260 fail("An exception should have been thrown.");
261 } catch (final ReactorException ex) {
262 final Throwable cause = ex.getCause();
263 assertTrue(cause instanceof InferenceException);
264 assertTrue(cause.getMessage().startsWith("(bar?revision=2017-01-20)my-cont is not a valid deviation " +
265 "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
270 public void shouldFailOnInvalidDeviationPath() throws Exception {
272 StmtTestUtils.parseYangSources(
273 sourceForResource("/deviation-resolution-test/foo-invalid-deviation-path.yang"),
274 sourceForResource("/deviation-resolution-test/bar.yang"));
275 fail("An exception should have been thrown.");
276 } catch (final ReactorException ex) {
277 final Throwable cause = ex.getCause().getCause();
278 assertTrue(cause instanceof InferenceException);
279 assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(bar?revision=2017-01-20)" +
280 "invalid, (bar?revision=2017-01-20)path]}' not found"));
285 public void shouldFailOnInvalidDeviateAdd() throws Exception {
287 StmtTestUtils.parseYangSources(
288 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid.yang"),
289 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid.yang"));
290 fail("An exception should have been thrown.");
291 } catch (final ReactorException ex) {
292 final Throwable cause = ex.getCause();
293 assertTrue(cause instanceof InferenceException);
294 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
295 ":yin:1)config to target node (bar?revision=2017-01-20)my-leaf because it is already defined in" +
296 " target and can appear only once."));
301 public void shouldFailOnInvalidDeviateAdd2() throws Exception {
303 StmtTestUtils.parseYangSources(
304 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang"),
305 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-2.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)default 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 shouldFailOnInvalidDeviateAdd3() throws Exception {
319 StmtTestUtils.parseYangSources(
320 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-4.yang"),
321 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-4.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-02-01)my-used-leaf because it is already " +
328 "defined in target and can appear only once."));
333 public void shouldFailOnInvalidDeviateReplace() throws Exception {
335 StmtTestUtils.parseYangSources(
336 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid.yang"),
337 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid.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 replace substatement " +
343 "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (bar?revision=2017-01-20)my-leaf " +
344 "because it does not exist in target node."));
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 assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default" +
362 " in target leaf-list (bar?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple " +
363 "default statements."));
364 System.setOut(stdout);
368 public void shouldLogInvalidDeviateDeleteAttempt() throws Exception {
369 final PrintStream stdout = System.out;
370 final ByteArrayOutputStream output = new ByteArrayOutputStream();
371 final String testLog;
373 System.setOut(new PrintStream(output, true, "UTF-8"));
375 StmtTestUtils.parseYangSources(
376 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid.yang"),
377 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid.yang"));
379 testLog = output.toString();
380 assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units " +
381 "with argument 'seconds' in target node (bar?revision=2017-01-20)my-leaf because it does not exist " +
382 "in the target node."));
383 System.setOut(stdout);
387 public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
389 StmtTestUtils.parseYangSources(
390 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang"),
391 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-3.yang"));
392 fail("An exception should have been thrown.");
393 } catch (final ReactorException ex) {
394 final Throwable cause = ex.getCause();
395 assertTrue(cause instanceof InvalidSubstatementException);
396 assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
401 public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
403 StmtTestUtils.parseYangSources(
404 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang"),
405 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-3.yang"));
406 fail("An exception should have been thrown.");
407 } catch (final ReactorException ex) {
408 final Throwable cause = ex.getCause();
409 assertTrue(cause instanceof InvalidSubstatementException);
410 assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
415 public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
417 StmtTestUtils.parseYangSources(
418 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang"),
419 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid-2.yang"));
420 fail("An exception should have been thrown.");
421 } catch (final ReactorException ex) {
422 final Throwable cause = ex.getCause();
423 assertTrue(cause instanceof InvalidSubstatementException);
424 assertTrue(cause.getMessage().startsWith("CONFIG is not valid for DEVIATE."));