Bug 4540: Yang parser exceptions should follow consistent path
[yangtools.git] / yang / yang-parser-impl / src / test / java / org / opendaylight / yangtools / yang / stmt / retest / YangParserTest.java
1 /*
2  * Copyright (c) 2013 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 package org.opendaylight.yangtools.yang.stmt.retest;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import java.io.File;
17 import java.io.IOException;
18 import java.net.URI;
19 import java.net.URISyntaxException;
20 import java.text.DateFormat;
21 import java.text.ParseException;
22 import java.text.SimpleDateFormat;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Date;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Set;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.common.YangConstants;
33 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
34 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
35 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
37 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.Deviation;
40 import org.opendaylight.yangtools.yang.model.api.Deviation.Deviate;
41 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
42 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
43 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.Module;
46 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
47 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
48 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
49 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
50 import org.opendaylight.yangtools.yang.model.api.Status;
51 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
52 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
53 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
54 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
55 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
56 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
57 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
58 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
59 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
60 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
61 import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
62 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
63 import org.opendaylight.yangtools.yang.model.util.type.BaseTypes;
64 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
65 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
66 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
67 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
68 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl;
69 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext;
70 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
71
72 public class YangParserTest {
73     public static final String FS = File.separator;
74
75     private final URI fooNS = URI.create("urn:opendaylight.foo");
76     private final URI barNS = URI.create("urn:opendaylight.bar");
77     private final URI bazNS = URI.create("urn:opendaylight.baz");
78     private Date fooRev;
79     private Date barRev;
80     private Date bazRev;
81
82     private Set<Module> modules;
83
84     @Before
85     public void init() throws Exception {
86         DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
87         fooRev = simpleDateFormat.parse("2013-02-27");
88         barRev = simpleDateFormat.parse("2013-07-03");
89         bazRev = simpleDateFormat.parse("2013-02-27");
90
91         modules = TestUtils.loadModules(getClass().getResource("/model").toURI());
92         assertEquals(3, modules.size());
93     }
94
95     @Test
96     public void testHeaders() throws ParseException {
97         Module foo = TestUtils.findModule(modules, "foo");
98
99         assertEquals("foo", foo.getName());
100         assertEquals("1", foo.getYangVersion());
101         assertEquals(fooNS, foo.getNamespace());
102         assertEquals("foo", foo.getPrefix());
103
104         Set<ModuleImport> imports = foo.getImports();
105         assertEquals(2, imports.size());
106
107         ModuleImport import2 = TestUtils.findImport(imports, "br");
108         assertEquals("bar", import2.getModuleName());
109         assertEquals(barRev, import2.getRevision());
110
111         ModuleImport import3 = TestUtils.findImport(imports, "bz");
112         assertEquals("baz", import3.getModuleName());
113         assertEquals(bazRev, import3.getRevision());
114
115         assertEquals("opendaylight", foo.getOrganization());
116         assertEquals("http://www.opendaylight.org/", foo.getContact());
117         Date expectedRevision = TestUtils.createDate("2013-02-27");
118         assertEquals(expectedRevision, foo.getRevision());
119         assertEquals(" WILL BE DEFINED LATER", foo.getReference());
120     }
121
122     @Test
123     public void testParseList() {
124         Module bar = TestUtils.findModule(modules, "bar");
125         URI expectedNamespace = URI.create("urn:opendaylight.bar");
126         String expectedPrefix = "bar";
127
128         ContainerSchemaNode interfaces = (ContainerSchemaNode) bar.getDataChildByName("interfaces");
129
130         ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName("ifEntry");
131         // test SchemaNode args
132         QName expectedQName = QName.create(expectedNamespace, barRev, "ifEntry");
133         assertEquals(expectedQName, ifEntry.getQName());
134         SchemaPath expectedPath = TestUtils.createPath(true, expectedNamespace, barRev, expectedPrefix, "interfaces",
135                 "ifEntry");
136         assertEquals(expectedPath, ifEntry.getPath());
137         assertNull(ifEntry.getDescription());
138         assertNull(ifEntry.getReference());
139         assertEquals(Status.CURRENT, ifEntry.getStatus());
140         assertEquals(0, ifEntry.getUnknownSchemaNodes().size());
141         // test DataSchemaNode args
142         assertFalse(ifEntry.isAugmenting());
143         assertTrue(ifEntry.isConfiguration());
144         ConstraintDefinition constraints = ifEntry.getConstraints();
145         // :TODO augment to ifEntry have when condition and so in consequence
146         // ifEntry should be a context node ?
147         // assertNull(constraints.getWhenCondition());
148         assertEquals(0, constraints.getMustConstraints().size());
149         assertTrue(constraints.isMandatory());
150         assertEquals(1, (int) constraints.getMinElements());
151         assertEquals(11, (int) constraints.getMaxElements());
152         // test AugmentationTarget args
153         Set<AugmentationSchema> availableAugmentations = ifEntry.getAvailableAugmentations();
154         assertEquals(2, availableAugmentations.size());
155         // test ListSchemaNode args
156         List<QName> expectedKey = new ArrayList<>();
157         expectedKey.add(QName.create(expectedNamespace, barRev, "ifIndex"));
158         assertEquals(expectedKey, ifEntry.getKeyDefinition());
159         assertFalse(ifEntry.isUserOrdered());
160         // test DataNodeContainer args
161         assertEquals(0, ifEntry.getTypeDefinitions().size());
162         assertEquals(4, ifEntry.getChildNodes().size());
163         assertEquals(0, ifEntry.getGroupings().size());
164         assertEquals(0, ifEntry.getUses().size());
165
166         LeafSchemaNode ifIndex = (LeafSchemaNode) ifEntry.getDataChildByName("ifIndex");
167         assertEquals(ifEntry.getKeyDefinition().get(0), ifIndex.getQName());
168         assertTrue(ifIndex.getType() instanceof UnsignedIntegerTypeDefinition);
169         assertEquals("minutes", ifIndex.getUnits());
170         LeafSchemaNode ifMtu = (LeafSchemaNode) ifEntry.getDataChildByName("ifMtu");
171         assertEquals(BaseTypes.int32Type(), ifMtu.getType());
172     }
173
174     @Test
175     public void testTypedefRangesResolving() throws ParseException {
176         Module foo = TestUtils.findModule(modules, "foo");
177         LeafSchemaNode int32Leaf = (LeafSchemaNode) foo.getDataChildByName("int32-leaf");
178
179         IntegerTypeDefinition leafType = (IntegerTypeDefinition) int32Leaf.getType();
180         QName leafTypeQName = leafType.getQName();
181         assertEquals("int32-ext2", leafTypeQName.getLocalName());
182         assertEquals(fooNS, leafTypeQName.getNamespace());
183         assertEquals(fooRev, leafTypeQName.getRevision());
184         assertEquals("mile", leafType.getUnits());
185         assertEquals("11", leafType.getDefaultValue());
186
187         List<RangeConstraint> ranges = leafType.getRangeConstraints();
188         assertEquals(1, ranges.size());
189         RangeConstraint range = ranges.get(0);
190         assertEquals(12, range.getMin().intValue());
191         assertEquals(20, range.getMax().intValue());
192
193         IntegerTypeDefinition baseType = leafType.getBaseType();
194         QName baseTypeQName = baseType.getQName();
195         assertEquals("int32-ext2", baseTypeQName.getLocalName());
196         assertEquals(barNS, baseTypeQName.getNamespace());
197         assertEquals(barRev, baseTypeQName.getRevision());
198         assertEquals("mile", baseType.getUnits());
199         assertEquals("11", baseType.getDefaultValue());
200
201         List<RangeConstraint> baseTypeRanges = baseType.getRangeConstraints();
202         assertEquals(2, baseTypeRanges.size());
203         RangeConstraint baseTypeRange1 = baseTypeRanges.get(0);
204         assertEquals(3, baseTypeRange1.getMin().intValue());
205         assertEquals(9, baseTypeRange1.getMax().intValue());
206         RangeConstraint baseTypeRange2 = baseTypeRanges.get(1);
207         assertEquals(11, baseTypeRange2.getMin().intValue());
208         assertEquals(20, baseTypeRange2.getMax().intValue());
209
210         IntegerTypeDefinition base = baseType.getBaseType();
211         QName baseQName = base.getQName();
212         assertEquals("int32-ext1", baseQName.getLocalName());
213         assertEquals(barNS, baseQName.getNamespace());
214         assertEquals(barRev, baseQName.getRevision());
215         assertNull(base.getUnits());
216         assertNull(base.getDefaultValue());
217
218         List<RangeConstraint> baseRanges = base.getRangeConstraints();
219         assertEquals(1, baseRanges.size());
220         RangeConstraint baseRange = baseRanges.get(0);
221         assertEquals(2, baseRange.getMin().intValue());
222         assertEquals(20, baseRange.getMax().intValue());
223
224         assertEquals(BaseTypes.int32Type(), base.getBaseType());
225     }
226
227     @Test
228     public void testTypedefPatternsResolving() {
229         Module foo = TestUtils.findModule(modules, "foo");
230         LeafSchemaNode stringleaf = (LeafSchemaNode) foo.getDataChildByName("string-leaf");
231
232         assertTrue(stringleaf.getType() instanceof StringTypeDefinition);
233         StringTypeDefinition type = (StringTypeDefinition) stringleaf.getType();
234         QName typeQName = type.getQName();
235         assertEquals("string-ext4", typeQName.getLocalName());
236         assertEquals(barNS, typeQName.getNamespace());
237         assertEquals(barRev, typeQName.getRevision());
238         assertNull(type.getUnits());
239         assertNull(type.getDefaultValue());
240         List<PatternConstraint> patterns = type.getPatternConstraints();
241         assertEquals(1, patterns.size());
242         PatternConstraint pattern = patterns.iterator().next();
243         assertEquals("^[e-z]*$", pattern.getRegularExpression());
244         assertTrue(type.getLengthConstraints().isEmpty());
245
246         StringTypeDefinition baseType1 = type.getBaseType();
247         QName baseType1QName = baseType1.getQName();
248         assertEquals("string-ext3", baseType1QName.getLocalName());
249         assertEquals(barNS, baseType1QName.getNamespace());
250         assertEquals(barRev, baseType1QName.getRevision());
251         assertNull(baseType1.getUnits());
252         assertNull(baseType1.getDefaultValue());
253         patterns = baseType1.getPatternConstraints();
254         assertEquals(1, patterns.size());
255         pattern = patterns.iterator().next();
256         assertEquals("^[b-u]*$", pattern.getRegularExpression());
257         assertTrue(baseType1.getLengthConstraints().isEmpty());
258
259         StringTypeDefinition baseType2 = baseType1.getBaseType();
260         QName baseType2QName = baseType2.getQName();
261         assertEquals("string-ext2", baseType2QName.getLocalName());
262         assertEquals(barNS, baseType2QName.getNamespace());
263         assertEquals(barRev, baseType2QName.getRevision());
264         assertNull(baseType2.getUnits());
265         assertNull(baseType2.getDefaultValue());
266         assertTrue(baseType2.getPatternConstraints().isEmpty());
267         List<LengthConstraint> baseType2Lengths = baseType2.getLengthConstraints();
268         assertEquals(1, baseType2Lengths.size());
269         LengthConstraint length = baseType2Lengths.get(0);
270         assertEquals(6, length.getMin().intValue());
271         assertEquals(10, length.getMax().intValue());
272
273         StringTypeDefinition baseType3 = baseType2.getBaseType();
274         QName baseType3QName = baseType3.getQName();
275         assertEquals("string-ext1", baseType3QName.getLocalName());
276         assertEquals(barNS, baseType3QName.getNamespace());
277         assertEquals(barRev, baseType3QName.getRevision());
278         assertNull(baseType3.getUnits());
279         assertNull(baseType3.getDefaultValue());
280         patterns = baseType3.getPatternConstraints();
281         assertEquals(1, patterns.size());
282         pattern = patterns.iterator().next();
283         assertEquals("^[a-k]*$", pattern.getRegularExpression());
284         List<LengthConstraint> baseType3Lengths = baseType3.getLengthConstraints();
285         assertEquals(1, baseType3Lengths.size());
286         length = baseType3Lengths.get(0);
287         assertEquals(5, length.getMin().intValue());
288         assertEquals(11, length.getMax().intValue());
289
290         assertEquals(BaseTypes.stringType(), baseType3.getBaseType());
291     }
292
293     @Test
294     public void testTypedefInvalidPatternsResolving() {
295         Module foo = TestUtils.findModule(modules, "foo");
296         final LeafSchemaNode invalidPatternStringLeaf = (LeafSchemaNode) foo
297                 .getDataChildByName("invalid-pattern-string-leaf");
298         StringTypeDefinition type = (StringTypeDefinition) invalidPatternStringLeaf.getType();
299         QName typeQName = type.getQName();
300         assertEquals("invalid-string-pattern", typeQName.getLocalName());
301         assertEquals(barNS, typeQName.getNamespace());
302         assertEquals(barRev, typeQName.getRevision());
303         assertNull(type.getUnits());
304         assertNull(type.getDefaultValue());
305         List<PatternConstraint> patterns = type.getPatternConstraints();
306         assertTrue(patterns.isEmpty());
307
308         final LeafSchemaNode invalidDirectStringPatternDefLeaf = (LeafSchemaNode) foo
309                 .getDataChildByName("invalid-direct-string-pattern-def-leaf");
310         type = (StringTypeDefinition) invalidDirectStringPatternDefLeaf.getType();
311         typeQName = type.getQName();
312         assertEquals("string", typeQName.getLocalName());
313         assertEquals(YangConstants.RFC6020_YANG_NAMESPACE, typeQName.getNamespace());
314         assertNull(typeQName.getRevision());
315         assertNull(type.getUnits());
316         assertNull(type.getDefaultValue());
317         patterns = type.getPatternConstraints();
318         assertTrue(patterns.isEmpty());
319
320         final LeafSchemaNode multiplePatternStringLeaf = (LeafSchemaNode) foo
321                 .getDataChildByName("multiple-pattern-string-leaf");
322         type = (StringTypeDefinition) multiplePatternStringLeaf.getType();
323         typeQName = type.getQName();
324         assertEquals("multiple-pattern-string", typeQName.getLocalName());
325         assertEquals(barNS, typeQName.getNamespace());
326         assertEquals(barRev, typeQName.getRevision());
327         assertNull(type.getUnits());
328         assertNull(type.getDefaultValue());
329         patterns = type.getPatternConstraints();
330         assertTrue(!patterns.isEmpty());
331         assertEquals(1, patterns.size());
332         PatternConstraint pattern = patterns.iterator().next();
333         assertEquals("^[e-z]*$", pattern.getRegularExpression());
334         assertTrue(type.getLengthConstraints().isEmpty());
335
336         final LeafSchemaNode multiplePatternDirectStringDefLeaf = (LeafSchemaNode) foo
337                 .getDataChildByName("multiple-pattern-direct-string-def-leaf");
338         type = (StringTypeDefinition) multiplePatternDirectStringDefLeaf.getType();
339         typeQName = type.getQName();
340         assertEquals("string", typeQName.getLocalName());
341         assertEquals(fooNS, typeQName.getNamespace());
342         assertEquals(fooRev, typeQName.getRevision());
343         assertNull(type.getUnits());
344         assertNull(type.getDefaultValue());
345         patterns = type.getPatternConstraints();
346         assertTrue(!patterns.isEmpty());
347         assertEquals(2, patterns.size());
348
349         boolean isEZPattern = false;
350         boolean isADPattern = false;
351         for (final PatternConstraint patternConstraint : patterns) {
352             if (patternConstraint.getRegularExpression().equals("^[e-z]*$")) {
353                 isEZPattern = true;
354             } else if (patternConstraint.getRegularExpression().equals("^[a-d]*$")) {
355                 isADPattern = true;
356             }
357         }
358         assertTrue(isEZPattern);
359         assertTrue(isADPattern);
360     }
361
362     @Test
363     public void testTypedefLengthsResolving() {
364         Module foo = TestUtils.findModule(modules, "foo");
365
366         LeafSchemaNode lengthLeaf = (LeafSchemaNode) foo.getDataChildByName("length-leaf");
367         StringTypeDefinition type = (StringTypeDefinition) lengthLeaf.getType();
368
369         QName typeQName = type.getQName();
370         assertEquals("string-ext2", typeQName.getLocalName());
371         assertEquals(fooNS, typeQName.getNamespace());
372         assertEquals(fooRev, typeQName.getRevision());
373         assertNull(type.getUnits());
374         assertNull(type.getDefaultValue());
375         assertTrue(type.getPatternConstraints().isEmpty());
376         List<LengthConstraint> typeLengths = type.getLengthConstraints();
377         assertEquals(1, typeLengths.size());
378         LengthConstraint length = typeLengths.get(0);
379         assertEquals(7, length.getMin().intValue());
380         assertEquals(10, length.getMax().intValue());
381
382         StringTypeDefinition baseType1 = type.getBaseType();
383         QName baseType1QName = baseType1.getQName();
384         assertEquals("string-ext2", baseType1QName.getLocalName());
385         assertEquals(barNS, baseType1QName.getNamespace());
386         assertEquals(barRev, baseType1QName.getRevision());
387         assertNull(baseType1.getUnits());
388         assertNull(baseType1.getDefaultValue());
389         assertTrue(baseType1.getPatternConstraints().isEmpty());
390         List<LengthConstraint> baseType2Lengths = baseType1.getLengthConstraints();
391         assertEquals(1, baseType2Lengths.size());
392         length = baseType2Lengths.get(0);
393         assertEquals(6, length.getMin().intValue());
394         assertEquals(10, length.getMax().intValue());
395
396         StringTypeDefinition baseType2 = baseType1.getBaseType();
397         QName baseType2QName = baseType2.getQName();
398         assertEquals("string-ext1", baseType2QName.getLocalName());
399         assertEquals(barNS, baseType2QName.getNamespace());
400         assertEquals(barRev, baseType2QName.getRevision());
401         assertNull(baseType2.getUnits());
402         assertNull(baseType2.getDefaultValue());
403         List<PatternConstraint> patterns = baseType2.getPatternConstraints();
404         assertEquals(1, patterns.size());
405         PatternConstraint pattern = patterns.iterator().next();
406         assertEquals("^[a-k]*$", pattern.getRegularExpression());
407         List<LengthConstraint> baseType3Lengths = baseType2.getLengthConstraints();
408         assertEquals(1, baseType3Lengths.size());
409         length = baseType3Lengths.get(0);
410         assertEquals(5, length.getMin().intValue());
411         assertEquals(11, length.getMax().intValue());
412
413         assertEquals(BaseTypes.stringType(), baseType2.getBaseType());
414     }
415
416     @Test
417     public void testTypedefDecimal1() {
418         Module foo = TestUtils.findModule(modules, "foo");
419         LeafSchemaNode testleaf = (LeafSchemaNode) foo.getDataChildByName("decimal-leaf");
420
421         assertTrue(testleaf.getType() instanceof DecimalTypeDefinition);
422         DecimalTypeDefinition type = (DecimalTypeDefinition) testleaf.getType();
423         QName typeQName = type.getQName();
424         assertEquals("my-decimal-type", typeQName.getLocalName());
425         assertEquals(barNS, typeQName.getNamespace());
426         assertEquals(barRev, typeQName.getRevision());
427         assertNull(type.getUnits());
428         assertNull(type.getDefaultValue());
429         assertEquals(6, type.getFractionDigits().intValue());
430         assertEquals(1, type.getRangeConstraints().size());
431
432         DecimalTypeDefinition typeBase = type.getBaseType();
433         QName typeBaseQName = typeBase.getQName();
434         assertEquals("decimal64", typeBaseQName.getLocalName());
435         assertEquals(barNS, typeBaseQName.getNamespace());
436         assertEquals(barRev, typeBaseQName.getRevision());
437         assertNull(typeBase.getUnits());
438         assertNull(typeBase.getDefaultValue());
439         assertEquals(6, typeBase.getFractionDigits().intValue());
440         assertEquals(1, typeBase.getRangeConstraints().size());
441
442         assertNull(typeBase.getBaseType());
443     }
444
445     @Test
446     public void testTypedefDecimal2() {
447         Module foo = TestUtils.findModule(modules, "foo");
448         LeafSchemaNode testleaf = (LeafSchemaNode) foo.getDataChildByName("decimal-leaf2");
449
450         assertTrue(testleaf.getType() instanceof DecimalTypeDefinition);
451         DecimalTypeDefinition type = (DecimalTypeDefinition) testleaf.getType();
452         QName typeQName = type.getQName();
453         assertEquals("my-decimal-type", typeQName.getLocalName());
454         assertEquals(barNS, typeQName.getNamespace());
455         assertEquals(barRev, typeQName.getRevision());
456         assertNull(type.getUnits());
457         assertNull(type.getDefaultValue());
458         assertEquals(6, type.getFractionDigits().intValue());
459         assertEquals(1, type.getRangeConstraints().size());
460
461         DecimalTypeDefinition baseTypeDecimal = type.getBaseType();
462         assertEquals(6, baseTypeDecimal.getFractionDigits().intValue());
463     }
464
465     @Test
466     public void testTypedefUnion() {
467         Module foo = TestUtils.findModule(modules, "foo");
468         LeafSchemaNode unionleaf = (LeafSchemaNode) foo.getDataChildByName("union-leaf");
469
470         assertTrue(unionleaf.getType() instanceof UnionTypeDefinition);
471         UnionTypeDefinition type = (UnionTypeDefinition) unionleaf.getType();
472         QName typeQName = type.getQName();
473         assertEquals("my-union-ext", typeQName.getLocalName());
474         assertEquals(barNS, typeQName.getNamespace());
475         assertEquals(barRev, typeQName.getRevision());
476         assertNull(type.getUnits());
477         assertNull(type.getDefaultValue());
478
479         UnionTypeDefinition baseType = type.getBaseType();
480         QName baseTypeQName = baseType.getQName();
481         assertEquals("my-union", baseTypeQName.getLocalName());
482         assertEquals(barNS, baseTypeQName.getNamespace());
483         assertEquals(barRev, baseTypeQName.getRevision());
484         assertNull(baseType.getUnits());
485         assertNull(baseType.getDefaultValue());
486
487         UnionTypeDefinition unionType = baseType.getBaseType();
488         List<TypeDefinition<?>> unionTypes = unionType.getTypes();
489         assertEquals(2, unionTypes.size());
490
491         IntegerTypeDefinition unionType1 = (IntegerTypeDefinition) unionTypes.get(0);
492         QName unionType1QName = baseType.getQName();
493         assertEquals("my-union", unionType1QName.getLocalName());
494         assertEquals(barNS, unionType1QName.getNamespace());
495         assertEquals(barRev, unionType1QName.getRevision());
496         assertNull(unionType1.getUnits());
497         assertNull(unionType1.getDefaultValue());
498
499         List<RangeConstraint> ranges = unionType1.getRangeConstraints();
500         assertEquals(1, ranges.size());
501         RangeConstraint range = ranges.get(0);
502         assertEquals(1, range.getMin().intValue());
503         assertEquals(100, range.getMax().intValue());
504         assertEquals(BaseTypes.int16Type(), unionType1.getBaseType());
505
506         assertEquals(BaseTypes.int32Type(), unionTypes.get(1));
507     }
508
509     @Test
510     public void testNestedUnionResolving() {
511         Module foo = TestUtils.findModule(modules, "foo");
512         LeafSchemaNode testleaf = (LeafSchemaNode) foo.getDataChildByName("custom-union-leaf");
513
514         assertTrue(testleaf.getType() instanceof UnionTypeDefinition);
515         UnionTypeDefinition type = (UnionTypeDefinition) testleaf.getType();
516         QName testleafTypeQName = type.getQName();
517         assertEquals(bazNS, testleafTypeQName.getNamespace());
518         assertEquals(bazRev, testleafTypeQName.getRevision());
519         assertEquals("union1", testleafTypeQName.getLocalName());
520         assertNull(type.getUnits());
521         assertNull(type.getDefaultValue());
522
523         UnionTypeDefinition typeBase = type.getBaseType();
524         QName typeBaseQName = typeBase.getQName();
525         assertEquals(bazNS, typeBaseQName.getNamespace());
526         assertEquals(bazRev, typeBaseQName.getRevision());
527         assertEquals("union2", typeBaseQName.getLocalName());
528         assertNull(typeBase.getUnits());
529         assertNull(typeBase.getDefaultValue());
530
531         UnionTypeDefinition union = typeBase.getBaseType();
532         List<TypeDefinition<?>> unionTypes = union.getTypes();
533         assertEquals(2, unionTypes.size());
534         assertEquals(BaseTypes.int32Type(), unionTypes.get(0));
535         assertTrue(unionTypes.get(1) instanceof UnionTypeDefinition);
536
537         UnionTypeDefinition unionType1 = (UnionTypeDefinition) unionTypes.get(1);
538         QName uniontType1QName = unionType1.getQName();
539         assertEquals(barNS, uniontType1QName.getNamespace());
540         assertEquals(barRev, uniontType1QName.getRevision());
541         assertEquals("nested-union2", uniontType1QName.getLocalName());
542         assertNull(unionType1.getUnits());
543         assertNull(unionType1.getDefaultValue());
544
545         UnionTypeDefinition nestedUnion = unionType1.getBaseType();
546         List<TypeDefinition<?>> nestedUnion2Types = nestedUnion.getTypes();
547         assertEquals(2, nestedUnion2Types.size());
548         assertTrue(nestedUnion2Types.get(1) instanceof StringTypeDefinition);
549         assertTrue(nestedUnion2Types.get(0) instanceof UnionTypeDefinition);
550
551         UnionTypeDefinition myUnionExt = (UnionTypeDefinition) nestedUnion2Types.get(0);
552         QName myUnionExtQName = myUnionExt.getQName();
553         assertEquals(barNS, myUnionExtQName.getNamespace());
554         assertEquals(barRev, myUnionExtQName.getRevision());
555         assertEquals("my-union-ext", myUnionExtQName.getLocalName());
556         assertNull(myUnionExt.getUnits());
557         assertNull(myUnionExt.getDefaultValue());
558
559
560         UnionTypeDefinition myUnion = myUnionExt.getBaseType();
561         QName myUnionQName = myUnion.getQName();
562         assertEquals(barNS, myUnionQName.getNamespace());
563         assertEquals(barRev, myUnionQName.getRevision());
564         assertEquals("my-union", myUnionQName.getLocalName());
565         assertNull(myUnion.getUnits());
566         assertNull(myUnion.getDefaultValue());
567
568         UnionTypeDefinition myUnionBase = myUnion.getBaseType();
569         List<TypeDefinition<?>> myUnionBaseTypes = myUnionBase.getTypes();
570         assertEquals(2, myUnionBaseTypes.size());
571         assertTrue(myUnionBaseTypes.get(0) instanceof IntegerTypeDefinition);
572         assertEquals(BaseTypes.int32Type(), myUnionBaseTypes.get(1));
573
574         IntegerTypeDefinition int16Ext = (IntegerTypeDefinition) myUnionBaseTypes.get(0);
575         QName int16ExtQName = int16Ext.getQName();
576         assertEquals(barNS, int16ExtQName.getNamespace());
577         assertEquals(barRev, int16ExtQName.getRevision());
578         assertEquals("int16", int16ExtQName.getLocalName());
579         assertNull(int16Ext.getUnits());
580         assertNull(int16Ext.getDefaultValue());
581         List<RangeConstraint> ranges = int16Ext.getRangeConstraints();
582         assertEquals(1, ranges.size());
583         RangeConstraint range = ranges.get(0);
584         assertEquals(1, range.getMin().intValue());
585         assertEquals(100, range.getMax().intValue());
586
587         assertEquals(BaseTypes.int16Type(), int16Ext.getBaseType());
588     }
589
590     @Test
591     public void testChoice() {
592         Module foo = TestUtils.findModule(modules, "foo");
593         ContainerSchemaNode transfer = (ContainerSchemaNode) foo.getDataChildByName("transfer");
594         ChoiceSchemaNode how = (ChoiceSchemaNode) transfer.getDataChildByName("how");
595         Set<ChoiceCaseNode> cases = how.getCases();
596         assertEquals(5, cases.size());
597         ChoiceCaseNode input = null;
598         ChoiceCaseNode output = null;
599         for (ChoiceCaseNode caseNode : cases) {
600             if ("input".equals(caseNode.getQName().getLocalName())) {
601                 input = caseNode;
602             } else if ("output".equals(caseNode.getQName().getLocalName())) {
603                 output = caseNode;
604             }
605         }
606         assertNotNull(input);
607         assertNotNull(input.getPath());
608         assertNotNull(output);
609         assertNotNull(output.getPath());
610     }
611
612     @Test
613     public void testDeviation() {
614         Module foo = TestUtils.findModule(modules, "foo");
615         Set<Deviation> deviations = foo.getDeviations();
616         assertEquals(1, deviations.size());
617         Deviation dev = deviations.iterator().next();
618         assertEquals("system/user ref", dev.getReference());
619
620         List<QName> path = new ArrayList<>();
621         path.add(QName.create(barNS, barRev, "interfaces"));
622         path.add(QName.create(barNS, barRev, "ifEntry"));
623         SchemaPath expectedPath = SchemaPath.create(path, true);
624
625         assertEquals(expectedPath, dev.getTargetPath());
626         assertEquals(Deviate.ADD, dev.getDeviate());
627     }
628
629     @Test
630     public void testUnknownNode() {
631         Module baz = TestUtils.findModule(modules, "baz");
632         ContainerSchemaNode network = (ContainerSchemaNode) baz.getDataChildByName("network");
633         List<UnknownSchemaNode> unknownNodes = network.getUnknownSchemaNodes();
634         assertEquals(1, unknownNodes.size());
635         UnknownSchemaNode unknownNode = unknownNodes.get(0);
636         assertNotNull(unknownNode.getNodeType());
637         assertEquals("point", unknownNode.getNodeParameter());
638     }
639
640     @Test
641     public void testFeature() {
642         Module baz = TestUtils.findModule(modules, "baz");
643         Set<FeatureDefinition> features = baz.getFeatures();
644         assertEquals(1, features.size());
645     }
646
647     @Test
648     public void testExtension() {
649         Module baz = TestUtils.findModule(modules, "baz");
650         List<ExtensionDefinition> extensions = baz.getExtensionSchemaNodes();
651         assertEquals(1, extensions.size());
652         ExtensionDefinition extension = extensions.get(0);
653         assertEquals("name", extension.getArgument());
654         assertEquals("Takes as argument a name string. Makes the code generator use the given name in the #define.",
655                 extension.getDescription());
656         assertTrue(extension.isYinElement());
657     }
658
659     @Test
660     public void testNotification() {
661         Module baz = TestUtils.findModule(modules, "baz");
662         String expectedPrefix = "c";
663
664         Set<NotificationDefinition> notifications = baz.getNotifications();
665         assertEquals(1, notifications.size());
666
667         NotificationDefinition notification = notifications.iterator().next();
668         // test SchemaNode args
669         QName expectedQName = QName.create(bazNS, bazRev, "event");
670         assertEquals(expectedQName, notification.getQName());
671         SchemaPath expectedPath = TestUtils.createPath(true, bazNS, bazRev, expectedPrefix, "event");
672         assertEquals(expectedPath, notification.getPath());
673         assertNull(notification.getDescription());
674         assertNull(notification.getReference());
675         assertEquals(Status.CURRENT, notification.getStatus());
676         assertEquals(0, notification.getUnknownSchemaNodes().size());
677         // test DataNodeContainer args
678         assertEquals(0, notification.getTypeDefinitions().size());
679         assertEquals(3, notification.getChildNodes().size());
680         assertEquals(0, notification.getGroupings().size());
681         assertEquals(0, notification.getUses().size());
682
683         LeafSchemaNode eventClass = (LeafSchemaNode) notification.getDataChildByName("event-class");
684         assertTrue(eventClass.getType() instanceof StringTypeDefinition);
685         LeafSchemaNode severity = (LeafSchemaNode) notification.getDataChildByName("severity");
686         assertTrue(severity.getType() instanceof StringTypeDefinition);
687     }
688
689     @Test
690     public void testRpc() {
691         Module baz = TestUtils.findModule(modules, "baz");
692
693         Set<RpcDefinition> rpcs = baz.getRpcs();
694         assertEquals(1, rpcs.size());
695
696         RpcDefinition rpc = rpcs.iterator().next();
697         assertEquals("Retrieve all or part of a specified configuration.", rpc.getDescription());
698         assertEquals("RFC 6241, Section 7.1", rpc.getReference());
699     }
700
701     @Test
702     public void testTypePath() throws ParseException {
703         Module bar = TestUtils.findModule(modules, "bar");
704         Set<TypeDefinition<?>> types = bar.getTypeDefinitions();
705
706         // int32-ext1
707         IntegerTypeDefinition int32ext1 = (IntegerTypeDefinition) TestUtils.findTypedef(types, "int32-ext1");
708         QName int32TypedefQName = int32ext1.getQName();
709
710         assertEquals(barNS, int32TypedefQName.getNamespace());
711         assertEquals(barRev, int32TypedefQName.getRevision());
712         assertEquals("int32-ext1", int32TypedefQName.getLocalName());
713
714         SchemaPath typeSchemaPath = int32ext1.getPath();
715         Iterable<QName> typePath = typeSchemaPath.getPathFromRoot();
716         Iterator<QName> typePathIt = typePath.iterator();
717         assertEquals(int32TypedefQName, typePathIt.next());
718         assertFalse(typePathIt.hasNext());
719
720         // int32-ext1/int32
721         IntegerTypeDefinition int32 = int32ext1.getBaseType();
722         assertEquals(BaseTypes.int32Type(), int32);
723     }
724
725     @Test
726     public void testTypePath2() throws ParseException {
727         Module bar = TestUtils.findModule(modules, "bar");
728         Set<TypeDefinition<?>> types = bar.getTypeDefinitions();
729
730         // my-decimal-type
731         DecimalTypeDefinition myDecType = (DecimalTypeDefinition) TestUtils.findTypedef(types, "my-decimal-type");
732         QName myDecTypeQName = myDecType.getQName();
733
734         assertEquals(barNS, myDecTypeQName.getNamespace());
735         assertEquals(barRev, myDecTypeQName.getRevision());
736         assertEquals("my-decimal-type", myDecTypeQName.getLocalName());
737
738         SchemaPath typeSchemaPath = myDecType.getPath();
739         Iterable<QName> typePath = typeSchemaPath.getPathFromRoot();
740         Iterator<QName> typePathIt = typePath.iterator();
741         assertEquals(myDecTypeQName, typePathIt.next());
742         assertFalse(typePathIt.hasNext());
743
744         // my-base-int32-type/int32
745         DecimalTypeDefinition dec64 = myDecType.getBaseType();
746         QName dec64QName = dec64.getQName();
747
748         assertEquals(barNS, dec64QName.getNamespace());
749         assertEquals(barRev, dec64QName.getRevision());
750         assertEquals("decimal64", dec64QName.getLocalName());
751
752         SchemaPath dec64SchemaPath = dec64.getPath();
753         Iterable<QName> dec64Path = dec64SchemaPath.getPathFromRoot();
754         Iterator<QName> dec64PathIt = dec64Path.iterator();
755         assertEquals(myDecTypeQName, dec64PathIt.next());
756         assertEquals(dec64QName, dec64PathIt.next());
757         assertFalse(dec64PathIt.hasNext());
758     }
759
760     @Test
761     public void testParseMethod1() throws Exception {
762         File yangFile = new File(getClass().getResource("/parse-methods/m1.yang").toURI());
763         File dependenciesDir = new File(getClass().getResource("/parse-methods").toURI());
764         YangContextParser parser = new YangParserImpl();
765         modules = parser.parseFile(yangFile, dependenciesDir).getModules();
766         assertEquals(6, modules.size());
767     }
768
769     @Test
770     public void testParseMethod2() throws Exception {
771         File yangFile = new File(getClass().getResource("/parse-methods/m1.yang").toURI());
772         File dependenciesDir = new File(getClass().getResource("/parse-methods/dependencies").toURI());
773         YangContextParser parser = new YangParserImpl();
774         modules = parser.parseFile(yangFile, dependenciesDir).getModules();
775         assertEquals(6, modules.size());
776     }
777
778     // @Test
779     // public void testSorting() throws Exception {
780     // // Correct order: m2, m4, m6, m8, m7, m6, m3, m1
781     // File yangFile = new File(getClass().getResource("/sorting-test/m1.yang").toURI());
782     // File dependenciesDir = new File(getClass().getResource("/sorting-test").toURI());
783     // YangContextParser parser = new YangParserImpl();
784     // modules = parser.parseFile(yangFile, dependenciesDir).getModules();
785     // SchemaContext ctx = new SchemaContextImpl(modules, Collections.<ModuleIdentifier, String> emptyMap());
786     // checkOrder(modules);
787     // assertSetEquals(modules, ctx.getModules());
788     //
789     // // ##########
790     // parser = new YangParserImpl();
791     // final File testDir = dependenciesDir;
792     // final String[] fileList = testDir.list();
793     // final List<File> testFiles = new ArrayList<>();
794     // if (fileList == null) {
795     // throw new FileNotFoundException(dependenciesDir.getAbsolutePath());
796     // }
797     // for (String fileName : fileList) {
798     // testFiles.add(new File(testDir, fileName));
799     // }
800     // Set<Module> newModules = parser.parseFiles(testFiles).getModules();
801     // assertSetEquals(newModules, modules);
802     // ctx = new SchemaContextImpl(newModules, Collections.<ModuleIdentifier, String> emptyMap());
803     // assertSetEquals(newModules, ctx.getModules());
804     // // ##########
805     // newModules = parser.parseFiles(testFiles, null).getModules();
806     // assertSetEquals(newModules, modules);
807     // ctx = new SchemaContextImpl(newModules, Collections.<ModuleIdentifier, String> emptyMap());
808     // assertSetEquals(newModules, ctx.getModules());
809     // // ##########
810     // List<InputStream> streams = new ArrayList<>();
811     // for (File f : testFiles) {
812     // streams.add(new FileInputStream(f));
813     // }
814     // newModules = parser.parseSources(BuilderUtils.filesToByteSources(testFiles)).getModules();
815     // assertSetEquals(newModules, modules);
816     // ctx = new SchemaContextImpl(newModules, Collections.<ModuleIdentifier, String> emptyMap());
817     // assertSetEquals(newModules, ctx.getModules());
818     // // ##########
819     // streams.clear();
820     // for (File f : testFiles) {
821     // streams.add(new FileInputStream(f));
822     // }
823     // newModules = parser.parseSources(BuilderUtils.filesToByteSources(testFiles), null).getModules();
824     // assertSetEquals(newModules, modules);
825     // ctx = new SchemaContextImpl(newModules, Collections.<ModuleIdentifier, String> emptyMap());
826     // assertSetEquals(newModules, ctx.getModules());
827     // // ##########
828     // Map<File, Module> mapped = parser.parseYangModelsMapped(testFiles);
829     // newModules = new LinkedHashSet<>(mapped.values());
830     // assertSetEquals(newModules, modules);
831     // ctx = new SchemaContextImpl(newModules, Collections.<ModuleIdentifier, String> emptyMap());
832     // assertSetEquals(newModules, ctx.getModules());
833     // // ##########
834     // streams.clear();
835     // for (File f : testFiles) {
836     // streams.add(new FileInputStream(f));
837     // }
838     // Map<InputStream, Module> mappedStreams = parser.parseYangModelsFromStreamsMapped(streams);
839     // newModules = new LinkedHashSet<>(mappedStreams.values());
840     // assertSetEquals(newModules, modules);
841     // ctx = new SchemaContextImpl(newModules, Collections.<ModuleIdentifier, String> emptyMap());
842     // assertSetEquals(newModules, ctx.getModules());
843     // }
844
845     private static void checkOrder(final Collection<Module> modules) {
846         Iterator<Module> it = modules.iterator();
847         Module m = it.next();
848         assertEquals("m2", m.getName());
849         m = it.next();
850         assertEquals("m4", m.getName());
851         m = it.next();
852         assertEquals("m6", m.getName());
853         m = it.next();
854         assertEquals("m8", m.getName());
855         m = it.next();
856         assertEquals("m7", m.getName());
857         m = it.next();
858         assertEquals("m5", m.getName());
859         m = it.next();
860         assertEquals("m3", m.getName());
861         m = it.next();
862         assertEquals("m1", m.getName());
863     }
864
865     private static void assertSetEquals(final Set<Module> s1, final Set<Module> s2) {
866         assertEquals(s1, s2);
867         Iterator<Module> it = s1.iterator();
868         for (Module m : s2) {
869             assertEquals(m, it.next());
870         }
871     }
872
873     @Test
874     public void testSubmodules() {
875         Module foo = TestUtils.findModule(modules, "foo");
876
877         DataSchemaNode id = foo.getDataChildByName("id");
878         assertNotNull(id);
879         DataSchemaNode subExt = foo.getDataChildByName("sub-ext");
880         assertNotNull(subExt);
881         DataSchemaNode subTransfer = foo.getDataChildByName("sub-transfer");
882         assertNotNull(subTransfer);
883
884         assertEquals(2, foo.getExtensionSchemaNodes().size());
885         assertEquals(2, foo.getAugmentations().size());
886     }
887
888     @Test
889     public void unknownStatementInSubmoduleHeaderTest() throws IOException, URISyntaxException {
890
891         File yang = new File(getClass().getResource("/yang-grammar-test/submodule-header-extension.yang").toURI());
892
893         try {
894             YangParserImpl.getInstance().parseFile(yang, yang.getParentFile());
895         } catch (YangSyntaxErrorException | YangParseException e) {
896             e.printStackTrace();
897             fail("YangSyntaxErrorException or YangParseException should not be thrown");
898         }
899
900     }
901
902     @Test
903     public void unknownStatementBetweenRevisionsTest() throws ReactorException {
904
905         final YangStatementSourceImpl yangModule = new YangStatementSourceImpl(
906                 "/yang-grammar-test/revisions-extension.yang", false);
907         final YangStatementSourceImpl yangSubmodule = new YangStatementSourceImpl(
908                 "/yang-grammar-test/submodule-header-extension.yang", false);
909
910         CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
911         addSources(reactor, yangModule, yangSubmodule);
912
913         final EffectiveSchemaContext result = reactor.buildEffective();
914         assertNotNull(result);
915     }
916
917     @Test
918     public void unknownStatementsInStatementsTest() throws ReactorException {
919
920         final YangStatementSourceImpl yangFile1 = new YangStatementSourceImpl(
921                 "/yang-grammar-test/stmtsep-in-statements.yang", false);
922         final YangStatementSourceImpl yangFile2 = new YangStatementSourceImpl(
923                 "/yang-grammar-test/stmtsep-in-statements2.yang", false);
924         final YangStatementSourceImpl yangFile3 = new YangStatementSourceImpl(
925                 "/yang-grammar-test/stmtsep-in-statements-sub.yang", false);
926
927         CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
928         addSources(reactor, yangFile1, yangFile2, yangFile3);
929         // TODO: change test or create new module in order to respect new statement parser validations
930         try {
931             final EffectiveSchemaContext result = reactor.buildEffective();
932         } catch (Exception e) {
933             assertEquals(IllegalArgumentException.class, e.getClass());
934             assertTrue(e.getMessage().startsWith("aaa is not a YANG statement or use of extension"));
935         }
936     }
937
938     private static void addSources(final CrossSourceStatementReactor.BuildAction reactor, final YangStatementSourceImpl... sources) {
939         for (YangStatementSourceImpl source : sources) {
940             reactor.addSource(source);
941         }
942     }
943 }