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