YANGTOOLS-621: introduce specialized integer types
[yangtools.git] / yang / yang-parser-impl / src / test / java / org / opendaylight / yangtools / yang / stmt / DeviationResolutionTest.java
1 /*
2  * Copyright (c) 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.yangtools.yang.stmt;
10
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;
18
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;
39
40 public class DeviationResolutionTest {
41
42     @Test
43     public void testDeviateNotSupported() throws Exception {
44         final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
45                 "/deviation-resolution-test/deviation-not-supported");
46         assertNotNull(schemaContext);
47
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);
52
53         assertEquals(1, myContA.getChildNodes().size());
54         assertNotNull(myContA.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-a3")));
55
56         final ContainerSchemaNode myContB = (ContainerSchemaNode) importedModule.getDataChildByName(
57                 QName.create(importedModule.getQNameModule(), "my-cont-b"));
58         assertNull(myContB);
59
60         final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
61                 QName.create(importedModule.getQNameModule(), "my-cont-c"));
62         assertNotNull(myContC);
63
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")));
67     }
68
69     @Test
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);
75
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);
80
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());
86
87         final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
88                 QName.create(barModule.getQNameModule(), "my-list"));
89         assertNotNull(myList);
90         assertEquals(2, myList.getUniqueConstraints().size());
91
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());
96
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());
102
103         final NotificationDefinition myNotification = barModule.getNotifications().iterator().next();
104         assertEquals(2, myNotification.getMustConstraints().size());
105
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());
111     }
112
113     @Test
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);
119
120         final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
121         assertNotNull(barModule);
122
123         final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
124                 QName.create(barModule.getQNameModule(), "my-leaf"));
125         assertNotNull(myLeaf);
126
127         assertTrue(myLeaf.getType() instanceof Uint32TypeDefinition);
128         assertEquals(Optional.of("bytes"), myLeaf.getType().getUnits());
129         assertEquals(Optional.of("10"), myLeaf.getType().getDefaultValue());
130
131         final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
132                 QName.create(barModule.getQNameModule(), "my-leaf-list-test"));
133         assertNotNull(myLeafList);
134
135         assertEquals(6, myLeafList.getConstraints().getMaxElements().intValue());
136         assertEquals(3, myLeafList.getConstraints().getMinElements().intValue());
137         assertTrue(myLeafList.isConfiguration());
138
139         final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
140                 QName.create(barModule.getQNameModule(), "my-choice"));
141         assertNotNull(myChoice);
142
143         assertFalse(myChoice.getConstraints().isMandatory());
144         assertEquals(1, myChoice.getUnknownSchemaNodes().size());
145         assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
146
147         final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
148                 QName.create(barModule.getQNameModule(), "my-cont"));
149         assertNotNull(myCont);
150
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());
159
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());
168     }
169
170     @Test
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);
176
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);
181
182         assertEquals(Optional.empty(), myLeaf.getType().getDefaultValue());
183         assertEquals(Optional.empty(), myLeaf.getType().getUnits());
184         assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
185
186         final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
187                 QName.create(barModule.getQNameModule(), "my-leaf-list"));
188         assertNotNull(myLeafList);
189
190         assertEquals(0, myLeafList.getDefaults().size());
191         assertEquals(0, myLeafList.getConstraints().getMustConstraints().size());
192
193         final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
194                 QName.create(barModule.getQNameModule(), "my-list"));
195         assertNotNull(myList);
196
197         assertEquals(0, myList.getUniqueConstraints().size());
198         assertEquals(0, myList.getUnknownSchemaNodes().size());
199
200         final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
201                 QName.create(barModule.getQNameModule(), "my-cont"));
202         assertNotNull(myCont);
203
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());
211
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());
219     }
220
221     @Test
222     public void shouldFailOnInvalidYang10Model() throws Exception {
223         try {
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."));
232         }
233     }
234
235     @Test
236     public void shouldFailOnInvalidYang10Model2() throws Exception {
237         try {
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."));
246         }
247     }
248
249     @Test
250     public void shouldFailOnInvalidDeviationTarget() throws Exception {
251         try {
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."));
261         }
262     }
263
264     @Test
265     public void shouldFailOnInvalidDeviationPath() throws Exception {
266         try {
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"));
276         }
277     }
278
279     @Test
280     public void shouldFailOnInvalidDeviateAdd() throws Exception {
281         try {
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."));
292         }
293     }
294
295     @Test
296     public void shouldFailOnInvalidDeviateAdd2() throws Exception {
297         try {
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."));
308         }
309     }
310
311     @Test
312     public void shouldFailOnInvalidDeviateAdd3() throws Exception {
313         try {
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."));
324         }
325     }
326
327     @Test
328     public void shouldFailOnInvalidDeviateReplace() throws Exception {
329         try {
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."));
340         }
341     }
342
343     @Test
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;
349
350         System.setOut(new PrintStream(output, true, "UTF-8"));
351
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"));
355
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."));
361     }
362
363     @Test
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;
369
370         System.setOut(new PrintStream(output, true, "UTF-8"));
371
372         StmtTestUtils.parseYangSources(
373                 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid.yang"),
374                 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid.yang"));
375
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."));
381     }
382
383     @Test
384     public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
385         try {
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."));
394         }
395     }
396
397     @Test
398     public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
399         try {
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."));
408         }
409     }
410
411     @Test
412     public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
413         try {
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."));
422         }
423     }
424 }