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.FileNotFoundException;
20 import java.io.PrintStream;
21 import java.io.UnsupportedEncodingException;
22 import java.net.URISyntaxException;
23 import java.text.ParseException;
24 import java.util.Date;
25 import org.junit.Test;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
28 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.Module;
35 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
36 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
37 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
38 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
40 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
41 import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
42 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
44 public class DeviationResolutionTest {
47 public void testDeviateNotSupported() throws ReactorException, FileNotFoundException, URISyntaxException,
49 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
50 "/deviation-resolution-test/deviation-not-supported");
51 assertNotNull(schemaContext);
53 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
55 final Module rootModule = schemaContext.findModuleByName("root", revision);
56 assertNotNull(rootModule);
58 final ContainerSchemaNode myContA = (ContainerSchemaNode) rootModule.getDataChildByName(
59 QName.create(rootModule.getQNameModule(), "my-cont-a"));
60 assertNotNull(myContA);
62 assertEquals(1, myContA.getChildNodes().size());
63 assertNotNull(myContA.getDataChildByName(QName.create(rootModule.getQNameModule(), "my-leaf-a3")));
65 final ContainerSchemaNode myContB = (ContainerSchemaNode) rootModule.getDataChildByName(
66 QName.create(rootModule.getQNameModule(), "my-cont-b"));
69 final Module importedModule = schemaContext.findModuleByName("imported", revision);
70 assertNotNull(importedModule);
72 final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
73 QName.create(importedModule.getQNameModule(), "my-cont-c"));
74 assertNotNull(myContC);
76 assertEquals(2, myContC.getChildNodes().size());
77 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
78 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
82 public void testDeviateAdd() throws ReactorException, FileNotFoundException, URISyntaxException, ParseException {
83 final SchemaContext schemaContext = StmtTestUtils.parseYangSource(
84 "/deviation-resolution-test/deviation-add/foo.yang");
85 assertNotNull(schemaContext);
87 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
89 final Module fooModule = schemaContext.findModuleByName("foo", revision);
90 assertNotNull(fooModule);
92 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
93 QName.create(fooModule.getQNameModule(), "my-leaf-list"));
94 assertNotNull(myLeafList);
96 assertFalse(myLeafList.isConfiguration());
97 assertEquals(3, myLeafList.getDefaults().size());
98 assertEquals(10, myLeafList.getConstraints().getMaxElements().intValue());
99 assertEquals(5, myLeafList.getConstraints().getMinElements().intValue());
100 assertNotNull(myLeafList.getType().getUnits());
102 final ListSchemaNode myList = (ListSchemaNode) fooModule.getDataChildByName(
103 QName.create(fooModule.getQNameModule(), "my-list"));
104 assertNotNull(myList);
105 assertEquals(2, myList.getUniqueConstraints().size());
107 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) fooModule.getDataChildByName(
108 QName.create(fooModule.getQNameModule(), "my-choice"));
109 assertNotNull(myChoice);
110 assertEquals("c2", myChoice.getDefaultCase());
112 final RpcDefinition myRpc = fooModule.getRpcs().iterator().next();
113 final ContainerSchemaNode input = myRpc.getInput();
114 assertEquals(2, input.getConstraints().getMustConstraints().size());
115 final ContainerSchemaNode output = myRpc.getOutput();
116 assertEquals(2, output.getConstraints().getMustConstraints().size());
118 final NotificationDefinition myNotification = fooModule.getNotifications().iterator().next();
119 assertEquals(2, myNotification.getConstraints().getMustConstraints().size());
121 final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) fooModule.getDataChildByName(
122 QName.create(fooModule.getQNameModule(), "my-anyxml"));
123 assertNotNull(myAnyxml);
124 assertTrue(myAnyxml.getConstraints().isMandatory());
125 assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
129 public void testDeviateReplace() throws ReactorException, FileNotFoundException, URISyntaxException, ParseException {
130 final SchemaContext schemaContext = StmtTestUtils.parseYangSource(
131 "/deviation-resolution-test/deviation-replace/foo.yang");
132 assertNotNull(schemaContext);
134 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
136 final Module fooModule = schemaContext.findModuleByName("foo", revision);
137 assertNotNull(fooModule);
139 final LeafSchemaNode myLeaf = (LeafSchemaNode) fooModule.getDataChildByName(
140 QName.create(fooModule.getQNameModule(), "my-leaf"));
141 assertNotNull(myLeaf);
143 assertTrue(myLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
144 assertNotNull(myLeaf.getUnits());
145 assertEquals("bytes", myLeaf.getUnits());
146 assertNotNull(myLeaf.getDefault());
147 assertEquals("10", myLeaf.getDefault());
149 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
150 QName.create(fooModule.getQNameModule(), "my-leaf-list-test"));
151 assertNotNull(myLeafList);
153 assertEquals(6, myLeafList.getConstraints().getMaxElements().intValue());
154 assertEquals(3, myLeafList.getConstraints().getMinElements().intValue());
155 assertTrue(myLeafList.isConfiguration());
157 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) fooModule.getDataChildByName(
158 QName.create(fooModule.getQNameModule(), "my-choice"));
159 assertNotNull(myChoice);
161 assertFalse(myChoice.getConstraints().isMandatory());
162 assertEquals(1, myChoice.getUnknownSchemaNodes().size());
163 assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
165 final ContainerSchemaNode myCont = (ContainerSchemaNode) fooModule.getDataChildByName(
166 QName.create(fooModule.getQNameModule(), "my-cont"));
167 assertNotNull(myCont);
169 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
170 QName.create(fooModule.getQNameModule(), "my-aug-leaf"));
171 assertNotNull(myAugLeaf);
172 assertTrue(myAugLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
173 assertNotNull(myAugLeaf.getUnits());
174 assertEquals("seconds", myAugLeaf.getUnits());
175 assertNotNull(myAugLeaf.getDefault());
176 assertEquals("new-def-val", myAugLeaf.getDefault());
177 assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
178 assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
180 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
181 QName.create(fooModule.getQNameModule(), "my-used-leaf"));
182 assertNotNull(myUsedLeaf);
183 assertTrue(myUsedLeaf.getType() instanceof UnsignedIntegerTypeDefinition);
184 assertNotNull(myUsedLeaf.getUnits());
185 assertEquals("weeks", myUsedLeaf.getUnits());
186 assertNotNull(myUsedLeaf.getDefault());
187 assertEquals("new-def-val", myUsedLeaf.getDefault());
188 assertEquals(1, myUsedLeaf.getUnknownSchemaNodes().size());
189 assertEquals("new arg", myUsedLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
193 public void testDeviateDelete() throws ReactorException, FileNotFoundException, URISyntaxException, ParseException {
194 final SchemaContext schemaContext = StmtTestUtils.parseYangSource(
195 "/deviation-resolution-test/deviation-delete/foo.yang");
196 assertNotNull(schemaContext);
198 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
200 final Module fooModule = schemaContext.findModuleByName("foo", revision);
201 assertNotNull(fooModule);
203 final LeafSchemaNode myLeaf = (LeafSchemaNode) fooModule.getDataChildByName(
204 QName.create(fooModule.getQNameModule(), "my-leaf"));
205 assertNotNull(myLeaf);
207 assertNull(myLeaf.getDefault());
208 assertNull(myLeaf.getUnits());
209 assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
211 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
212 QName.create(fooModule.getQNameModule(), "my-leaf-list"));
213 assertNotNull(myLeafList);
215 assertEquals(0, myLeafList.getDefaults().size());
216 assertEquals(0, myLeafList.getConstraints().getMustConstraints().size());
218 final ListSchemaNode myList = (ListSchemaNode) fooModule.getDataChildByName(
219 QName.create(fooModule.getQNameModule(), "my-list"));
220 assertNotNull(myList);
222 assertEquals(0, myList.getUniqueConstraints().size());
223 assertEquals(0, myList.getUnknownSchemaNodes().size());
225 final ContainerSchemaNode myCont = (ContainerSchemaNode) fooModule.getDataChildByName(
226 QName.create(fooModule.getQNameModule(), "my-cont"));
227 assertNotNull(myCont);
229 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
230 QName.create(fooModule.getQNameModule(), "my-aug-leaf"));
231 assertNotNull(myAugLeaf);
232 assertNull(myAugLeaf.getDefault());
233 assertNull(myAugLeaf.getUnits());
234 assertEquals(0, myAugLeaf.getConstraints().getMustConstraints().size());
235 assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
237 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
238 QName.create(fooModule.getQNameModule(), "my-used-leaf"));
239 assertNotNull(myUsedLeaf);
240 assertNull(myUsedLeaf.getDefault());
241 assertNull(myUsedLeaf.getUnits());
242 assertEquals(0, myUsedLeaf.getConstraints().getMustConstraints().size());
243 assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
247 public void shouldFailOnInvalidYang10Model() throws FileNotFoundException, URISyntaxException {
249 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo10-invalid.yang");
250 fail("An exception should have been thrown.");
251 } catch (final ReactorException ex) {
252 final Throwable cause = ex.getCause();
253 assertTrue(cause instanceof InvalidSubstatementException);
254 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
259 public void shouldFailOnInvalidYang10Model2() throws FileNotFoundException, URISyntaxException {
261 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo10-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 FileNotFoundException, URISyntaxException {
273 StmtTestUtils.parseYangSource("/deviation-resolution-test/foo-invalid-deviation-target.yang");
274 fail("An exception should have been thrown.");
275 } catch (final ReactorException ex) {
276 final Throwable cause = ex.getCause();
277 assertTrue(cause instanceof InferenceException);
278 assertTrue(cause.getMessage().startsWith("(foo?revision=2017-01-20)my-cont is not a valid deviation " +
279 "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
284 public void shouldFailOnInvalidDeviationPath() throws FileNotFoundException, URISyntaxException {
286 StmtTestUtils.parseYangSource("/deviation-resolution-test/foo-invalid-deviation-path.yang");
287 fail("An exception should have been thrown.");
288 } catch (final ReactorException ex) {
289 final Throwable cause = ex.getCause().getCause();
290 assertTrue(cause instanceof InferenceException);
291 assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(foo?revision=2017-01-20)invalid, " +
292 "(foo?revision=2017-01-20)path]}' not found"));
297 public void shouldFailOnInvalidDeviateAdd() throws FileNotFoundException, URISyntaxException {
299 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid.yang");
300 fail("An exception should have been thrown.");
301 } catch (final ReactorException ex) {
302 final Throwable cause = ex.getCause();
303 assertTrue(cause instanceof InferenceException);
304 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
305 ":yin:1)config to target node (foo?revision=2017-01-20)my-leaf because it is already defined in" +
306 " target and can appear only once."));
311 public void shouldFailOnInvalidDeviateAdd2() throws FileNotFoundException, URISyntaxException {
313 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang");
314 fail("An exception should have been thrown.");
315 } catch (final ReactorException ex) {
316 final Throwable cause = ex.getCause();
317 assertTrue(cause instanceof InferenceException);
318 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
319 ":yin:1)default to target node (foo?revision=2017-01-20)my-leaf because it is already defined in" +
320 " target and can appear only once."));
325 public void shouldFailOnInvalidDeviateAdd3() throws FileNotFoundException, URISyntaxException {
327 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid-4.yang");
328 fail("An exception should have been thrown.");
329 } catch (final ReactorException ex) {
330 final Throwable cause = ex.getCause();
331 assertTrue(cause instanceof InferenceException);
332 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
333 ":yin:1)default to target node (foo?revision=2017-02-01)my-used-leaf because it is already " +
334 "defined in target and can appear only once."));
339 public void shouldFailOnInvalidDeviateReplace() throws FileNotFoundException, URISyntaxException {
341 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid.yang");
342 fail("An exception should have been thrown.");
343 } catch (final ReactorException ex) {
344 final Throwable cause = ex.getCause();
345 assertTrue(cause instanceof InferenceException);
346 assertTrue(cause.getMessage().startsWith("Deviation cannot replace substatement " +
347 "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (foo?revision=2017-01-20)my-leaf " +
348 "because it does not exist in target node."));
353 public void shouldLogInvalidDeviateReplaceAttempt() throws FileNotFoundException, URISyntaxException,
354 UnsupportedEncodingException, ReactorException {
355 final PrintStream stdout = System.out;
356 final ByteArrayOutputStream output = new ByteArrayOutputStream();
357 final String testLog;
359 System.setOut(new PrintStream(output, true, "UTF-8"));
361 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang");
363 testLog = output.toString();
364 assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default" +
365 " in target leaf-list (foo?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple " +
366 "default statements."));
367 System.setOut(stdout);
371 public void shouldLogInvalidDeviateDeleteAttempt() throws FileNotFoundException, URISyntaxException,
372 UnsupportedEncodingException, ReactorException {
373 final PrintStream stdout = System.out;
374 final ByteArrayOutputStream output = new ByteArrayOutputStream();
375 final String testLog;
377 System.setOut(new PrintStream(output, true, "UTF-8"));
379 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo-invalid.yang");
381 testLog = output.toString();
382 assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units " +
383 "with argument 'seconds' in target node (foo?revision=2017-01-20)my-leaf because it does not exist " +
384 "in the target node."));
385 System.setOut(stdout);
389 public void shouldFailOnInvalidDeviateAddSubstatement() throws FileNotFoundException, URISyntaxException {
391 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-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 FileNotFoundException, URISyntaxException {
403 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang");
404 fail("An exception should have been thrown.");
405 } catch (final ReactorException ex) {
406 final Throwable cause = ex.getCause();
407 assertTrue(cause instanceof InvalidSubstatementException);
408 assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
413 public void shouldFailOnInvalidDeviateDeleteSubstatement() throws FileNotFoundException, URISyntaxException {
415 StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang");
416 fail("An exception should have been thrown.");
417 } catch (final ReactorException ex) {
418 final Throwable cause = ex.getCause();
419 assertTrue(cause instanceof InvalidSubstatementException);
420 assertTrue(cause.getMessage().startsWith("CONFIG is not valid for DEVIATE."));