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