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;
18 import java.io.ByteArrayOutputStream;
19 import java.io.PrintStream;
20 import java.util.Date;
21 import org.junit.Test;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
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 Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
49 final Module rootModule = schemaContext.findModuleByName("root", revision);
50 assertNotNull(rootModule);
52 final ContainerSchemaNode myContA = (ContainerSchemaNode) rootModule.getDataChildByName(
53 QName.create(rootModule.getQNameModule(), "my-cont-a"));
54 assertNotNull(myContA);
56 assertEquals(1, myContA.getChildNodes().size());
57 assertNotNull(myContA.getDataChildByName(QName.create(rootModule.getQNameModule(), "my-leaf-a3")));
59 final ContainerSchemaNode myContB = (ContainerSchemaNode) rootModule.getDataChildByName(
60 QName.create(rootModule.getQNameModule(), "my-cont-b"));
63 final Module importedModule = schemaContext.findModuleByName("imported", revision);
64 assertNotNull(importedModule);
66 final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
67 QName.create(importedModule.getQNameModule(), "my-cont-c"));
68 assertNotNull(myContC);
70 assertEquals(2, myContC.getChildNodes().size());
71 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
72 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
76 public void testDeviateAdd() throws Exception {
77 final SchemaContext schemaContext = StmtTestUtils.parseYangSource(
78 "/deviation-resolution-test/deviation-add/foo.yang");
79 assertNotNull(schemaContext);
81 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
83 final Module fooModule = schemaContext.findModuleByName("foo", revision);
84 assertNotNull(fooModule);
86 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
87 QName.create(fooModule.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) fooModule.getDataChildByName(
97 QName.create(fooModule.getQNameModule(), "my-list"));
98 assertNotNull(myList);
99 assertEquals(2, myList.getUniqueConstraints().size());
101 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) fooModule.getDataChildByName(
102 QName.create(fooModule.getQNameModule(), "my-choice"));
103 assertNotNull(myChoice);
104 assertEquals("c2", myChoice.getDefaultCase());
106 final RpcDefinition myRpc = fooModule.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 = fooModule.getNotifications().iterator().next();
113 assertEquals(2, myNotification.getConstraints().getMustConstraints().size());
115 final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) fooModule.getDataChildByName(
116 QName.create(fooModule.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.parseYangSource(
125 "/deviation-resolution-test/deviation-replace/foo.yang");
126 assertNotNull(schemaContext);
128 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
130 final Module fooModule = schemaContext.findModuleByName("foo", revision);
131 assertNotNull(fooModule);
133 final LeafSchemaNode myLeaf = (LeafSchemaNode) fooModule.getDataChildByName(
134 QName.create(fooModule.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) fooModule.getDataChildByName(
144 QName.create(fooModule.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) fooModule.getDataChildByName(
152 QName.create(fooModule.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) fooModule.getDataChildByName(
160 QName.create(fooModule.getQNameModule(), "my-cont"));
161 assertNotNull(myCont);
163 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
164 QName.create(fooModule.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(fooModule.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.parseYangSource(
189 "/deviation-resolution-test/deviation-delete/foo.yang");
190 assertNotNull(schemaContext);
192 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
194 final Module fooModule = schemaContext.findModuleByName("foo", revision);
195 assertNotNull(fooModule);
197 final LeafSchemaNode myLeaf = (LeafSchemaNode) fooModule.getDataChildByName(
198 QName.create(fooModule.getQNameModule(), "my-leaf"));
199 assertNotNull(myLeaf);
201 assertNull(myLeaf.getDefault());
202 assertNull(myLeaf.getUnits());
203 assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
205 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
206 QName.create(fooModule.getQNameModule(), "my-leaf-list"));
207 assertNotNull(myLeafList);
209 assertEquals(0, myLeafList.getDefaults().size());
210 assertEquals(0, myLeafList.getConstraints().getMustConstraints().size());
212 final ListSchemaNode myList = (ListSchemaNode) fooModule.getDataChildByName(
213 QName.create(fooModule.getQNameModule(), "my-list"));
214 assertNotNull(myList);
216 assertEquals(0, myList.getUniqueConstraints().size());
217 assertEquals(0, myList.getUnknownSchemaNodes().size());
219 final ContainerSchemaNode myCont = (ContainerSchemaNode) fooModule.getDataChildByName(
220 QName.create(fooModule.getQNameModule(), "my-cont"));
221 assertNotNull(myCont);
223 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
224 QName.create(fooModule.getQNameModule(), "my-aug-leaf"));
225 assertNotNull(myAugLeaf);
226 assertNull(myAugLeaf.getDefault());
227 assertNull(myAugLeaf.getUnits());
228 assertEquals(0, myAugLeaf.getConstraints().getMustConstraints().size());
229 assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
231 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
232 QName.create(fooModule.getQNameModule(), "my-used-leaf"));
233 assertNotNull(myUsedLeaf);
234 assertNull(myUsedLeaf.getDefault());
235 assertNull(myUsedLeaf.getUnits());
236 assertEquals(0, myUsedLeaf.getConstraints().getMustConstraints().size());
237 assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
241 public void shouldFailOnInvalidYang10Model() throws Exception {
243 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo10-invalid.yang");
244 fail("An exception should have been thrown.");
245 } catch (final ReactorException ex) {
246 final Throwable cause = ex.getCause();
247 assertTrue(cause instanceof InvalidSubstatementException);
248 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
253 public void shouldFailOnInvalidYang10Model2() throws Exception {
255 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang");
256 fail("An exception should have been thrown.");
257 } catch (final ReactorException ex) {
258 final Throwable cause = ex.getCause();
259 assertTrue(cause instanceof InvalidSubstatementException);
260 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
265 public void shouldFailOnInvalidDeviationTarget() throws Exception {
267 StmtTestUtils.parseYangSource("/deviation-resolution-test/foo-invalid-deviation-target.yang");
268 fail("An exception should have been thrown.");
269 } catch (final ReactorException ex) {
270 final Throwable cause = ex.getCause();
271 assertTrue(cause instanceof InferenceException);
272 assertTrue(cause.getMessage().startsWith("(foo?revision=2017-01-20)my-cont is not a valid deviation " +
273 "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
278 public void shouldFailOnInvalidDeviationPath() throws Exception {
280 StmtTestUtils.parseYangSource("/deviation-resolution-test/foo-invalid-deviation-path.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=[(foo?revision=2017-01-20)invalid, " +
286 "(foo?revision=2017-01-20)path]}' not found"));
291 public void shouldFailOnInvalidDeviateAdd() throws Exception {
293 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid.yang");
294 fail("An exception should have been thrown.");
295 } catch (final ReactorException ex) {
296 final Throwable cause = ex.getCause();
297 assertTrue(cause instanceof InferenceException);
298 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
299 ":yin:1)config to target node (foo?revision=2017-01-20)my-leaf because it is already defined in" +
300 " target and can appear only once."));
305 public void shouldFailOnInvalidDeviateAdd2() throws Exception {
307 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang");
308 fail("An exception should have been thrown.");
309 } catch (final ReactorException ex) {
310 final Throwable cause = ex.getCause();
311 assertTrue(cause instanceof InferenceException);
312 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
313 ":yin:1)default to target node (foo?revision=2017-01-20)my-leaf because it is already defined in" +
314 " target and can appear only once."));
319 public void shouldFailOnInvalidDeviateAdd3() throws Exception {
321 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-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 (foo?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.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid.yang");
336 fail("An exception should have been thrown.");
337 } catch (final ReactorException ex) {
338 final Throwable cause = ex.getCause();
339 assertTrue(cause instanceof InferenceException);
340 assertTrue(cause.getMessage().startsWith("Deviation cannot replace substatement " +
341 "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (foo?revision=2017-01-20)my-leaf " +
342 "because it does not exist in target node."));
347 public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
348 final PrintStream stdout = System.out;
349 final ByteArrayOutputStream output = new ByteArrayOutputStream();
350 final String testLog;
352 System.setOut(new PrintStream(output, true, "UTF-8"));
354 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang");
356 testLog = output.toString();
357 assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default" +
358 " in target leaf-list (foo?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple " +
359 "default statements."));
360 System.setOut(stdout);
364 public void shouldLogInvalidDeviateDeleteAttempt() 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.parseYangSource("/deviation-resolution-test/deviation-delete/foo-invalid.yang");
373 testLog = output.toString();
374 assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units " +
375 "with argument 'seconds' in target node (foo?revision=2017-01-20)my-leaf because it does not exist " +
376 "in the target node."));
377 System.setOut(stdout);
381 public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
383 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang");
384 fail("An exception should have been thrown.");
385 } catch (final ReactorException ex) {
386 final Throwable cause = ex.getCause();
387 assertTrue(cause instanceof InvalidSubstatementException);
388 assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
393 public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
395 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang");
396 fail("An exception should have been thrown.");
397 } catch (final ReactorException ex) {
398 final Throwable cause = ex.getCause();
399 assertTrue(cause instanceof InvalidSubstatementException);
400 assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
405 public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
407 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo-invalid-2.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("CONFIG is not valid for DEVIATE."));