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.Date;
22 import org.junit.Test;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
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.LeafListSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.Module;
32 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
33 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
35 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
37 import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
38 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
40 public class DeviationResolutionTest {
43 public void testDeviateNotSupported() throws Exception {
44 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
45 "/deviation-resolution-test/deviation-not-supported");
46 assertNotNull(schemaContext);
48 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
50 final Module importedModule = schemaContext.findModuleByName("imported", revision);
51 assertNotNull(importedModule);
53 final ContainerSchemaNode myContA = (ContainerSchemaNode) importedModule.getDataChildByName(
54 QName.create(importedModule.getQNameModule(), "my-cont-a"));
55 assertNotNull(myContA);
57 assertEquals(1, myContA.getChildNodes().size());
58 assertNotNull(myContA.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-a3")));
60 final ContainerSchemaNode myContB = (ContainerSchemaNode) importedModule.getDataChildByName(
61 QName.create(importedModule.getQNameModule(), "my-cont-b"));
64 final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
65 QName.create(importedModule.getQNameModule(), "my-cont-c"));
66 assertNotNull(myContC);
68 assertEquals(2, myContC.getChildNodes().size());
69 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
70 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
74 public void testDeviateAdd() throws Exception {
75 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
76 sourceForResource("/deviation-resolution-test/deviation-add/foo.yang"),
77 sourceForResource("/deviation-resolution-test/deviation-add/bar.yang"));
78 assertNotNull(schemaContext);
80 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
82 final Module barModule = schemaContext.findModuleByName("bar", revision);
83 assertNotNull(barModule);
85 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
86 QName.create(barModule.getQNameModule(), "my-leaf-list"));
87 assertNotNull(myLeafList);
89 assertFalse(myLeafList.isConfiguration());
90 assertEquals(3, myLeafList.getDefaults().size());
91 assertEquals(10, myLeafList.getConstraints().getMaxElements().intValue());
92 assertEquals(5, myLeafList.getConstraints().getMinElements().intValue());
93 assertNotNull(myLeafList.getType().getUnits());
95 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
96 QName.create(barModule.getQNameModule(), "my-list"));
97 assertNotNull(myList);
98 assertEquals(2, myList.getUniqueConstraints().size());
100 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
101 QName.create(barModule.getQNameModule(), "my-choice"));
102 assertNotNull(myChoice);
103 assertEquals("c2", myChoice.getDefaultCase());
105 final RpcDefinition myRpc = barModule.getRpcs().iterator().next();
106 final ContainerSchemaNode input = myRpc.getInput();
107 assertEquals(2, input.getConstraints().getMustConstraints().size());
108 final ContainerSchemaNode output = myRpc.getOutput();
109 assertEquals(2, output.getConstraints().getMustConstraints().size());
111 final NotificationDefinition myNotification = barModule.getNotifications().iterator().next();
112 assertEquals(2, myNotification.getConstraints().getMustConstraints().size());
114 final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) barModule.getDataChildByName(
115 QName.create(barModule.getQNameModule(), "my-anyxml"));
116 assertNotNull(myAnyxml);
117 assertTrue(myAnyxml.getConstraints().isMandatory());
118 assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
122 public void testDeviateReplace() throws Exception {
123 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
124 sourceForResource("/deviation-resolution-test/deviation-replace/foo.yang"),
125 sourceForResource("/deviation-resolution-test/deviation-replace/bar.yang"));
126 assertNotNull(schemaContext);
128 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
130 final Module barModule = schemaContext.findModuleByName("bar", revision);
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 UnsignedIntegerTypeDefinition);
138 assertNotNull(myLeaf.getUnits());
139 assertEquals("bytes", myLeaf.getUnits());
140 assertNotNull(myLeaf.getDefault());
141 assertEquals("10", myLeaf.getDefault());
143 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
144 QName.create(barModule.getQNameModule(), "my-leaf-list-test"));
145 assertNotNull(myLeafList);
147 assertEquals(6, myLeafList.getConstraints().getMaxElements().intValue());
148 assertEquals(3, myLeafList.getConstraints().getMinElements().intValue());
149 assertTrue(myLeafList.isConfiguration());
151 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
152 QName.create(barModule.getQNameModule(), "my-choice"));
153 assertNotNull(myChoice);
155 assertFalse(myChoice.getConstraints().isMandatory());
156 assertEquals(1, myChoice.getUnknownSchemaNodes().size());
157 assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
159 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
160 QName.create(barModule.getQNameModule(), "my-cont"));
161 assertNotNull(myCont);
163 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
164 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
165 assertNotNull(myAugLeaf);
166 assertTrue(myAugLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
167 assertNotNull(myAugLeaf.getUnits());
168 assertEquals("seconds", myAugLeaf.getUnits());
169 assertNotNull(myAugLeaf.getDefault());
170 assertEquals("new-def-val", myAugLeaf.getDefault());
171 assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
172 assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
174 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
175 QName.create(barModule.getQNameModule(), "my-used-leaf"));
176 assertNotNull(myUsedLeaf);
177 assertTrue(myUsedLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
178 assertNotNull(myUsedLeaf.getUnits());
179 assertEquals("weeks", myUsedLeaf.getUnits());
180 assertNotNull(myUsedLeaf.getDefault());
181 assertEquals("new-def-val", myUsedLeaf.getDefault());
182 assertEquals(1, myUsedLeaf.getUnknownSchemaNodes().size());
183 assertEquals("new arg", myUsedLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
187 public void testDeviateDelete() throws Exception {
188 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
189 sourceForResource("/deviation-resolution-test/deviation-delete/foo.yang"),
190 sourceForResource("/deviation-resolution-test/deviation-delete/bar.yang"));
191 assertNotNull(schemaContext);
193 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
195 final Module barModule = schemaContext.findModuleByName("bar", revision);
196 assertNotNull(barModule);
198 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
199 QName.create(barModule.getQNameModule(), "my-leaf"));
200 assertNotNull(myLeaf);
202 assertNull(myLeaf.getDefault());
203 assertNull(myLeaf.getUnits());
204 assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
206 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
207 QName.create(barModule.getQNameModule(), "my-leaf-list"));
208 assertNotNull(myLeafList);
210 assertEquals(0, myLeafList.getDefaults().size());
211 assertEquals(0, myLeafList.getConstraints().getMustConstraints().size());
213 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
214 QName.create(barModule.getQNameModule(), "my-list"));
215 assertNotNull(myList);
217 assertEquals(0, myList.getUniqueConstraints().size());
218 assertEquals(0, myList.getUnknownSchemaNodes().size());
220 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
221 QName.create(barModule.getQNameModule(), "my-cont"));
222 assertNotNull(myCont);
224 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
225 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
226 assertNotNull(myAugLeaf);
227 assertNull(myAugLeaf.getDefault());
228 assertNull(myAugLeaf.getUnits());
229 assertEquals(0, myAugLeaf.getConstraints().getMustConstraints().size());
230 assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
232 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
233 QName.create(barModule.getQNameModule(), "my-used-leaf"));
234 assertNotNull(myUsedLeaf);
235 assertNull(myUsedLeaf.getDefault());
236 assertNull(myUsedLeaf.getUnits());
237 assertEquals(0, myUsedLeaf.getConstraints().getMustConstraints().size());
238 assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
242 public void shouldFailOnInvalidYang10Model() throws Exception {
244 StmtTestUtils.parseYangSources(
245 sourceForResource("/deviation-resolution-test/deviation-add/foo10-invalid.yang"),
246 sourceForResource("/deviation-resolution-test/deviation-add/bar10-invalid.yang"));
247 fail("An exception should have been thrown.");
248 } catch (final ReactorException ex) {
249 final Throwable cause = ex.getCause();
250 assertTrue(cause instanceof InvalidSubstatementException);
251 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
256 public void shouldFailOnInvalidYang10Model2() throws Exception {
258 StmtTestUtils.parseYangSources(
259 sourceForResource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang"),
260 sourceForResource("/deviation-resolution-test/deviation-delete/bar10-invalid.yang"));
261 fail("An exception should have been thrown.");
262 } catch (final ReactorException ex) {
263 final Throwable cause = ex.getCause();
264 assertTrue(cause instanceof InvalidSubstatementException);
265 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
270 public void shouldFailOnInvalidDeviationTarget() throws Exception {
272 StmtTestUtils.parseYangSources(sourceForResource(
273 "/deviation-resolution-test/foo-invalid-deviation-target.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();
278 assertTrue(cause instanceof InferenceException);
279 assertTrue(cause.getMessage().startsWith("(bar?revision=2017-01-20)my-cont is not a valid deviation " +
280 "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
285 public void shouldFailOnInvalidDeviationPath() throws Exception {
287 StmtTestUtils.parseYangSources(
288 sourceForResource("/deviation-resolution-test/foo-invalid-deviation-path.yang"),
289 sourceForResource("/deviation-resolution-test/bar.yang"));
290 fail("An exception should have been thrown.");
291 } catch (final ReactorException ex) {
292 final Throwable cause = ex.getCause().getCause();
293 assertTrue(cause instanceof InferenceException);
294 assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(bar?revision=2017-01-20)" +
295 "invalid, (bar?revision=2017-01-20)path]}' not found"));
300 public void shouldFailOnInvalidDeviateAdd() throws Exception {
302 StmtTestUtils.parseYangSources(
303 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid.yang"),
304 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid.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)config 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 shouldFailOnInvalidDeviateAdd2() throws Exception {
318 StmtTestUtils.parseYangSources(
319 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang"),
320 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-2.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-01-20)my-leaf because it is already defined in" +
327 " target and can appear only once."));
332 public void shouldFailOnInvalidDeviateAdd3() throws Exception {
334 StmtTestUtils.parseYangSources(
335 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-4.yang"),
336 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-4.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 add substatement (urn:ietf:params:xml:ns:yang" +
342 ":yin:1)default to target node (bar?revision=2017-02-01)my-used-leaf because it is already " +
343 "defined in target and can appear only once."));
348 public void shouldFailOnInvalidDeviateReplace() throws Exception {
350 StmtTestUtils.parseYangSources(
351 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid.yang"),
352 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid.yang"));
353 fail("An exception should have been thrown.");
354 } catch (final ReactorException ex) {
355 final Throwable cause = ex.getCause();
356 assertTrue(cause instanceof InferenceException);
357 assertTrue(cause.getMessage().startsWith("Deviation cannot replace substatement " +
358 "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (bar?revision=2017-01-20)my-leaf " +
359 "because it does not exist in target node."));
364 public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
365 final PrintStream stdout = System.out;
366 final ByteArrayOutputStream output = new ByteArrayOutputStream();
367 final String testLog;
369 System.setOut(new PrintStream(output, true, "UTF-8"));
371 StmtTestUtils.parseYangSources(
372 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang"),
373 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-2.yang"));
375 testLog = output.toString();
376 assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default" +
377 " in target leaf-list (bar?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple " +
378 "default statements."));
379 System.setOut(stdout);
383 public void shouldLogInvalidDeviateDeleteAttempt() throws Exception {
384 final PrintStream stdout = System.out;
385 final ByteArrayOutputStream output = new ByteArrayOutputStream();
386 final String testLog;
388 System.setOut(new PrintStream(output, true, "UTF-8"));
390 StmtTestUtils.parseYangSources(
391 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid.yang"),
392 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid.yang"));
394 testLog = output.toString();
395 assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units " +
396 "with argument 'seconds' in target node (bar?revision=2017-01-20)my-leaf because it does not exist " +
397 "in the target node."));
398 System.setOut(stdout);
402 public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
404 StmtTestUtils.parseYangSources(
405 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang"),
406 sourceForResource("/deviation-resolution-test/deviation-add/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("TYPE is not valid for DEVIATE."));
416 public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
418 StmtTestUtils.parseYangSources(
419 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang"),
420 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-3.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("MUST is not valid for DEVIATE."));
430 public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
432 StmtTestUtils.parseYangSources(
433 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang"),
434 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid-2.yang"));
435 fail("An exception should have been thrown.");
436 } catch (final ReactorException ex) {
437 final Throwable cause = ex.getCause();
438 assertTrue(cause instanceof InvalidSubstatementException);
439 assertTrue(cause.getMessage().startsWith("CONFIG is not valid for DEVIATE."));