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