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.Optional;
22 import org.junit.Test;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.common.Revision;
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.Uint32TypeDefinition;
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 Module importedModule = schemaContext.findModule("imported", Revision.of("2017-01-20")).get();
49 final ContainerSchemaNode myContA = (ContainerSchemaNode) importedModule.getDataChildByName(
50 QName.create(importedModule.getQNameModule(), "my-cont-a"));
51 assertNotNull(myContA);
53 assertEquals(1, myContA.getChildNodes().size());
54 assertNotNull(myContA.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-a3")));
56 final ContainerSchemaNode myContB = (ContainerSchemaNode) importedModule.getDataChildByName(
57 QName.create(importedModule.getQNameModule(), "my-cont-b"));
60 final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
61 QName.create(importedModule.getQNameModule(), "my-cont-c"));
62 assertNotNull(myContC);
64 assertEquals(2, myContC.getChildNodes().size());
65 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
66 assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
70 public void testDeviateAdd() throws Exception {
71 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
72 sourceForResource("/deviation-resolution-test/deviation-add/foo.yang"),
73 sourceForResource("/deviation-resolution-test/deviation-add/bar.yang"));
74 assertNotNull(schemaContext);
76 final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
77 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
78 QName.create(barModule.getQNameModule(), "my-leaf-list"));
79 assertNotNull(myLeafList);
81 assertFalse(myLeafList.isConfiguration());
82 assertEquals(3, myLeafList.getDefaults().size());
83 assertEquals(10, myLeafList.getConstraints().getMaxElements().intValue());
84 assertEquals(5, myLeafList.getConstraints().getMinElements().intValue());
85 assertNotNull(myLeafList.getType().getUnits());
87 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
88 QName.create(barModule.getQNameModule(), "my-list"));
89 assertNotNull(myList);
90 assertEquals(2, myList.getUniqueConstraints().size());
92 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
93 QName.create(barModule.getQNameModule(), "my-choice"));
94 assertNotNull(myChoice);
95 assertEquals("c2", myChoice.getDefaultCase().get().getQName().getLocalName());
97 final RpcDefinition myRpc = barModule.getRpcs().iterator().next();
98 final ContainerSchemaNode input = myRpc.getInput();
99 assertEquals(2, input.getConstraints().getMustConstraints().size());
100 final ContainerSchemaNode output = myRpc.getOutput();
101 assertEquals(2, output.getConstraints().getMustConstraints().size());
103 final NotificationDefinition myNotification = barModule.getNotifications().iterator().next();
104 assertEquals(2, myNotification.getMustConstraints().size());
106 final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) barModule.getDataChildByName(
107 QName.create(barModule.getQNameModule(), "my-anyxml"));
108 assertNotNull(myAnyxml);
109 assertTrue(myAnyxml.getConstraints().isMandatory());
110 assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
114 public void testDeviateReplace() throws Exception {
115 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
116 sourceForResource("/deviation-resolution-test/deviation-replace/foo.yang"),
117 sourceForResource("/deviation-resolution-test/deviation-replace/bar.yang"));
118 assertNotNull(schemaContext);
120 final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
121 assertNotNull(barModule);
123 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
124 QName.create(barModule.getQNameModule(), "my-leaf"));
125 assertNotNull(myLeaf);
127 assertTrue(myLeaf.getType() instanceof Uint32TypeDefinition);
128 assertEquals(Optional.of("bytes"), myLeaf.getType().getUnits());
129 assertEquals(Optional.of("10"), myLeaf.getType().getDefaultValue());
131 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
132 QName.create(barModule.getQNameModule(), "my-leaf-list-test"));
133 assertNotNull(myLeafList);
135 assertEquals(6, myLeafList.getConstraints().getMaxElements().intValue());
136 assertEquals(3, myLeafList.getConstraints().getMinElements().intValue());
137 assertTrue(myLeafList.isConfiguration());
139 final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
140 QName.create(barModule.getQNameModule(), "my-choice"));
141 assertNotNull(myChoice);
143 assertFalse(myChoice.getConstraints().isMandatory());
144 assertEquals(1, myChoice.getUnknownSchemaNodes().size());
145 assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
147 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
148 QName.create(barModule.getQNameModule(), "my-cont"));
149 assertNotNull(myCont);
151 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
152 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
153 assertNotNull(myAugLeaf);
154 assertTrue(myAugLeaf.getType() instanceof Uint32TypeDefinition);
155 assertEquals(Optional.of("seconds"), myAugLeaf.getType().getUnits());
156 assertEquals(Optional.of("new-def-val"), myAugLeaf.getType().getDefaultValue());
157 assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
158 assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
160 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
161 QName.create(barModule.getQNameModule(), "my-used-leaf"));
162 assertNotNull(myUsedLeaf);
163 assertTrue(myUsedLeaf.getType() instanceof Uint32TypeDefinition);
164 assertEquals(Optional.of("weeks"), myUsedLeaf.getType().getUnits());
165 assertEquals(Optional.of("new-def-val"), myUsedLeaf.getType().getDefaultValue());
166 assertEquals(1, myUsedLeaf.getUnknownSchemaNodes().size());
167 assertEquals("new arg", myUsedLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
171 public void testDeviateDelete() throws Exception {
172 final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
173 sourceForResource("/deviation-resolution-test/deviation-delete/foo.yang"),
174 sourceForResource("/deviation-resolution-test/deviation-delete/bar.yang"));
175 assertNotNull(schemaContext);
177 final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
178 final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
179 QName.create(barModule.getQNameModule(), "my-leaf"));
180 assertNotNull(myLeaf);
182 assertEquals(Optional.empty(), myLeaf.getType().getDefaultValue());
183 assertEquals(Optional.empty(), myLeaf.getType().getUnits());
184 assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
186 final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
187 QName.create(barModule.getQNameModule(), "my-leaf-list"));
188 assertNotNull(myLeafList);
190 assertEquals(0, myLeafList.getDefaults().size());
191 assertEquals(0, myLeafList.getConstraints().getMustConstraints().size());
193 final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
194 QName.create(barModule.getQNameModule(), "my-list"));
195 assertNotNull(myList);
197 assertEquals(0, myList.getUniqueConstraints().size());
198 assertEquals(0, myList.getUnknownSchemaNodes().size());
200 final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
201 QName.create(barModule.getQNameModule(), "my-cont"));
202 assertNotNull(myCont);
204 final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
205 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
206 assertNotNull(myAugLeaf);
207 assertEquals(Optional.empty(), myAugLeaf.getType().getDefaultValue());
208 assertEquals(Optional.empty(), myAugLeaf.getType().getUnits());
209 assertEquals(0, myAugLeaf.getConstraints().getMustConstraints().size());
210 assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
212 final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
213 QName.create(barModule.getQNameModule(), "my-used-leaf"));
214 assertNotNull(myUsedLeaf);
215 assertEquals(Optional.empty(), myUsedLeaf.getType().getDefaultValue());
216 assertEquals(Optional.empty(), myUsedLeaf.getType().getUnits());
217 assertEquals(0, myUsedLeaf.getConstraints().getMustConstraints().size());
218 assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
222 public void shouldFailOnInvalidYang10Model() throws Exception {
224 StmtTestUtils.parseYangSources(
225 sourceForResource("/deviation-resolution-test/deviation-add/foo10-invalid.yang"),
226 sourceForResource("/deviation-resolution-test/deviation-add/bar10-invalid.yang"));
227 fail("An exception should have been thrown.");
228 } catch (final ReactorException ex) {
229 final Throwable cause = ex.getCause();
230 assertTrue(cause instanceof InvalidSubstatementException);
231 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
236 public void shouldFailOnInvalidYang10Model2() throws Exception {
238 StmtTestUtils.parseYangSources(
239 sourceForResource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang"),
240 sourceForResource("/deviation-resolution-test/deviation-delete/bar10-invalid.yang"));
241 fail("An exception should have been thrown.");
242 } catch (final ReactorException ex) {
243 final Throwable cause = ex.getCause();
244 assertTrue(cause instanceof InvalidSubstatementException);
245 assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
250 public void shouldFailOnInvalidDeviationTarget() throws Exception {
252 StmtTestUtils.parseYangSources(sourceForResource(
253 "/deviation-resolution-test/foo-invalid-deviation-target.yang"),
254 sourceForResource("/deviation-resolution-test/bar.yang"));
255 fail("An exception should have been thrown.");
256 } catch (final ReactorException ex) {
257 final Throwable cause = ex.getCause();
258 assertTrue(cause instanceof InferenceException);
259 assertTrue(cause.getMessage().startsWith("(bar?revision=2017-01-20)my-cont is not a valid deviation "
260 + "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
265 public void shouldFailOnInvalidDeviationPath() throws Exception {
267 StmtTestUtils.parseYangSources(
268 sourceForResource("/deviation-resolution-test/foo-invalid-deviation-path.yang"),
269 sourceForResource("/deviation-resolution-test/bar.yang"));
270 fail("An exception should have been thrown.");
271 } catch (final ReactorException ex) {
272 final Throwable cause = ex.getCause().getCause();
273 assertTrue(cause instanceof InferenceException);
274 assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(bar?revision=2017-01-20)"
275 + "invalid, (bar?revision=2017-01-20)path]}' not found"));
280 public void shouldFailOnInvalidDeviateAdd() throws Exception {
282 StmtTestUtils.parseYangSources(
283 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid.yang"),
284 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid.yang"));
285 fail("An exception should have been thrown.");
286 } catch (final ReactorException ex) {
287 final Throwable cause = ex.getCause();
288 assertTrue(cause instanceof InferenceException);
289 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
290 + ":yin:1)config to target node (bar?revision=2017-01-20)my-leaf because it is already defined in"
291 + " target and can appear only once."));
296 public void shouldFailOnInvalidDeviateAdd2() throws Exception {
298 StmtTestUtils.parseYangSources(
299 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang"),
300 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-2.yang"));
301 fail("An exception should have been thrown.");
302 } catch (final ReactorException ex) {
303 final Throwable cause = ex.getCause();
304 assertTrue(cause instanceof InferenceException);
305 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
306 + ":yin:1)default to target node (bar?revision=2017-01-20)my-leaf because it is already defined in"
307 + " target and can appear only once."));
312 public void shouldFailOnInvalidDeviateAdd3() throws Exception {
314 StmtTestUtils.parseYangSources(
315 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-4.yang"),
316 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-4.yang"));
317 fail("An exception should have been thrown.");
318 } catch (final ReactorException ex) {
319 final Throwable cause = ex.getCause();
320 assertTrue(cause instanceof InferenceException);
321 assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
322 + ":yin:1)default to target node (bar?revision=2017-02-01)my-used-leaf because it is already "
323 + "defined in target and can appear only once."));
328 public void shouldFailOnInvalidDeviateReplace() throws Exception {
330 StmtTestUtils.parseYangSources(
331 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid.yang"),
332 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid.yang"));
333 fail("An exception should have been thrown.");
334 } catch (final ReactorException ex) {
335 final Throwable cause = ex.getCause();
336 assertTrue(cause instanceof InferenceException);
337 assertTrue(cause.getMessage().startsWith("Deviation cannot replace substatement "
338 + "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (bar?revision=2017-01-20)my-leaf "
339 + "because it does not exist in target node."));
344 @SuppressWarnings("checkstyle:regexpSinglelineJava")
345 public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
346 final PrintStream stdout = System.out;
347 final ByteArrayOutputStream output = new ByteArrayOutputStream();
348 final String testLog;
350 System.setOut(new PrintStream(output, true, "UTF-8"));
352 StmtTestUtils.parseYangSources(
353 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang"),
354 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-2.yang"));
356 testLog = output.toString();
357 System.setOut(stdout);
358 assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default"
359 + " in target leaf-list (bar?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple "
360 + "default statements."));
364 @SuppressWarnings("checkstyle:regexpSinglelineJava")
365 public void shouldLogInvalidDeviateDeleteAttempt() 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-delete/foo-invalid.yang"),
374 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid.yang"));
376 testLog = output.toString();
377 System.setOut(stdout);
378 assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units "
379 + "with argument 'seconds' in target node (bar?revision=2017-01-20)my-leaf because it does not exist "
380 + "in the target node."));
384 public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
386 StmtTestUtils.parseYangSources(
387 sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang"),
388 sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-3.yang"));
389 fail("An exception should have been thrown.");
390 } catch (final ReactorException ex) {
391 final Throwable cause = ex.getCause();
392 assertTrue(cause instanceof InvalidSubstatementException);
393 assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
398 public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
400 StmtTestUtils.parseYangSources(
401 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang"),
402 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-3.yang"));
403 fail("An exception should have been thrown.");
404 } catch (final ReactorException ex) {
405 final Throwable cause = ex.getCause();
406 assertTrue(cause instanceof InvalidSubstatementException);
407 assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
412 public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
414 StmtTestUtils.parseYangSources(
415 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang"),
416 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid-2.yang"));
417 fail("An exception should have been thrown.");
418 } catch (final ReactorException ex) {
419 final Throwable cause = ex.getCause();
420 assertTrue(cause instanceof InvalidSubstatementException);
421 assertTrue(cause.getMessage().startsWith("CONFIG is not valid for DEVIATE."));