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