ce22eaedac0448bcd6a079a8317d7fe663947a2a
[yangtools.git] / parser / yang-parser-rfc7950 / src / test / java / org / opendaylight / yangtools / yang / stmt / YangParserTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.stmt;
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.opendaylight.yangtools.yang.stmt.StmtTestUtils.assertPathEquals;
16 import static org.opendaylight.yangtools.yang.stmt.StmtTestUtils.sourceForResource;
17
18 import com.google.common.collect.Range;
19 import com.google.common.collect.RangeSet;
20 import java.io.IOException;
21 import java.net.URISyntaxException;
22 import java.text.ParseException;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Optional;
28 import java.util.Set;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.opendaylight.yangtools.yang.common.QName;
32 import org.opendaylight.yangtools.yang.common.QNameModule;
33 import org.opendaylight.yangtools.yang.common.Revision;
34 import org.opendaylight.yangtools.yang.common.XMLNamespace;
35 import org.opendaylight.yangtools.yang.common.YangVersion;
36 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.DeviateKind;
42 import org.opendaylight.yangtools.yang.model.api.Deviation;
43 import org.opendaylight.yangtools.yang.model.api.ElementCountConstraint;
44 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
45 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
46 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
47 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
48 import org.opendaylight.yangtools.yang.model.api.Module;
49 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
50 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
51 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
52 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
53 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
54 import org.opendaylight.yangtools.yang.model.api.Status;
55 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
56 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
57 import org.opendaylight.yangtools.yang.model.api.stmt.UnrecognizedStatement;
58 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
59 import org.opendaylight.yangtools.yang.model.api.type.Int16TypeDefinition;
60 import org.opendaylight.yangtools.yang.model.api.type.Int32TypeDefinition;
61 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
62 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
63 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
64 import org.opendaylight.yangtools.yang.model.api.type.TypeDefinitions;
65 import org.opendaylight.yangtools.yang.model.api.type.Uint32TypeDefinition;
66 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
67 import org.opendaylight.yangtools.yang.model.ri.type.BaseTypes;
68 import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.RFC7950Reactors;
69 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
70 import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
71 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
72 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
73 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.BuildAction;
74
75 public class YangParserTest {
76     private static final QNameModule FOO = QNameModule.create(XMLNamespace.of("urn:opendaylight.foo"),
77         Revision.of("2013-02-27"));
78     private static final QNameModule BAR = QNameModule.create(XMLNamespace.of("urn:opendaylight.bar"),
79         Revision.of("2013-07-03"));
80     private static final QNameModule BAZ = QNameModule.create(XMLNamespace.of("urn:opendaylight.baz"),
81         Revision.of("2013-02-27"));
82
83     private SchemaContext context;
84     private Module foo;
85     private Module bar;
86     private Module baz;
87
88     @Before
89     public void init() throws Exception {
90         context = TestUtils.loadModules(getClass().getResource("/model").toURI());
91         foo = TestUtils.findModule(context, "foo").get();
92         bar = TestUtils.findModule(context, "bar").get();
93         baz = TestUtils.findModule(context, "baz").get();
94     }
95
96     @Test
97     public void testHeaders() throws ParseException {
98         assertEquals("foo", foo.getName());
99         assertEquals(YangVersion.VERSION_1, foo.getYangVersion());
100         assertEquals(FOO.getNamespace(), foo.getNamespace());
101         assertEquals("foo", foo.getPrefix());
102
103         final Collection<? extends ModuleImport> imports = foo.getImports();
104         assertEquals(2, imports.size());
105
106         final ModuleImport import2 = TestUtils.findImport(imports, "br");
107         assertEquals("bar", import2.getModuleName());
108         assertEquals(BAR.getRevision(), import2.getRevision());
109
110         final ModuleImport import3 = TestUtils.findImport(imports, "bz");
111         assertEquals("baz", import3.getModuleName());
112         assertEquals(BAZ.getRevision(), import3.getRevision());
113
114         assertEquals(Optional.of("opendaylight"), foo.getOrganization());
115         assertEquals(Optional.of("http://www.opendaylight.org/"), foo.getContact());
116         assertEquals(Revision.ofNullable("2013-02-27"), foo.getRevision());
117         assertFalse(foo.getReference().isPresent());
118     }
119
120     @Test
121     public void testParseList() {
122         final ContainerSchemaNode interfaces = (ContainerSchemaNode) bar.getDataChildByName(QName.create(
123             bar.getQNameModule(), "interfaces"));
124
125         final ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName(QName.create(bar.getQNameModule(),
126             "ifEntry"));
127         // test SchemaNode args
128         assertEquals(QName.create(BAR, "ifEntry"), ifEntry.getQName());
129
130         assertPathEquals(SchemaPath.create(true, QName.create(BAR, "interfaces"), QName.create(BAR, "ifEntry")),
131             ifEntry);
132         assertFalse(ifEntry.getDescription().isPresent());
133         assertFalse(ifEntry.getReference().isPresent());
134         assertEquals(Status.CURRENT, ifEntry.getStatus());
135         assertEquals(0, ifEntry.getUnknownSchemaNodes().size());
136         // test DataSchemaNode args
137         assertFalse(ifEntry.isAugmenting());
138         assertEquals(Optional.of(Boolean.TRUE), ifEntry.effectiveConfig());
139         // :TODO augment to ifEntry have when condition and so in consequence
140         // ifEntry should be a context node ?
141         // assertNull(constraints.getWhenCondition());
142         assertEquals(0, ifEntry.getMustConstraints().size());
143         ElementCountConstraint constraints = ifEntry.getElementCountConstraint().get();
144         assertEquals((Object) 1, constraints.getMinElements());
145         assertEquals((Object) 11, constraints.getMaxElements());
146         // test AugmentationTarget args
147         final Collection<? extends AugmentationSchemaNode> availableAugmentations = ifEntry.getAvailableAugmentations();
148         assertEquals(2, availableAugmentations.size());
149         // test ListSchemaNode args
150         final List<QName> expectedKey = new ArrayList<>();
151         expectedKey.add(QName.create(BAR, "ifIndex"));
152         assertEquals(expectedKey, ifEntry.getKeyDefinition());
153         assertFalse(ifEntry.isUserOrdered());
154         // test DataNodeContainer args
155         assertEquals(0, ifEntry.getTypeDefinitions().size());
156         assertEquals(4, ifEntry.getChildNodes().size());
157         assertEquals(0, ifEntry.getGroupings().size());
158         assertEquals(0, ifEntry.getUses().size());
159
160         final LeafSchemaNode ifIndex = (LeafSchemaNode) ifEntry.getDataChildByName(QName.create(bar.getQNameModule(),
161             "ifIndex"));
162         assertEquals(ifEntry.getKeyDefinition().get(0), ifIndex.getQName());
163         assertTrue(ifIndex.getType() instanceof Uint32TypeDefinition);
164         assertEquals(Optional.of("minutes"), ifIndex.getType().getUnits());
165         final LeafSchemaNode ifMtu = (LeafSchemaNode) ifEntry.getDataChildByName(QName.create(bar.getQNameModule(),
166             "ifMtu"));
167         assertEquals(BaseTypes.int32Type(), ifMtu.getType());
168     }
169
170     @Test
171     public void testTypedefRangesResolving() throws ParseException {
172         final LeafSchemaNode int32Leaf = (LeafSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(),
173             "int32-leaf"));
174
175         final Int32TypeDefinition leafType = (Int32TypeDefinition) int32Leaf.getType();
176         assertEquals(QName.create(FOO, "int32-ext2"), leafType.getQName());
177         assertEquals(Optional.of("mile"), leafType.getUnits());
178         assertEquals(Optional.of("11"), leafType.getDefaultValue());
179
180         final RangeSet<? extends Number> rangeset = leafType.getRangeConstraint().get().getAllowedRanges();
181         final Set<? extends Range<? extends Number>> ranges = rangeset.asRanges();
182         assertEquals(1, ranges.size());
183
184         final Range<? extends Number> range = ranges.iterator().next();
185         assertEquals(12, range.lowerEndpoint().intValue());
186         assertEquals(20, range.upperEndpoint().intValue());
187
188         final Int32TypeDefinition firstBaseType = leafType.getBaseType();
189         assertEquals(QName.create(BAR, "int32-ext2"), firstBaseType.getQName());
190         assertEquals(Optional.of("mile"), firstBaseType.getUnits());
191         assertEquals(Optional.of("11"), firstBaseType.getDefaultValue());
192
193         final RangeSet<? extends Number> firstRangeset = firstBaseType.getRangeConstraint().get().getAllowedRanges();
194         final Set<? extends Range<? extends Number>> baseRanges = firstRangeset.asRanges();
195         assertEquals(2, baseRanges.size());
196
197         final Iterator<? extends Range<? extends Number>> it = baseRanges.iterator();
198         final Range<? extends Number> baseTypeRange1 = it.next();
199         assertEquals(3, baseTypeRange1.lowerEndpoint().intValue());
200         assertEquals(9, baseTypeRange1.upperEndpoint().intValue());
201         final Range<? extends Number> baseTypeRange2 = it.next();
202         assertEquals(11, baseTypeRange2.lowerEndpoint().intValue());
203         assertEquals(20, baseTypeRange2.upperEndpoint().intValue());
204
205         final Int32TypeDefinition secondBaseType = firstBaseType.getBaseType();
206         final QName baseQName = secondBaseType.getQName();
207         assertEquals("int32-ext1", baseQName.getLocalName());
208         assertEquals(BAR, baseQName.getModule());
209         assertEquals(Optional.empty(), secondBaseType.getUnits());
210         assertEquals(Optional.empty(), secondBaseType.getDefaultValue());
211
212         final Set<? extends Range<? extends Number>> secondRanges = secondBaseType.getRangeConstraint().get()
213                 .getAllowedRanges().asRanges();
214         assertEquals(1, secondRanges.size());
215         final Range<? extends Number> secondRange = secondRanges.iterator().next();
216         assertEquals(2, secondRange.lowerEndpoint().intValue());
217         assertEquals(20, secondRange.upperEndpoint().intValue());
218
219         assertEquals(BaseTypes.int32Type(), secondBaseType.getBaseType());
220     }
221
222     @Test
223     public void testTypedefPatternsResolving() {
224         final LeafSchemaNode stringleaf = (LeafSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(),
225             "string-leaf"));
226
227         assertTrue(stringleaf.getType() instanceof StringTypeDefinition);
228         final StringTypeDefinition type = (StringTypeDefinition) stringleaf.getType();
229         final QName typeQName = type.getQName();
230         assertEquals("string-ext4", typeQName.getLocalName());
231         assertEquals(BAR, typeQName.getModule());
232         assertEquals(Optional.empty(), type.getUnits());
233         assertEquals(Optional.empty(), type.getDefaultValue());
234         List<PatternConstraint> patterns = type.getPatternConstraints();
235         assertEquals(1, patterns.size());
236         PatternConstraint pattern = patterns.iterator().next();
237         assertEquals("^(?:[e-z]*)$", pattern.getJavaPatternString());
238         assertEquals(1, type.getLengthConstraint().get().getAllowedRanges().asRanges().size());
239
240         final StringTypeDefinition baseType1 = type.getBaseType();
241         final QName baseType1QName = baseType1.getQName();
242         assertEquals("string-ext3", baseType1QName.getLocalName());
243         assertEquals(BAR, baseType1QName.getModule());
244         assertEquals(Optional.empty(), baseType1.getUnits());
245         assertEquals(Optional.empty(), baseType1.getDefaultValue());
246         patterns = baseType1.getPatternConstraints();
247         assertEquals(1, patterns.size());
248         pattern = patterns.iterator().next();
249         assertEquals("^(?:[b-u]*)$", pattern.getJavaPatternString());
250         assertEquals(1, baseType1.getLengthConstraint().get().getAllowedRanges().asRanges().size());
251
252         final StringTypeDefinition baseType2 = baseType1.getBaseType();
253         final QName baseType2QName = baseType2.getQName();
254         assertEquals("string-ext2", baseType2QName.getLocalName());
255         assertEquals(BAR, baseType2QName.getModule());
256         assertEquals(Optional.empty(), baseType2.getUnits());
257         assertEquals(Optional.empty(), baseType2.getDefaultValue());
258         assertTrue(baseType2.getPatternConstraints().isEmpty());
259         final RangeSet<Integer> baseType2Lengths = baseType2.getLengthConstraint().get().getAllowedRanges();
260         assertEquals(1, baseType2Lengths.asRanges().size());
261         Range<Integer> length = baseType2Lengths.span();
262         assertEquals(6, length.lowerEndpoint().intValue());
263         assertEquals(10, length.upperEndpoint().intValue());
264
265         final StringTypeDefinition baseType3 = baseType2.getBaseType();
266         assertEquals(QName.create(BAR, "string-ext1"), baseType3.getQName());
267         assertEquals(Optional.empty(), baseType3.getUnits());
268         assertEquals(Optional.empty(), baseType3.getDefaultValue());
269         patterns = baseType3.getPatternConstraints();
270         assertEquals(1, patterns.size());
271         pattern = patterns.iterator().next();
272         assertEquals("^(?:[a-k]*)$", pattern.getJavaPatternString());
273         final RangeSet<Integer> baseType3Lengths = baseType3.getLengthConstraint().get().getAllowedRanges();
274         assertEquals(1, baseType3Lengths.asRanges().size());
275         length = baseType3Lengths.span();
276         assertEquals(5, length.lowerEndpoint().intValue());
277         assertEquals(11, length.upperEndpoint().intValue());
278
279         assertEquals(BaseTypes.stringType(), baseType3.getBaseType());
280     }
281
282     @Test
283     public void testTypedefInvalidPatternsResolving() {
284         final LeafSchemaNode multiplePatternStringLeaf = (LeafSchemaNode) foo
285                 .getDataChildByName(QName.create(foo.getQNameModule(), "multiple-pattern-string-leaf"));
286         StringTypeDefinition type = (StringTypeDefinition) multiplePatternStringLeaf.getType();
287         assertEquals(QName.create(BAR, "multiple-pattern-string"), type.getQName());
288         assertEquals(Optional.empty(), type.getUnits());
289         assertEquals(Optional.empty(), type.getDefaultValue());
290         List<PatternConstraint> patterns = type.getPatternConstraints();
291         assertEquals(2, patterns.size());
292         assertEquals("^(?:[A-Z]*-%22!\\^\\^)$", patterns.get(0).getJavaPatternString());
293         assertEquals("^(?:[e-z]*)$", patterns.get(1).getJavaPatternString());
294         assertEquals(1, type.getLengthConstraint().get().getAllowedRanges().asRanges().size());
295
296         final LeafSchemaNode multiplePatternDirectStringDefLeaf = (LeafSchemaNode) foo
297                 .getDataChildByName(QName.create(foo.getQNameModule(), "multiple-pattern-direct-string-def-leaf"));
298         type = (StringTypeDefinition) multiplePatternDirectStringDefLeaf.getType();
299         assertEquals(QName.create(FOO, "string"), type.getQName());
300         assertEquals(Optional.empty(), type.getUnits());
301         assertEquals(Optional.empty(), type.getDefaultValue());
302         patterns = type.getPatternConstraints();
303         assertEquals(3, patterns.size());
304
305         assertEquals("^(?:[e-z]*)$", patterns.get(0).getJavaPatternString());
306         assertEquals("^(?:[A-Z]*-%22!\\^\\^})$", patterns.get(1).getJavaPatternString());
307         assertEquals("^(?:[a-d]*)$", patterns.get(2).getJavaPatternString());
308     }
309
310     @Test
311     public void testTypedefLengthsResolving() {
312         final LeafSchemaNode lengthLeaf = (LeafSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(),
313             "length-leaf"));
314         final StringTypeDefinition type = (StringTypeDefinition) lengthLeaf.getType();
315
316         assertEquals(QName.create(FOO, "string-ext2"), type.getQName());
317         assertEquals(Optional.empty(), type.getUnits());
318         assertEquals(Optional.empty(), type.getDefaultValue());
319         assertTrue(type.getPatternConstraints().isEmpty());
320         final RangeSet<Integer> typeLengths = type.getLengthConstraint().get().getAllowedRanges();
321         assertEquals(1, typeLengths.asRanges().size());
322         Range<Integer> length = typeLengths.span();
323         assertEquals(7, length.lowerEndpoint().intValue());
324         assertEquals(10, length.upperEndpoint().intValue());
325
326         final StringTypeDefinition baseType1 = type.getBaseType();
327         assertEquals(QName.create(BAR, "string-ext2"), baseType1.getQName());
328         assertEquals(Optional.empty(), baseType1.getUnits());
329         assertEquals(Optional.empty(), baseType1.getDefaultValue());
330         assertTrue(baseType1.getPatternConstraints().isEmpty());
331         final RangeSet<Integer> baseType2Lengths = baseType1.getLengthConstraint().get().getAllowedRanges();
332         assertEquals(1, baseType2Lengths.asRanges().size());
333         length = baseType2Lengths.span();
334         assertEquals(6, length.lowerEndpoint().intValue());
335         assertEquals(10, length.upperEndpoint().intValue());
336
337         final StringTypeDefinition baseType2 = baseType1.getBaseType();
338         assertEquals(QName.create(BAR, "string-ext1"), baseType2.getQName());
339         assertEquals(Optional.empty(), baseType2.getUnits());
340         assertEquals(Optional.empty(), baseType2.getDefaultValue());
341         final List<PatternConstraint> patterns = baseType2.getPatternConstraints();
342         assertEquals(1, patterns.size());
343         final PatternConstraint pattern = patterns.iterator().next();
344         assertEquals("^(?:[a-k]*)$", pattern.getJavaPatternString());
345         final RangeSet<Integer> baseType3Lengths = baseType2.getLengthConstraint().get().getAllowedRanges();
346         assertEquals(1, baseType3Lengths.asRanges().size());
347         length = baseType3Lengths.span();
348         assertEquals(5, length.lowerEndpoint().intValue());
349         assertEquals(11, length.upperEndpoint().intValue());
350
351         assertEquals(BaseTypes.stringType(), baseType2.getBaseType());
352     }
353
354     @Test
355     public void testTypedefDecimal1() {
356         final LeafSchemaNode testleaf = (LeafSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(),
357             "decimal-leaf"));
358
359         assertTrue(testleaf.getType() instanceof DecimalTypeDefinition);
360         final DecimalTypeDefinition type = (DecimalTypeDefinition) testleaf.getType();
361         assertEquals(QName.create(BAR, "my-decimal-type"), type.getQName());
362         assertEquals(Optional.empty(), type.getUnits());
363         assertEquals(Optional.empty(), type.getDefaultValue());
364         assertEquals(6, type.getFractionDigits());
365         assertEquals(1, type.getRangeConstraint().get().getAllowedRanges().asRanges().size());
366
367         final DecimalTypeDefinition typeBase = type.getBaseType();
368         assertEquals(QName.create(BAR, "decimal64"), typeBase.getQName());
369         assertEquals(Optional.empty(), typeBase.getUnits());
370         assertEquals(Optional.empty(), typeBase.getDefaultValue());
371         assertEquals(6, typeBase.getFractionDigits());
372         assertEquals(1, typeBase.getRangeConstraint().get().getAllowedRanges().asRanges().size());
373
374         assertNull(typeBase.getBaseType());
375     }
376
377     @Test
378     public void testTypedefDecimal2() {
379         final LeafSchemaNode testleaf = (LeafSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(),
380             "decimal-leaf2"));
381
382         assertTrue(testleaf.getType() instanceof DecimalTypeDefinition);
383         final DecimalTypeDefinition type = (DecimalTypeDefinition) testleaf.getType();
384         assertEquals(QName.create(BAR, "my-decimal-type"), type.getQName());
385         assertEquals(Optional.empty(), type.getUnits());
386         assertEquals(Optional.empty(), type.getDefaultValue());
387         assertEquals(6, type.getFractionDigits());
388         assertEquals(1, type.getRangeConstraint().get().getAllowedRanges().asRanges().size());
389
390         final DecimalTypeDefinition baseTypeDecimal = type.getBaseType();
391         assertEquals(6, baseTypeDecimal.getFractionDigits());
392     }
393
394     @Test
395     public void testTypedefUnion() {
396         final LeafSchemaNode unionleaf = (LeafSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(),
397             "union-leaf"));
398
399         assertTrue(unionleaf.getType() instanceof UnionTypeDefinition);
400         final UnionTypeDefinition type = (UnionTypeDefinition) unionleaf.getType();
401         assertEquals(QName.create(BAR, "my-union-ext"), type.getQName());
402         assertEquals(Optional.empty(), type.getUnits());
403         assertEquals(Optional.empty(), type.getDefaultValue());
404
405         final UnionTypeDefinition baseType = type.getBaseType();
406         assertEquals(QName.create(BAR, "my-union"), baseType.getQName());
407         assertEquals(Optional.empty(), baseType.getUnits());
408         assertEquals(Optional.empty(), baseType.getDefaultValue());
409
410         final UnionTypeDefinition unionType = baseType.getBaseType();
411         final List<TypeDefinition<?>> unionTypes = unionType.getTypes();
412         assertEquals(2, unionTypes.size());
413
414         final Int16TypeDefinition unionType1 = (Int16TypeDefinition) unionTypes.get(0);
415         assertEquals(QName.create(BAR, "my-union"), baseType.getQName());
416         assertEquals(Optional.empty(), unionType1.getUnits());
417         assertEquals(Optional.empty(), unionType1.getDefaultValue());
418
419         final RangeConstraint<?> ranges = unionType1.getRangeConstraint().get();
420         assertEquals(1, ranges.getAllowedRanges().asRanges().size());
421         final Range<?> range = ranges.getAllowedRanges().span();
422         assertEquals((short)1, range.lowerEndpoint());
423         assertEquals((short)100, range.upperEndpoint());
424         assertEquals(BaseTypes.int16Type(), unionType1.getBaseType());
425
426         assertEquals(BaseTypes.int32Type(), unionTypes.get(1));
427     }
428
429     @Test
430     public void testNestedUnionResolving() {
431         final LeafSchemaNode testleaf = (LeafSchemaNode) foo.getDataChildByName(QName.create(foo.getQNameModule(),
432             "custom-union-leaf"));
433
434         assertTrue(testleaf.getType() instanceof UnionTypeDefinition);
435         final UnionTypeDefinition type = (UnionTypeDefinition) testleaf.getType();
436         assertEquals(QName.create(BAZ, "union1"), type.getQName());
437         assertEquals(Optional.empty(), type.getUnits());
438         assertEquals(Optional.empty(), type.getDefaultValue());
439
440         final UnionTypeDefinition typeBase = type.getBaseType();
441         assertEquals(QName.create(BAZ, "union2"), typeBase.getQName());
442         assertEquals(Optional.empty(), typeBase.getUnits());
443         assertEquals(Optional.empty(), typeBase.getDefaultValue());
444
445         final UnionTypeDefinition union = typeBase.getBaseType();
446         final List<TypeDefinition<?>> unionTypes = union.getTypes();
447         assertEquals(2, unionTypes.size());
448         assertEquals(BaseTypes.int32Type(), unionTypes.get(0));
449         assertTrue(unionTypes.get(1) instanceof UnionTypeDefinition);
450
451         final UnionTypeDefinition unionType1 = (UnionTypeDefinition) unionTypes.get(1);
452         assertEquals(QName.create(BAR, "nested-union2"), unionType1.getQName());
453         assertEquals(Optional.empty(), unionType1.getUnits());
454         assertEquals(Optional.empty(), unionType1.getDefaultValue());
455
456         final UnionTypeDefinition nestedUnion = unionType1.getBaseType();
457         final List<TypeDefinition<?>> nestedUnion2Types = nestedUnion.getTypes();
458         assertEquals(2, nestedUnion2Types.size());
459         assertTrue(nestedUnion2Types.get(1) instanceof StringTypeDefinition);
460         assertTrue(nestedUnion2Types.get(0) instanceof UnionTypeDefinition);
461
462         final UnionTypeDefinition myUnionExt = (UnionTypeDefinition) nestedUnion2Types.get(0);
463         assertEquals(QName.create(BAR, "my-union-ext"), myUnionExt.getQName());
464         assertEquals(Optional.empty(), myUnionExt.getUnits());
465         assertEquals(Optional.empty(), myUnionExt.getDefaultValue());
466
467
468         final UnionTypeDefinition myUnion = myUnionExt.getBaseType();
469         assertEquals(QName.create(BAR, "my-union"), myUnion.getQName());
470         assertEquals(Optional.empty(), myUnion.getUnits());
471         assertEquals(Optional.empty(), myUnion.getDefaultValue());
472
473         final UnionTypeDefinition myUnionBase = myUnion.getBaseType();
474         final List<TypeDefinition<?>> myUnionBaseTypes = myUnionBase.getTypes();
475         assertEquals(2, myUnionBaseTypes.size());
476         assertTrue(myUnionBaseTypes.get(0) instanceof Int16TypeDefinition);
477         assertEquals(BaseTypes.int32Type(), myUnionBaseTypes.get(1));
478
479         final Int16TypeDefinition int16Ext = (Int16TypeDefinition) myUnionBaseTypes.get(0);
480         assertEquals(TypeDefinitions.INT16, int16Ext.getQName());
481         assertEquals(Optional.empty(), int16Ext.getUnits());
482         assertEquals(Optional.empty(), int16Ext.getDefaultValue());
483         final Set<? extends Range<? extends Number>> ranges = int16Ext.getRangeConstraint().get().getAllowedRanges()
484                 .asRanges();
485         assertEquals(1, ranges.size());
486         final Range<? extends Number> range = ranges.iterator().next();
487         assertEquals(1, range.lowerEndpoint().intValue());
488         assertEquals(100, range.upperEndpoint().intValue());
489
490         assertEquals(BaseTypes.int16Type(), int16Ext.getBaseType());
491     }
492
493     @Test
494     public void testChoice() {
495         final ContainerSchemaNode transfer = (ContainerSchemaNode) foo.getDataChildByName(
496             QName.create(foo.getQNameModule(), "transfer"));
497         final ChoiceSchemaNode how = (ChoiceSchemaNode) transfer.getDataChildByName(
498             QName.create(foo.getQNameModule(), "how"));
499         final Collection<? extends CaseSchemaNode> cases = how.getCases();
500         assertEquals(5, cases.size());
501         CaseSchemaNode input = null;
502         CaseSchemaNode output = null;
503         for (final CaseSchemaNode caseNode : cases) {
504             if ("input".equals(caseNode.getQName().getLocalName())) {
505                 input = caseNode;
506             } else if ("output".equals(caseNode.getQName().getLocalName())) {
507                 output = caseNode;
508             }
509         }
510         assertNotNull(input);
511         assertNotNull(output);
512     }
513
514     @Test
515     public void testDeviation() {
516         final Collection<? extends Deviation> deviations = foo.getDeviations();
517         assertEquals(1, deviations.size());
518         final Deviation dev = deviations.iterator().next();
519         assertEquals(Optional.of("system/user ref"), dev.getReference());
520
521         assertEquals(Absolute.of(QName.create(BAR, "interfaces"), QName.create(BAR, "ifEntry")), dev.getTargetPath());
522         assertEquals(DeviateKind.ADD, dev.getDeviates().iterator().next().getDeviateType());
523     }
524
525     @Test
526     public void testUnknownNode() {
527         final ContainerSchemaNode network = (ContainerSchemaNode) baz.getDataChildByName(
528             QName.create(baz.getQNameModule(), "network"));
529         final Collection<? extends UnrecognizedStatement> unknownNodes = network.asEffectiveStatement().getDeclared()
530             .declaredSubstatements(UnrecognizedStatement.class);
531         assertEquals(1, unknownNodes.size());
532         assertEquals("point", unknownNodes.iterator().next().argument());
533     }
534
535     @Test
536     public void testFeature() {
537         final Collection<? extends FeatureDefinition> features = baz.getFeatures();
538         assertEquals(3, features.size());
539     }
540
541     @Test
542     public void testExtension() {
543         final Collection<? extends ExtensionDefinition> extensions = baz.getExtensionSchemaNodes();
544         assertEquals(1, extensions.size());
545         final ExtensionDefinition extension = extensions.iterator().next();
546         assertEquals("name", extension.getArgument());
547         assertEquals(
548             Optional.of("Takes as argument a name string. Makes the code generator use the given name in the #define."),
549                 extension.getDescription());
550         assertTrue(extension.isYinElement());
551     }
552
553     @Test
554     public void testNotification() {
555         final Collection<? extends NotificationDefinition> notifications = baz.getNotifications();
556         assertEquals(1, notifications.size());
557
558         final NotificationDefinition notification = notifications.iterator().next();
559         // test SchemaNode args
560         assertEquals(QName.create(BAZ, "event"), notification.getQName());
561         final SchemaPath expectedPath = SchemaPath.create(true,  QName.create(BAZ, "event"));
562         assertPathEquals(expectedPath, notification);
563         assertFalse(notification.getDescription().isPresent());
564         assertFalse(notification.getReference().isPresent());
565         assertEquals(Status.CURRENT, notification.getStatus());
566         assertEquals(0, notification.getUnknownSchemaNodes().size());
567         // test DataNodeContainer args
568         assertEquals(0, notification.getTypeDefinitions().size());
569         assertEquals(3, notification.getChildNodes().size());
570         assertEquals(0, notification.getGroupings().size());
571         assertEquals(0, notification.getUses().size());
572
573         final LeafSchemaNode eventClass = (LeafSchemaNode) notification.getDataChildByName(
574             QName.create(baz.getQNameModule(), "event-class"));
575         assertTrue(eventClass.getType() instanceof StringTypeDefinition);
576         final LeafSchemaNode severity = (LeafSchemaNode) notification.getDataChildByName(
577             QName.create(baz.getQNameModule(), "severity"));
578         assertTrue(severity.getType() instanceof StringTypeDefinition);
579     }
580
581     @Test
582     public void testRpc() {
583         final Collection<? extends RpcDefinition> rpcs = baz.getRpcs();
584         assertEquals(1, rpcs.size());
585
586         final RpcDefinition rpc = rpcs.iterator().next();
587         assertEquals(Optional.of("Retrieve all or part of a specified configuration."), rpc.getDescription());
588         assertEquals(Optional.of("RFC 6241, Section 7.1"), rpc.getReference());
589     }
590
591     @Test
592     public void testTypePath() throws ParseException {
593         final Collection<? extends TypeDefinition<?>> types = bar.getTypeDefinitions();
594
595         // int32-ext1
596         final Int32TypeDefinition int32ext1 = (Int32TypeDefinition) TestUtils.findTypedef(types, "int32-ext1");
597         assertEquals(QName.create(BAR, "int32-ext1"), int32ext1.getQName());
598
599         // int32-ext1/int32
600         assertEquals(BaseTypes.int32Type(), int32ext1.getBaseType());
601     }
602
603     @Test
604     public void testTypePath2() throws ParseException {
605         final Collection<? extends TypeDefinition<?>> types = bar.getTypeDefinitions();
606
607         // my-decimal-type
608         final DecimalTypeDefinition myDecType = (DecimalTypeDefinition) TestUtils.findTypedef(types, "my-decimal-type");
609         final QName myDecTypeQName = myDecType.getQName();
610
611         assertEquals(BAR, myDecTypeQName.getModule());
612         assertEquals("my-decimal-type", myDecTypeQName.getLocalName());
613
614         // my-base-int32-type/int32
615         final DecimalTypeDefinition dec64 = myDecType.getBaseType();
616         final QName dec64QName = dec64.getQName();
617
618         assertEquals(BAR, dec64QName.getModule());
619         assertEquals("decimal64", dec64QName.getLocalName());
620     }
621
622     private static void checkOrder(final Collection<Module> modules) {
623         final Iterator<Module> it = modules.iterator();
624         Module module = it.next();
625         assertEquals("m2", module.getName());
626         module = it.next();
627         assertEquals("m4", module.getName());
628         module = it.next();
629         assertEquals("m6", module.getName());
630         module = it.next();
631         assertEquals("m8", module.getName());
632         module = it.next();
633         assertEquals("m7", module.getName());
634         module = it.next();
635         assertEquals("m5", module.getName());
636         module = it.next();
637         assertEquals("m3", module.getName());
638         module = it.next();
639         assertEquals("m1", module.getName());
640     }
641
642     private static void assertSetEquals(final Set<Module> s1, final Set<Module> s2) {
643         assertEquals(s1, s2);
644         final Iterator<Module> it = s1.iterator();
645         for (final Module m : s2) {
646             assertEquals(m, it.next());
647         }
648     }
649
650     @Test
651     public void testSubmodules() {
652         final DataSchemaNode id = foo.getDataChildByName(QName.create(foo.getQNameModule(), "id"));
653         assertNotNull(id);
654         final DataSchemaNode subExt = foo.getDataChildByName(QName.create(foo.getQNameModule(), "sub-ext"));
655         assertNotNull(subExt);
656         final DataSchemaNode subTransfer = foo.getDataChildByName(QName.create(foo.getQNameModule(), "sub-transfer"));
657         assertNotNull(subTransfer);
658
659         assertEquals(2, foo.getExtensionSchemaNodes().size());
660         assertEquals(2, foo.getAugmentations().size());
661     }
662
663     @Test
664     public void unknownStatementInSubmoduleHeaderTest() throws IOException, URISyntaxException, ReactorException {
665         final StatementStreamSource yang1 = sourceForResource("/yang-grammar-test/revisions-extension.yang");
666         final StatementStreamSource yang2 = sourceForResource("/yang-grammar-test/submodule-header-extension.yang");
667         TestUtils.parseYangSources(yang1, yang2);
668     }
669
670     @Test
671     public void unknownStatementBetweenRevisionsTest() throws ReactorException {
672         final SchemaContext result = RFC7950Reactors.defaultReactor().newBuild()
673                 .addSource(sourceForResource("/yang-grammar-test/revisions-extension.yang"))
674                 .addSource(sourceForResource("/yang-grammar-test/submodule-header-extension.yang"))
675                 .buildEffective();
676         assertNotNull(result);
677     }
678
679     @Test
680     public void unknownStatementsInStatementsTest() {
681
682         final StatementStreamSource yangFile1 = sourceForResource(
683                 "/yang-grammar-test/stmtsep-in-statements.yang");
684         final StatementStreamSource yangFile2 = sourceForResource(
685                 "/yang-grammar-test/stmtsep-in-statements2.yang");
686         final StatementStreamSource yangFile3 = sourceForResource(
687                 "/yang-grammar-test/stmtsep-in-statements-sub.yang");
688
689         final BuildAction reactor = RFC7950Reactors.defaultReactor().newBuild()
690                 .addSources(yangFile1, yangFile2, yangFile3);
691         // TODO: change test or create new module in order to respect new statement parser validations
692         try {
693             final SchemaContext result = reactor.buildEffective();
694         } catch (final ReactorException e) {
695             assertEquals(SomeModifiersUnresolvedException.class, e.getClass());
696             assertTrue(e.getCause() instanceof SourceException);
697             assertTrue(e.getCause().getMessage().startsWith("aaa is not a YANG statement or use of extension"));
698         }
699     }
700
701 }