Adjust test suite parser update to conform with API changes
[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.ElementCountConstraint;
29 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.Module;
33 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
34 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
35 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
36 import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition;
37 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
38 import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
39 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
40
41 public class DeviationResolutionTest {
42
43     @Test
44     public void testDeviateNotSupported() throws Exception {
45         final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
46                 "/deviation-resolution-test/deviation-not-supported");
47         assertNotNull(schemaContext);
48
49         final Module importedModule = schemaContext.findModule("imported", Revision.of("2017-01-20")).get();
50         final ContainerSchemaNode myContA = (ContainerSchemaNode) importedModule.getDataChildByName(
51                 QName.create(importedModule.getQNameModule(), "my-cont-a"));
52         assertNotNull(myContA);
53
54         assertEquals(1, myContA.getChildNodes().size());
55         assertNotNull(myContA.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-a3")));
56
57         final ContainerSchemaNode myContB = (ContainerSchemaNode) importedModule.getDataChildByName(
58                 QName.create(importedModule.getQNameModule(), "my-cont-b"));
59         assertNull(myContB);
60
61         final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
62                 QName.create(importedModule.getQNameModule(), "my-cont-c"));
63         assertNotNull(myContC);
64
65         assertEquals(2, myContC.getChildNodes().size());
66         assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
67         assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
68     }
69
70     @Test
71     public void testDeviateAdd() throws Exception {
72         final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
73                 sourceForResource("/deviation-resolution-test/deviation-add/foo.yang"),
74                 sourceForResource("/deviation-resolution-test/deviation-add/bar.yang"));
75         assertNotNull(schemaContext);
76
77         final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
78         final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
79                 QName.create(barModule.getQNameModule(), "my-leaf-list"));
80         assertNotNull(myLeafList);
81
82         assertFalse(myLeafList.isConfiguration());
83         assertEquals(3, myLeafList.getDefaults().size());
84
85         final ElementCountConstraint constraint = myLeafList.getElementCountConstraint().get();
86         assertEquals(10, constraint.getMaxElements().intValue());
87         assertEquals(5, constraint.getMinElements().intValue());
88         assertNotNull(myLeafList.getType().getUnits());
89
90         final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
91                 QName.create(barModule.getQNameModule(), "my-list"));
92         assertNotNull(myList);
93         assertEquals(2, myList.getUniqueConstraints().size());
94
95         final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
96                 QName.create(barModule.getQNameModule(), "my-choice"));
97         assertNotNull(myChoice);
98         assertEquals("c2", myChoice.getDefaultCase().get().getQName().getLocalName());
99
100         final RpcDefinition myRpc = barModule.getRpcs().iterator().next();
101         final ContainerSchemaNode input = myRpc.getInput();
102         assertEquals(2, input.getMustConstraints().size());
103         final ContainerSchemaNode output = myRpc.getOutput();
104         assertEquals(2, output.getMustConstraints().size());
105
106         final NotificationDefinition myNotification = barModule.getNotifications().iterator().next();
107         assertEquals(2, myNotification.getMustConstraints().size());
108
109         final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) barModule.getDataChildByName(
110                 QName.create(barModule.getQNameModule(), "my-anyxml"));
111         assertNotNull(myAnyxml);
112         assertTrue(myAnyxml.isMandatory());
113         assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
114     }
115
116     @Test
117     public void testDeviateReplace() throws Exception {
118         final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
119                 sourceForResource("/deviation-resolution-test/deviation-replace/foo.yang"),
120                 sourceForResource("/deviation-resolution-test/deviation-replace/bar.yang"));
121         assertNotNull(schemaContext);
122
123         final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
124         assertNotNull(barModule);
125
126         final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
127                 QName.create(barModule.getQNameModule(), "my-leaf"));
128         assertNotNull(myLeaf);
129
130         assertTrue(myLeaf.getType() instanceof Uint32TypeDefinition);
131         assertEquals(Optional.of("bytes"), myLeaf.getType().getUnits());
132         assertEquals(Optional.of("10"), myLeaf.getType().getDefaultValue());
133
134         final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
135                 QName.create(barModule.getQNameModule(), "my-leaf-list-test"));
136         assertNotNull(myLeafList);
137
138         final ElementCountConstraint constraint = myLeafList.getElementCountConstraint().get();
139         assertEquals(6, constraint.getMaxElements().intValue());
140         assertEquals(3, constraint.getMinElements().intValue());
141         assertTrue(myLeafList.isConfiguration());
142
143         final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) barModule.getDataChildByName(
144                 QName.create(barModule.getQNameModule(), "my-choice"));
145         assertNotNull(myChoice);
146
147         assertFalse(myChoice.isMandatory());
148         assertEquals(1, myChoice.getUnknownSchemaNodes().size());
149         assertEquals("new arg", myChoice.getUnknownSchemaNodes().iterator().next().getNodeParameter());
150
151         final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
152                 QName.create(barModule.getQNameModule(), "my-cont"));
153         assertNotNull(myCont);
154
155         final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
156                 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
157         assertNotNull(myAugLeaf);
158         assertTrue(myAugLeaf.getType() instanceof Uint32TypeDefinition);
159         assertEquals(Optional.of("seconds"), myAugLeaf.getType().getUnits());
160         assertEquals(Optional.of("new-def-val"), myAugLeaf.getType().getDefaultValue());
161         assertEquals(1, myAugLeaf.getUnknownSchemaNodes().size());
162         assertEquals("new arg", myAugLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
163
164         final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
165                 QName.create(barModule.getQNameModule(), "my-used-leaf"));
166         assertNotNull(myUsedLeaf);
167         assertTrue(myUsedLeaf.getType() instanceof Uint32TypeDefinition);
168         assertEquals(Optional.of("weeks"), myUsedLeaf.getType().getUnits());
169         assertEquals(Optional.of("new-def-val"), myUsedLeaf.getType().getDefaultValue());
170         assertEquals(1, myUsedLeaf.getUnknownSchemaNodes().size());
171         assertEquals("new arg", myUsedLeaf.getUnknownSchemaNodes().iterator().next().getNodeParameter());
172     }
173
174     @Test
175     public void testDeviateDelete() throws Exception {
176         final SchemaContext schemaContext = StmtTestUtils.parseYangSources(
177                 sourceForResource("/deviation-resolution-test/deviation-delete/foo.yang"),
178                 sourceForResource("/deviation-resolution-test/deviation-delete/bar.yang"));
179         assertNotNull(schemaContext);
180
181         final Module barModule = schemaContext.findModule("bar", Revision.of("2017-01-20")).get();
182         final LeafSchemaNode myLeaf = (LeafSchemaNode) barModule.getDataChildByName(
183                 QName.create(barModule.getQNameModule(), "my-leaf"));
184         assertNotNull(myLeaf);
185
186         assertEquals(Optional.empty(), myLeaf.getType().getDefaultValue());
187         assertEquals(Optional.empty(), myLeaf.getType().getUnits());
188         assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
189
190         final LeafListSchemaNode myLeafList = (LeafListSchemaNode) barModule.getDataChildByName(
191                 QName.create(barModule.getQNameModule(), "my-leaf-list"));
192         assertNotNull(myLeafList);
193
194         assertEquals(0, myLeafList.getDefaults().size());
195         assertEquals(0, myLeafList.getMustConstraints().size());
196
197         final ListSchemaNode myList = (ListSchemaNode) barModule.getDataChildByName(
198                 QName.create(barModule.getQNameModule(), "my-list"));
199         assertNotNull(myList);
200
201         assertEquals(0, myList.getUniqueConstraints().size());
202         assertEquals(0, myList.getUnknownSchemaNodes().size());
203
204         final ContainerSchemaNode myCont = (ContainerSchemaNode) barModule.getDataChildByName(
205                 QName.create(barModule.getQNameModule(), "my-cont"));
206         assertNotNull(myCont);
207
208         final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
209                 QName.create(barModule.getQNameModule(), "my-aug-leaf"));
210         assertNotNull(myAugLeaf);
211         assertEquals(Optional.empty(), myAugLeaf.getType().getDefaultValue());
212         assertEquals(Optional.empty(), myAugLeaf.getType().getUnits());
213         assertEquals(0, myAugLeaf.getMustConstraints().size());
214         assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
215
216         final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
217                 QName.create(barModule.getQNameModule(), "my-used-leaf"));
218         assertNotNull(myUsedLeaf);
219         assertEquals(Optional.empty(), myUsedLeaf.getType().getDefaultValue());
220         assertEquals(Optional.empty(), myUsedLeaf.getType().getUnits());
221         assertEquals(0, myUsedLeaf.getMustConstraints().size());
222         assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
223     }
224
225     @Test
226     public void shouldFailOnInvalidYang10Model() throws Exception {
227         try {
228             StmtTestUtils.parseYangSources(
229                     sourceForResource("/deviation-resolution-test/deviation-add/foo10-invalid.yang"),
230                     sourceForResource("/deviation-resolution-test/deviation-add/bar10-invalid.yang"));
231             fail("An exception should have been thrown.");
232         } catch (final ReactorException ex) {
233             final Throwable cause = ex.getCause();
234             assertTrue(cause instanceof InvalidSubstatementException);
235             assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
236         }
237     }
238
239     @Test
240     public void shouldFailOnInvalidYang10Model2() throws Exception {
241         try {
242             StmtTestUtils.parseYangSources(
243                     sourceForResource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang"),
244                     sourceForResource("/deviation-resolution-test/deviation-delete/bar10-invalid.yang"));
245             fail("An exception should have been thrown.");
246         } catch (final ReactorException ex) {
247             final Throwable cause = ex.getCause();
248             assertTrue(cause instanceof InvalidSubstatementException);
249             assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
250         }
251     }
252
253     @Test
254     public void shouldFailOnInvalidDeviationTarget() throws Exception {
255         try {
256             StmtTestUtils.parseYangSources(sourceForResource(
257                     "/deviation-resolution-test/foo-invalid-deviation-target.yang"),
258                     sourceForResource("/deviation-resolution-test/bar.yang"));
259             fail("An exception should have been thrown.");
260         } catch (final ReactorException ex) {
261             final Throwable cause = ex.getCause();
262             assertTrue(cause instanceof InferenceException);
263             assertTrue(cause.getMessage().startsWith("(bar?revision=2017-01-20)my-cont is not a valid deviation "
264                     + "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
265         }
266     }
267
268     @Test
269     public void shouldFailOnInvalidDeviationPath() throws Exception {
270         try {
271             StmtTestUtils.parseYangSources(
272                     sourceForResource("/deviation-resolution-test/foo-invalid-deviation-path.yang"),
273                     sourceForResource("/deviation-resolution-test/bar.yang"));
274             fail("An exception should have been thrown.");
275         } catch (final ReactorException ex) {
276             final Throwable cause = ex.getCause().getCause();
277             assertTrue(cause instanceof InferenceException);
278             assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(bar?revision=2017-01-20)"
279                     + "invalid, (bar?revision=2017-01-20)path]}' not found"));
280         }
281     }
282
283     @Test
284     public void shouldFailOnInvalidDeviateAdd() throws Exception {
285         try {
286             StmtTestUtils.parseYangSources(
287                     sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid.yang"),
288                     sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid.yang"));
289             fail("An exception should have been thrown.");
290         } catch (final ReactorException ex) {
291             final Throwable cause = ex.getCause();
292             assertTrue(cause instanceof InferenceException);
293             assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang"
294                     + ":yin:1)config to target node (bar?revision=2017-01-20)my-leaf because it is already defined in"
295                     + " target and can appear only once."));
296         }
297     }
298
299     @Test
300     public void shouldFailOnInvalidDeviateAdd2() throws Exception {
301         try {
302             StmtTestUtils.parseYangSources(
303                     sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang"),
304                     sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-2.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)default to target node (bar?revision=2017-01-20)my-leaf because it is already defined in"
311                     + " target and can appear only once."));
312         }
313     }
314
315     @Test
316     public void shouldFailOnInvalidDeviateAdd3() throws Exception {
317         try {
318             StmtTestUtils.parseYangSources(
319                     sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-4.yang"),
320                     sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-4.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-02-01)my-used-leaf because it is already "
327                     + "defined in target and can appear only once."));
328         }
329     }
330
331     @Test
332     public void shouldFailOnInvalidDeviateReplace() throws Exception {
333         try {
334             StmtTestUtils.parseYangSources(
335                     sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid.yang"),
336                     sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid.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 replace substatement "
342                     + "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (bar?revision=2017-01-20)my-leaf "
343                     + "because it does not exist in target node."));
344         }
345     }
346
347     @Test
348     @SuppressWarnings("checkstyle:regexpSinglelineJava")
349     public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
350         final PrintStream stdout = System.out;
351         final ByteArrayOutputStream output = new ByteArrayOutputStream();
352         final String testLog;
353
354         System.setOut(new PrintStream(output, true, "UTF-8"));
355
356         StmtTestUtils.parseYangSources(
357                 sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang"),
358                 sourceForResource("/deviation-resolution-test/deviation-replace/bar-invalid-2.yang"));
359
360         testLog = output.toString();
361         System.setOut(stdout);
362         assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default"
363                 + " in target leaf-list (bar?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple "
364                 + "default statements."));
365     }
366
367     @Test
368     @SuppressWarnings("checkstyle:regexpSinglelineJava")
369     public void shouldLogInvalidDeviateDeleteAttempt() throws Exception {
370         final PrintStream stdout = System.out;
371         final ByteArrayOutputStream output = new ByteArrayOutputStream();
372         final String testLog;
373
374         System.setOut(new PrintStream(output, true, "UTF-8"));
375
376         StmtTestUtils.parseYangSources(
377                 sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid.yang"),
378                 sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid.yang"));
379
380         testLog = output.toString();
381         System.setOut(stdout);
382         assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units "
383                 + "with argument 'seconds' in target node (bar?revision=2017-01-20)my-leaf because it does not exist "
384                 + "in the target node."));
385     }
386
387     @Test
388     public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
389         try {
390             StmtTestUtils.parseYangSources(
391                     sourceForResource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang"),
392                     sourceForResource("/deviation-resolution-test/deviation-add/bar-invalid-3.yang"));
393             fail("An exception should have been thrown.");
394         } catch (final ReactorException ex) {
395             final Throwable cause = ex.getCause();
396             assertTrue(cause instanceof InvalidSubstatementException);
397             assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
398         }
399     }
400
401     @Test
402     public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
403         try {
404             StmtTestUtils.parseYangSources(
405                     sourceForResource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang"),
406                     sourceForResource("/deviation-resolution-test/deviation-replace/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("MUST is not valid for DEVIATE."));
412         }
413     }
414
415     @Test
416     public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
417         try {
418             StmtTestUtils.parseYangSources(
419                     sourceForResource("/deviation-resolution-test/deviation-delete/foo-invalid-2.yang"),
420                     sourceForResource("/deviation-resolution-test/deviation-delete/bar-invalid-2.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("CONFIG is not valid for DEVIATE."));
426         }
427     }
428 }