Migrate users of Optional.get()
[yangtools.git] / parser / yang-parser-rfc7950 / src / test / java / org / opendaylight / yangtools / yang / stmt / YangParserWithContextTest.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.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertFalse;
12 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
13 import static org.junit.jupiter.api.Assertions.assertNotEquals;
14 import static org.junit.jupiter.api.Assertions.assertNotNull;
15 import static org.junit.jupiter.api.Assertions.assertSame;
16 import static org.junit.jupiter.api.Assertions.assertTrue;
17 import static org.opendaylight.yangtools.yang.stmt.StmtTestUtils.sourceForResource;
18
19 import com.google.common.collect.Iterables;
20 import com.google.common.collect.Range;
21 import java.util.Optional;
22 import org.junit.jupiter.api.Test;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.common.Revision;
25 import org.opendaylight.yangtools.yang.common.Uint8;
26 import org.opendaylight.yangtools.yang.common.XMLNamespace;
27 import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.DeviateKind;
31 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.UsesNode;
35 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
36 import org.opendaylight.yangtools.yang.model.api.stmt.UnrecognizedStatement;
37 import org.opendaylight.yangtools.yang.model.api.type.Uint16TypeDefinition;
38 import org.opendaylight.yangtools.yang.model.api.type.Uint8TypeDefinition;
39 import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.RFC7950Reactors;
40 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
41
42 class YangParserWithContextTest {
43     private static final XMLNamespace T1_NS = XMLNamespace.of("urn:simple.demo.test1");
44     private static final XMLNamespace T2_NS = XMLNamespace.of("urn:simple.demo.test2");
45     private static final XMLNamespace T3_NS = XMLNamespace.of("urn:simple.demo.test3");
46     private static final Revision REV = Revision.of("2013-06-18");
47
48     private static final StatementStreamSource BAR = sourceForResource("/model/bar.yang");
49     private static final StatementStreamSource BAZ = sourceForResource("/model/baz.yang");
50     private static final StatementStreamSource FOO = sourceForResource("/model/foo.yang");
51     private static final StatementStreamSource SUBFOO = sourceForResource("/model/subfoo.yang");
52
53     private static final StatementStreamSource[] IETF = new StatementStreamSource[]{
54         sourceForResource("/ietf/iana-afn-safi@2012-06-04.yang"),
55         sourceForResource("/ietf/iana-if-type@2012-06-05.yang"),
56         sourceForResource("/ietf/iana-timezones@2012-07-09.yang"),
57         sourceForResource("/ietf/ietf-inet-types@2010-09-24.yang"),
58         sourceForResource("/ietf/ietf-yang-types@2010-09-24.yang"),
59         sourceForResource("/ietf/network-topology@2013-07-12.yang"),
60         sourceForResource("/ietf/network-topology@2013-10-21.yang")};
61
62     @Test
63     void testTypeFromContext() throws Exception {
64         final var context = RFC7950Reactors.defaultReactor().newBuild()
65             .addSources(IETF)
66             .addSource(sourceForResource("/types/custom-types-test@2012-04-04.yang"))
67             .addSource(sourceForResource("/context-test/test1.yang"))
68             .buildEffective();
69
70         final var module = context.findModule("test1", Revision.of("2013-06-18")).orElseThrow();
71         final var leaf = assertInstanceOf(LeafSchemaNode.class,
72             module.getDataChildByName(QName.create(module.getQNameModule(), "id")));
73
74         final var leafType = assertInstanceOf(Uint16TypeDefinition.class, leaf.getType());
75         QName qname = leafType.getQName();
76         assertEquals(XMLNamespace.of("urn:simple.demo.test1"), qname.getNamespace());
77         assertEquals(Revision.ofNullable("2013-06-18"), qname.getRevision());
78         assertEquals("port-number", qname.getLocalName());
79
80         final var leafBaseType = leafType.getBaseType();
81         qname = leafBaseType.getQName();
82         assertEquals(XMLNamespace.of("urn:ietf:params:xml:ns:yang:ietf-inet-types"), qname.getNamespace());
83         assertEquals(Revision.ofNullable("2010-09-24"), qname.getRevision());
84         assertEquals("port-number", qname.getLocalName());
85
86         final var dscpExt = assertInstanceOf(Uint8TypeDefinition.class,
87             TestUtils.findTypedef(module.getTypeDefinitions(), "dscp-ext"));
88         final var ranges = dscpExt.getRangeConstraint().orElseThrow().getAllowedRanges().asRanges();
89         assertEquals(1, ranges.size());
90         final Range<?> range = ranges.iterator().next();
91         assertEquals(Uint8.valueOf(0), range.lowerEndpoint());
92         assertEquals(Uint8.valueOf(63), range.upperEndpoint());
93     }
94
95     @Test
96     void testUsesFromContext() throws Exception {
97         final var context = RFC7950Reactors.defaultReactor().newBuild()
98             .addSources(BAZ, FOO, BAR, SUBFOO, sourceForResource("/context-test/test2.yang"))
99             .buildEffective();
100
101         final var testModule = context.findModule("test2", Revision.of("2013-06-18")).orElseThrow();
102         final var contextModule = context.findModules(XMLNamespace.of("urn:opendaylight.baz")).iterator().next();
103         assertNotNull(contextModule);
104         final var groupings = contextModule.getGroupings();
105         assertEquals(1, groupings.size());
106         final var grouping = groupings.iterator().next();
107
108         // get node containing uses
109         final var peer = assertInstanceOf(ContainerSchemaNode.class,
110             testModule.getDataChildByName(QName.create(testModule.getQNameModule(), "peer")));
111         final var destination = assertInstanceOf(ContainerSchemaNode.class,
112             peer.getDataChildByName(QName.create(testModule.getQNameModule(), "destination")));
113
114         // check uses
115         final var uses = destination.getUses();
116         assertEquals(1, uses.size());
117
118         // check uses process
119         final var data_u = assertInstanceOf(AnyxmlSchemaNode.class,
120             destination.getDataChildByName(QName.create(testModule.getQNameModule(), "data")));
121         assertTrue(data_u.isAddedByUses());
122
123         final var data_g = assertInstanceOf(AnyxmlSchemaNode.class,
124             grouping.getDataChildByName(QName.create(contextModule.getQNameModule(), "data")));
125         assertFalse(data_g.isAddedByUses());
126         assertNotEquals(data_u, data_g);
127
128         final var how_u = assertInstanceOf(ChoiceSchemaNode.class,
129             destination.getDataChildByName(QName.create(testModule.getQNameModule(), "how")));
130         assertTrue(how_u.isAddedByUses());
131
132         final var how_g = assertInstanceOf(ChoiceSchemaNode.class,
133             grouping.getDataChildByName(QName.create(contextModule.getQNameModule(), "how")));
134         assertFalse(how_g.isAddedByUses());
135         assertNotEquals(how_u, how_g);
136
137         final var address_u = assertInstanceOf(LeafSchemaNode.class,
138             destination.getDataChildByName(QName.create(testModule.getQNameModule(), "address")));
139         assertTrue(address_u.isAddedByUses());
140
141         final var address_g = assertInstanceOf(LeafSchemaNode.class,
142             grouping.getDataChildByName(QName.create(contextModule.getQNameModule(), "address")));
143         assertFalse(address_g.isAddedByUses());
144         assertNotEquals(address_u, address_g);
145
146         final var port_u = assertInstanceOf(ContainerSchemaNode.class,
147             destination.getDataChildByName(QName.create(testModule.getQNameModule(), "port")));
148         assertTrue(port_u.isAddedByUses());
149
150         final var port_g = assertInstanceOf(ContainerSchemaNode.class,
151             grouping.getDataChildByName(QName.create(contextModule.getQNameModule(), "port")));
152         assertNotNull(port_g);
153         assertFalse(port_g.isAddedByUses());
154         assertNotEquals(port_u, port_g);
155
156         final ListSchemaNode addresses_u = assertInstanceOf(ListSchemaNode.class,
157             destination.getDataChildByName(QName.create(testModule.getQNameModule(), "addresses")));
158         assertNotNull(addresses_u);
159         assertTrue(addresses_u.isAddedByUses());
160
161         final ListSchemaNode addresses_g = assertInstanceOf(ListSchemaNode.class,
162             grouping.getDataChildByName(QName.create(contextModule.getQNameModule(), "addresses")));
163         assertNotNull(addresses_g);
164         assertFalse(addresses_g.isAddedByUses());
165         assertNotEquals(addresses_u, addresses_g);
166
167         // grouping defined by 'uses'
168         final var groupings_u = destination.getGroupings();
169         assertEquals(0, groupings_u.size());
170
171         // grouping defined in 'grouping' node
172         final var groupings_g = grouping.getGroupings();
173         assertEquals(1, groupings_g.size());
174         final var grouping_g = groupings_g.iterator().next();
175         assertFalse(grouping_g.isAddedByUses());
176     }
177
178     @Test
179     void testUsesRefineFromContext() throws Exception {
180         final var context = RFC7950Reactors.defaultReactor().newBuild()
181             .addSources(BAZ, FOO, BAR, SUBFOO, sourceForResource("/context-test/test2.yang"))
182             .buildEffective();
183
184         final var module = context.findModule("test2", Revision.of("2013-06-18")).orElseThrow();
185         final var peer = assertInstanceOf(ContainerSchemaNode.class,
186             module.getDataChildByName(QName.create(module.getQNameModule(), "peer")));
187         final var destination = assertInstanceOf(ContainerSchemaNode.class,
188             peer.getDataChildByName(QName.create(module.getQNameModule(), "destination")));
189         final var usesNodes = destination.getUses();
190         assertEquals(1, usesNodes.size());
191         final UsesNode usesNode = usesNodes.iterator().next();
192
193         // test grouping path
194         assertEquals(QName.create(XMLNamespace.of("urn:opendaylight.baz"), Revision.of("2013-02-27"), "target"),
195             usesNode.getSourceGrouping().getQName());
196
197         // test refine
198         final var refines = usesNode.getRefines();
199         assertEquals(3, refines.size());
200
201         LeafSchemaNode refineLeaf = null;
202         ContainerSchemaNode refineContainer = null;
203         ListSchemaNode refineList = null;
204         for (var entry : refines.entrySet()) {
205             final SchemaNode value = entry.getValue();
206             if (value instanceof LeafSchemaNode leaf) {
207                 refineLeaf = leaf;
208             } else if (value instanceof ContainerSchemaNode container) {
209                 refineContainer = container;
210             } else if (value instanceof ListSchemaNode list) {
211                 refineList = list;
212             }
213         }
214
215         // leaf address
216         assertNotNull(refineLeaf);
217         assertEquals("address", refineLeaf.getQName().getLocalName());
218         assertEquals(Optional.of("description of address defined by refine"), refineLeaf.getDescription());
219         assertEquals(Optional.of("address reference added by refine"), refineLeaf.getReference());
220         assertEquals(Optional.of(Boolean.FALSE), refineLeaf.effectiveConfig());
221         assertTrue(refineLeaf.isMandatory());
222         final var leafMustConstraints = refineLeaf.getMustConstraints();
223         assertEquals(1, leafMustConstraints.size());
224         final var leafMust = leafMustConstraints.iterator().next();
225         assertEquals("ifType != 'ethernet' or (ifType = 'ethernet' and ifMTU = 1500)", leafMust.getXpath().toString());
226
227         // container port
228         assertNotNull(refineContainer);
229         final var mustConstraints = refineContainer.getMustConstraints();
230         assertTrue(mustConstraints.isEmpty());
231         assertEquals(Optional.of("description of port defined by refine"), refineContainer.getDescription());
232         assertEquals(Optional.of("port reference added by refine"), refineContainer.getReference());
233         assertEquals(Optional.of(Boolean.FALSE), refineContainer.effectiveConfig());
234         assertTrue(refineContainer.isPresenceContainer());
235
236         // list addresses
237         assertNotNull(refineList);
238         assertEquals(Optional.of("description of addresses defined by refine"), refineList.getDescription());
239         assertEquals(Optional.of("addresses reference added by refine"), refineList.getReference());
240         assertEquals(Optional.of(Boolean.FALSE), refineList.effectiveConfig());
241         final var constraint = refineList.getElementCountConstraint().orElseThrow();
242         assertEquals((Object) 2, constraint.getMinElements());
243         assertEquals((Object) 12, constraint.getMaxElements());
244     }
245
246     @Test
247     void testIdentity() throws Exception {
248         final var context = RFC7950Reactors.defaultReactor().newBuild()
249             .addSources(IETF)
250             .addSource(sourceForResource("/types/custom-types-test@2012-04-04.yang"))
251             .addSource(sourceForResource("/context-test/test3.yang"))
252             .buildEffective();
253
254         final var module = context.findModule("test3", Revision.of("2013-06-18")).orElseThrow();
255         final var identities = module.getIdentities();
256         assertEquals(1, identities.size());
257
258         final var identity = identities.iterator().next();
259         final QName idQName = identity.getQName();
260         assertEquals(XMLNamespace.of("urn:simple.demo.test3"), idQName.getNamespace());
261         assertEquals(Revision.ofNullable("2013-06-18"), idQName.getRevision());
262         assertEquals("pt", idQName.getLocalName());
263
264         final var baseIdentity = Iterables.getOnlyElement(identity.getBaseIdentities());
265         final QName idBaseQName = baseIdentity.getQName();
266         assertEquals(XMLNamespace.of("urn:custom.types.demo"), idBaseQName.getNamespace());
267         assertEquals(Revision.ofNullable("2012-04-16"), idBaseQName.getRevision());
268         assertEquals("service-type", idBaseQName.getLocalName());
269     }
270
271     @Test
272     void testUnknownNodes() throws Exception {
273         final var context = RFC7950Reactors.defaultReactor().newBuild()
274             .addSources(IETF)
275             .addSource(sourceForResource("/types/custom-types-test@2012-04-04.yang"))
276             .addSource(sourceForResource("/context-test/test3.yang"))
277             .buildEffective();
278
279         final var module = context.findModule("test3", Revision.of("2013-06-18")).orElseThrow();
280         final var network = assertInstanceOf(ContainerSchemaNode.class,
281             module.getDataChildByName(QName.create(module.getQNameModule(), "network")))
282             .asEffectiveStatement().getDeclared();
283         final var unknownNodes = network.declaredSubstatements(UnrecognizedStatement.class);
284         assertEquals(1, unknownNodes.size());
285
286         final var un = unknownNodes.iterator().next();
287         final QName unType = un.statementDefinition().getStatementName();
288         assertEquals(XMLNamespace.of("urn:custom.types.demo"), unType.getNamespace());
289         assertEquals(Revision.ofNullable("2012-04-16"), unType.getRevision());
290         assertEquals("mountpoint", unType.getLocalName());
291         assertEquals("point", un.argument());
292     }
293
294     @Test
295     void testAugment() throws Exception {
296         final var t4 = TestUtils.parseYangSource(
297             "/context-augment-test/test1.yang", "/context-augment-test/test2.yang",
298             "/context-augment-test/test3.yang", "/context-augment-test/test4.yang")
299             .findModules("test4").iterator().next();
300         final var interfaces = assertInstanceOf(ContainerSchemaNode.class,
301             t4.getDataChildByName(QName.create(t4.getQNameModule(), "interfaces")));
302         final var ifEntry = assertInstanceOf(ListSchemaNode.class,
303             interfaces.getDataChildByName(QName.create(t4.getQNameModule(), "ifEntry")));
304
305         // test augmentation process
306         final var augmentHolder = assertInstanceOf(ContainerSchemaNode.class,
307             ifEntry.getDataChildByName(QName.create(T3_NS, REV, "augment-holder")));
308         final var ds0 = augmentHolder.getDataChildByName(QName.create(T2_NS, REV, "ds0ChannelNumber"));
309         final var interfaceId = augmentHolder.getDataChildByName(QName.create(T2_NS, REV, "interface-id"));
310         assertNotNull(interfaceId);
311         final var higherLayerIf = augmentHolder.getDataChildByName(QName.create(T2_NS, REV, "higher-layer-if"));
312         final var schemas = assertInstanceOf(ContainerSchemaNode.class,
313             augmentHolder.getDataChildByName(QName.create(T2_NS, REV, "schemas")));
314         assertNotNull(schemas.getDataChildByName(QName.create(T1_NS, REV, "id")));
315
316         // test augment target after augmentation: check if it is same instance
317         final var ifEntryAfterAugment = assertInstanceOf(ListSchemaNode.class,
318             interfaces.getDataChildByName(QName.create(t4.getQNameModule(), "ifEntry")));
319         assertSame(ifEntry, ifEntryAfterAugment);
320     }
321
322     @Test
323     void testDeviation() throws Exception {
324         final var context = RFC7950Reactors.defaultReactor().newBuild()
325             .addSource(sourceForResource("/model/bar.yang"))
326             .addSource(sourceForResource("/context-test/deviation-test.yang"))
327             .buildEffective();
328
329         final var testModule = context.findModule("deviation-test", Revision.of("2013-02-27")).orElseThrow();
330         final var deviations = testModule.getDeviations();
331         assertEquals(1, deviations.size());
332         final var dev = deviations.iterator().next();
333
334         assertEquals(Optional.of("system/user ref"), dev.getReference());
335
336         final XMLNamespace expectedNS = XMLNamespace.of("urn:opendaylight.bar");
337         final Revision expectedRev = Revision.of("2013-07-03");
338
339         assertEquals(Absolute.of(
340                 QName.create(expectedNS, expectedRev, "interfaces"), QName.create(expectedNS, expectedRev, "ifEntry")),
341             dev.getTargetPath());
342         assertEquals(DeviateKind.ADD, dev.getDeviates().iterator().next().getDeviateType());
343     }
344 }