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