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