4f716aa4c0b26b05221b4c841699188cdaba6f9c
[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
18 import java.io.ByteArrayOutputStream;
19 import java.io.PrintStream;
20 import java.util.Date;
21 import org.junit.Test;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
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 Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
48
49         final Module rootModule = schemaContext.findModuleByName("root", revision);
50         assertNotNull(rootModule);
51
52         final ContainerSchemaNode myContA = (ContainerSchemaNode) rootModule.getDataChildByName(
53                 QName.create(rootModule.getQNameModule(), "my-cont-a"));
54         assertNotNull(myContA);
55
56         assertEquals(1, myContA.getChildNodes().size());
57         assertNotNull(myContA.getDataChildByName(QName.create(rootModule.getQNameModule(), "my-leaf-a3")));
58
59         final ContainerSchemaNode myContB = (ContainerSchemaNode) rootModule.getDataChildByName(
60                 QName.create(rootModule.getQNameModule(), "my-cont-b"));
61         assertNull(myContB);
62
63         final Module importedModule = schemaContext.findModuleByName("imported", revision);
64         assertNotNull(importedModule);
65
66         final ContainerSchemaNode myContC = (ContainerSchemaNode) importedModule.getDataChildByName(
67                 QName.create(importedModule.getQNameModule(), "my-cont-c"));
68         assertNotNull(myContC);
69
70         assertEquals(2, myContC.getChildNodes().size());
71         assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c1")));
72         assertNotNull(myContC.getDataChildByName(QName.create(importedModule.getQNameModule(), "my-leaf-c2")));
73     }
74
75     @Test
76     public void testDeviateAdd() throws Exception {
77         final SchemaContext schemaContext = StmtTestUtils.parseYangSource(
78                 "/deviation-resolution-test/deviation-add/foo.yang");
79         assertNotNull(schemaContext);
80
81         final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
82
83         final Module fooModule = schemaContext.findModuleByName("foo", revision);
84         assertNotNull(fooModule);
85
86         final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
87                 QName.create(fooModule.getQNameModule(), "my-leaf-list"));
88         assertNotNull(myLeafList);
89
90         assertFalse(myLeafList.isConfiguration());
91         assertEquals(3, myLeafList.getDefaults().size());
92         assertEquals(10, myLeafList.getConstraints().getMaxElements().intValue());
93         assertEquals(5, myLeafList.getConstraints().getMinElements().intValue());
94         assertNotNull(myLeafList.getType().getUnits());
95
96         final ListSchemaNode myList = (ListSchemaNode) fooModule.getDataChildByName(
97                 QName.create(fooModule.getQNameModule(), "my-list"));
98         assertNotNull(myList);
99         assertEquals(2, myList.getUniqueConstraints().size());
100
101         final ChoiceSchemaNode myChoice = (ChoiceSchemaNode) fooModule.getDataChildByName(
102                 QName.create(fooModule.getQNameModule(), "my-choice"));
103         assertNotNull(myChoice);
104         assertEquals("c2", myChoice.getDefaultCase());
105
106         final RpcDefinition myRpc = fooModule.getRpcs().iterator().next();
107         final ContainerSchemaNode input = myRpc.getInput();
108         assertEquals(2, input.getConstraints().getMustConstraints().size());
109         final ContainerSchemaNode output = myRpc.getOutput();
110         assertEquals(2, output.getConstraints().getMustConstraints().size());
111
112         final NotificationDefinition myNotification = fooModule.getNotifications().iterator().next();
113         assertEquals(2, myNotification.getConstraints().getMustConstraints().size());
114
115         final AnyXmlSchemaNode myAnyxml = (AnyXmlSchemaNode) fooModule.getDataChildByName(
116                 QName.create(fooModule.getQNameModule(), "my-anyxml"));
117         assertNotNull(myAnyxml);
118         assertTrue(myAnyxml.getConstraints().isMandatory());
119         assertEquals(2, myAnyxml.getUnknownSchemaNodes().size());
120     }
121
122     @Test
123     public void testDeviateReplace() throws Exception {
124         final SchemaContext schemaContext = StmtTestUtils.parseYangSource(
125                 "/deviation-resolution-test/deviation-replace/foo.yang");
126         assertNotNull(schemaContext);
127
128         final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
129
130         final Module fooModule = schemaContext.findModuleByName("foo", revision);
131         assertNotNull(fooModule);
132
133         final LeafSchemaNode myLeaf = (LeafSchemaNode) fooModule.getDataChildByName(
134                 QName.create(fooModule.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) fooModule.getDataChildByName(
144                 QName.create(fooModule.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) fooModule.getDataChildByName(
152                 QName.create(fooModule.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) fooModule.getDataChildByName(
160                 QName.create(fooModule.getQNameModule(), "my-cont"));
161         assertNotNull(myCont);
162
163         final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
164                 QName.create(fooModule.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(fooModule.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.parseYangSource(
189                 "/deviation-resolution-test/deviation-delete/foo.yang");
190         assertNotNull(schemaContext);
191
192         final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-20");
193
194         final Module fooModule = schemaContext.findModuleByName("foo", revision);
195         assertNotNull(fooModule);
196
197         final LeafSchemaNode myLeaf = (LeafSchemaNode) fooModule.getDataChildByName(
198                 QName.create(fooModule.getQNameModule(), "my-leaf"));
199         assertNotNull(myLeaf);
200
201         assertNull(myLeaf.getDefault());
202         assertNull(myLeaf.getUnits());
203         assertEquals(0, myLeaf.getUnknownSchemaNodes().size());
204
205         final LeafListSchemaNode myLeafList = (LeafListSchemaNode) fooModule.getDataChildByName(
206                 QName.create(fooModule.getQNameModule(), "my-leaf-list"));
207         assertNotNull(myLeafList);
208
209         assertEquals(0, myLeafList.getDefaults().size());
210         assertEquals(0, myLeafList.getConstraints().getMustConstraints().size());
211
212         final ListSchemaNode myList = (ListSchemaNode) fooModule.getDataChildByName(
213                 QName.create(fooModule.getQNameModule(), "my-list"));
214         assertNotNull(myList);
215
216         assertEquals(0, myList.getUniqueConstraints().size());
217         assertEquals(0, myList.getUnknownSchemaNodes().size());
218
219         final ContainerSchemaNode myCont = (ContainerSchemaNode) fooModule.getDataChildByName(
220                 QName.create(fooModule.getQNameModule(), "my-cont"));
221         assertNotNull(myCont);
222
223         final LeafSchemaNode myAugLeaf = (LeafSchemaNode) myCont.getDataChildByName(
224                 QName.create(fooModule.getQNameModule(), "my-aug-leaf"));
225         assertNotNull(myAugLeaf);
226         assertNull(myAugLeaf.getDefault());
227         assertNull(myAugLeaf.getUnits());
228         assertEquals(0, myAugLeaf.getConstraints().getMustConstraints().size());
229         assertEquals(0, myAugLeaf.getUnknownSchemaNodes().size());
230
231         final LeafSchemaNode myUsedLeaf = (LeafSchemaNode) myCont.getDataChildByName(
232                 QName.create(fooModule.getQNameModule(), "my-used-leaf"));
233         assertNotNull(myUsedLeaf);
234         assertNull(myUsedLeaf.getDefault());
235         assertNull(myUsedLeaf.getUnits());
236         assertEquals(0, myUsedLeaf.getConstraints().getMustConstraints().size());
237         assertEquals(0, myUsedLeaf.getUnknownSchemaNodes().size());
238     }
239
240     @Test
241     public void shouldFailOnInvalidYang10Model() throws Exception {
242         try {
243             StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo10-invalid.yang");
244             fail("An exception should have been thrown.");
245         } catch (final ReactorException ex) {
246             final Throwable cause = ex.getCause();
247             assertTrue(cause instanceof InvalidSubstatementException);
248             assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
249         }
250     }
251
252     @Test
253     public void shouldFailOnInvalidYang10Model2() throws Exception {
254         try {
255             StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo10-invalid.yang");
256             fail("An exception should have been thrown.");
257         } catch (final ReactorException ex) {
258             final Throwable cause = ex.getCause();
259             assertTrue(cause instanceof InvalidSubstatementException);
260             assertTrue(cause.getMessage().startsWith("Maximal count of DEFAULT for DEVIATE is 1, detected 2."));
261         }
262     }
263
264     @Test
265     public void shouldFailOnInvalidDeviationTarget() throws Exception {
266         try {
267             StmtTestUtils.parseYangSource("/deviation-resolution-test/foo-invalid-deviation-target.yang");
268             fail("An exception should have been thrown.");
269         } catch (final ReactorException ex) {
270             final Throwable cause = ex.getCause();
271             assertTrue(cause instanceof InferenceException);
272             assertTrue(cause.getMessage().startsWith("(foo?revision=2017-01-20)my-cont is not a valid deviation " +
273                     "target for substatement (urn:ietf:params:xml:ns:yang:yin:1)max-elements."));
274         }
275     }
276
277     @Test
278     public void shouldFailOnInvalidDeviationPath() throws Exception {
279         try {
280             StmtTestUtils.parseYangSource("/deviation-resolution-test/foo-invalid-deviation-path.yang");
281             fail("An exception should have been thrown.");
282         } catch (final ReactorException ex) {
283             final Throwable cause = ex.getCause().getCause();
284             assertTrue(cause instanceof InferenceException);
285             assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(foo?revision=2017-01-20)invalid, " +
286                     "(foo?revision=2017-01-20)path]}' not found"));
287         }
288     }
289
290     @Test
291     public void shouldFailOnInvalidDeviateAdd() throws Exception {
292         try {
293             StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid.yang");
294             fail("An exception should have been thrown.");
295         } catch (final ReactorException ex) {
296             final Throwable cause = ex.getCause();
297             assertTrue(cause instanceof InferenceException);
298             assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
299                     ":yin:1)config to target node (foo?revision=2017-01-20)my-leaf because it is already defined in" +
300                     " target and can appear only once."));
301         }
302     }
303
304     @Test
305     public void shouldFailOnInvalidDeviateAdd2() throws Exception {
306         try {
307             StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid-2.yang");
308             fail("An exception should have been thrown.");
309         } catch (final ReactorException ex) {
310             final Throwable cause = ex.getCause();
311             assertTrue(cause instanceof InferenceException);
312             assertTrue(cause.getMessage().startsWith("Deviation cannot add substatement (urn:ietf:params:xml:ns:yang" +
313                     ":yin:1)default to target node (foo?revision=2017-01-20)my-leaf because it is already defined in" +
314                     " target and can appear only once."));
315         }
316     }
317
318     @Test
319     public void shouldFailOnInvalidDeviateAdd3() throws Exception {
320         try {
321             StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-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 (foo?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.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid.yang");
336             fail("An exception should have been thrown.");
337         } catch (final ReactorException ex) {
338             final Throwable cause = ex.getCause();
339             assertTrue(cause instanceof InferenceException);
340             assertTrue(cause.getMessage().startsWith("Deviation cannot replace substatement " +
341                     "(urn:ietf:params:xml:ns:yang:yin:1)units in target node (foo?revision=2017-01-20)my-leaf " +
342                     "because it does not exist in target node."));
343         }
344     }
345
346     @Test
347     public void shouldLogInvalidDeviateReplaceAttempt() throws Exception {
348         final PrintStream stdout = System.out;
349         final ByteArrayOutputStream output = new ByteArrayOutputStream();
350         final String testLog;
351
352         System.setOut(new PrintStream(output, true, "UTF-8"));
353
354         StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid-2.yang");
355
356         testLog = output.toString();
357         assertTrue(testLog.contains("Deviation cannot replace substatement (urn:ietf:params:xml:ns:yang:yin:1)default" +
358                 " in target leaf-list (foo?revision=2017-01-20)my-leaf-list because a leaf-list can have multiple " +
359                 "default statements."));
360         System.setOut(stdout);
361     }
362
363     @Test
364     public void shouldLogInvalidDeviateDeleteAttempt() 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.parseYangSource("/deviation-resolution-test/deviation-delete/foo-invalid.yang");
372
373         testLog = output.toString();
374         assertTrue(testLog.contains("Deviation cannot delete substatement (urn:ietf:params:xml:ns:yang:yin:1)units " +
375                 "with argument 'seconds' in target node (foo?revision=2017-01-20)my-leaf because it does not exist " +
376                 "in the target node."));
377         System.setOut(stdout);
378     }
379
380     @Test
381     public void shouldFailOnInvalidDeviateAddSubstatement() throws Exception {
382         try {
383             StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-add/foo-invalid-3.yang");
384             fail("An exception should have been thrown.");
385         } catch (final ReactorException ex) {
386             final Throwable cause = ex.getCause();
387             assertTrue(cause instanceof InvalidSubstatementException);
388             assertTrue(cause.getMessage().startsWith("TYPE is not valid for DEVIATE."));
389         }
390     }
391
392     @Test
393     public void shouldFailOnInvalidDeviateReplaceSubstatement() throws Exception {
394         try {
395             StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-replace/foo-invalid-3.yang");
396             fail("An exception should have been thrown.");
397         } catch (final ReactorException ex) {
398             final Throwable cause = ex.getCause();
399             assertTrue(cause instanceof InvalidSubstatementException);
400             assertTrue(cause.getMessage().startsWith("MUST is not valid for DEVIATE."));
401         }
402     }
403
404     @Test
405     public void shouldFailOnInvalidDeviateDeleteSubstatement() throws Exception {
406         try {
407             StmtTestUtils.parseYangSource("/deviation-resolution-test/deviation-delete/foo-invalid-2.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("CONFIG is not valid for DEVIATE."));
413         }
414     }
415 }