Introduce yangtools.binding.meta
[yangtools.git] / parser / yang-parser-rfc7950 / src / test / java / org / opendaylight / yangtools / yang / stmt / AugmentTest.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.assertNotNull;
13 import static org.junit.jupiter.api.Assertions.assertTrue;
14
15 import org.junit.jupiter.api.BeforeAll;
16 import org.junit.jupiter.api.Test;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.common.Revision;
20 import org.opendaylight.yangtools.yang.common.XMLNamespace;
21 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
26 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
28 import org.opendaylight.yangtools.yang.model.api.InputSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.Module;
32 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
33 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
34 import org.opendaylight.yangtools.yang.model.api.type.TypeDefinitions;
35
36 class AugmentTest extends AbstractYangTest {
37     private static final QNameModule FOO = QNameModule.of("urn:opendaylight.foo", "2013-10-13");
38     private static final QNameModule BAR = QNameModule.of("urn:opendaylight.bar", "2013-10-14");
39     private static final QNameModule BAZ = QNameModule.of("urn:opendaylight.baz", "2013-10-15");
40
41     private static final QName Q0 = QName.create(BAR, "interfaces");
42     private static final QName Q1 = QName.create(BAR, "ifEntry");
43     private static final QName Q2 = QName.create(BAZ, "augment-holder");
44
45     private static EffectiveModelContext AUGMENT_IN_AUGMENT;
46
47     @BeforeAll
48     static void beforeClass() throws Exception {
49         AUGMENT_IN_AUGMENT = assertEffectiveModelDir("/augment-test/augment-in-augment");
50     }
51
52     @Test
53     void testAugmentParsing() {
54         // foo.yang
55         final Module module1 = AUGMENT_IN_AUGMENT.findModules("foo").iterator().next();
56         var augmentations = module1.getAugmentations();
57         assertEquals(1, augmentations.size());
58         final AugmentationSchemaNode augment = augmentations.iterator().next();
59         assertNotNull(augment);
60
61         assertEquals(Absolute.of(Q0, Q1, Q2), augment.getTargetPath());
62
63         final var augmentChildren = augment.getChildNodes();
64         assertEquals(4, augmentChildren.size());
65         for (final DataSchemaNode dsn : augmentChildren) {
66             checkIsAugmenting(dsn, false);
67         }
68
69         final LeafSchemaNode ds0ChannelNumber = (LeafSchemaNode) augment.getDataChildByName(QName.create(
70             module1.getQNameModule(), "ds0ChannelNumber"));
71         final LeafSchemaNode interfaceId = (LeafSchemaNode) augment.getDataChildByName(QName.create(
72             module1.getQNameModule(), "interface-id"));
73         final ContainerSchemaNode schemas = (ContainerSchemaNode) augment.getDataChildByName(QName.create(
74             module1.getQNameModule(), "schemas"));
75         final ChoiceSchemaNode odl = (ChoiceSchemaNode) augment.getDataChildByName(QName.create(
76             module1.getQNameModule(), "odl"));
77
78         assertNotNull(ds0ChannelNumber);
79         assertNotNull(interfaceId);
80         assertNotNull(schemas);
81         assertNotNull(odl);
82
83         // leaf ds0ChannelNumber
84         assertEquals(QName.create(FOO, "ds0ChannelNumber"), ds0ChannelNumber.getQName());
85         assertFalse(ds0ChannelNumber.isAugmenting());
86         // type of leaf ds0ChannelNumber
87         assertEquals(TypeDefinitions.STRING, ds0ChannelNumber.getType().getQName());
88
89         // leaf interface-id
90         assertEquals(QName.create(FOO, "interface-id"), interfaceId.getQName());
91         assertFalse(interfaceId.isAugmenting());
92
93         // container schemas
94         assertEquals(QName.create(FOO, "schemas"), schemas.getQName());
95         assertFalse(schemas.isAugmenting());
96
97         // choice odl
98         assertEquals(QName.create(FOO, "odl"), odl.getQName());
99         assertFalse(odl.isAugmenting());
100
101         // baz.yang
102         final Module module3 = AUGMENT_IN_AUGMENT.findModules("baz").iterator().next();
103         augmentations = module3.getAugmentations();
104         assertEquals(3, augmentations.size());
105         AugmentationSchemaNode augment1 = null;
106         AugmentationSchemaNode augment2 = null;
107         AugmentationSchemaNode augment3 = null;
108         for (final AugmentationSchemaNode as : augmentations) {
109             if (as.getWhenCondition().isEmpty()) {
110                 augment3 = as;
111             } else if ("br:ifType='ds0'".equals(as.getWhenCondition().orElseThrow().toString())) {
112                 augment1 = as;
113             } else if ("br:ifType='ds2'".equals(as.getWhenCondition().orElseThrow().toString())) {
114                 augment2 = as;
115             }
116         }
117         assertNotNull(augment1);
118         assertNotNull(augment2);
119         assertNotNull(augment3);
120
121         assertEquals(1, augment1.getChildNodes().size());
122         final ContainerSchemaNode augmentHolder = (ContainerSchemaNode) augment1.getDataChildByName(QName.create(
123             module3.getQNameModule(), "augment-holder"));
124         assertNotNull(augmentHolder);
125
126         assertEquals(1, augment2.getChildNodes().size());
127         final ContainerSchemaNode augmentHolder2 = (ContainerSchemaNode) augment2.getDataChildByName(QName.create(
128             module3.getQNameModule(), "augment-holder2"));
129         assertNotNull(augmentHolder2);
130
131         assertEquals(1, augment3.getChildNodes().size());
132         final CaseSchemaNode pause = (CaseSchemaNode) augment3.getDataChildByName(QName.create(
133             module3.getQNameModule(), "pause"));
134         assertNotNull(pause);
135     }
136
137     @Test
138     void testAugmentResolving() {
139         final Module module2 = AUGMENT_IN_AUGMENT.findModules("bar").iterator().next();
140         final ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName(QName.create(
141             module2.getQNameModule(), "interfaces"));
142         final ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName(QName.create(
143             module2.getQNameModule(), "ifEntry"));
144
145         // baz.yang
146         // augment "/br:interfaces/br:ifEntry" {
147         final ContainerSchemaNode augmentHolder = (ContainerSchemaNode) ifEntry.getDataChildByName(QName.create(BAZ,
148             "augment-holder"));
149         checkIsAugmenting(augmentHolder, true);
150         assertEquals(Q2, augmentHolder.getQName());
151
152         // foo.yang
153         // augment "/br:interfaces/br:ifEntry/bz:augment-holder"
154         final LeafSchemaNode ds0ChannelNumber = (LeafSchemaNode) augmentHolder.getDataChildByName(QName.create(FOO,
155             "ds0ChannelNumber"));
156         final LeafSchemaNode interfaceId = (LeafSchemaNode) augmentHolder.getDataChildByName(QName.create(FOO,
157             "interface-id"));
158         final ContainerSchemaNode schemas = (ContainerSchemaNode) augmentHolder.getDataChildByName(QName.create(FOO,
159             "schemas"));
160         final ChoiceSchemaNode odl = (ChoiceSchemaNode) augmentHolder.getDataChildByName(QName.create(FOO, "odl"));
161
162         assertNotNull(ds0ChannelNumber);
163         assertNotNull(interfaceId);
164         assertNotNull(schemas);
165         assertNotNull(odl);
166
167         // leaf ds0ChannelNumber
168         assertEquals(QName.create(FOO, "ds0ChannelNumber"), ds0ChannelNumber.getQName());
169
170         // leaf interface-id
171         assertEquals(QName.create(FOO, "interface-id"), interfaceId.getQName());
172
173         // container schemas
174         assertEquals(QName.create(FOO, "schemas"), schemas.getQName());
175
176         // choice odl
177         assertEquals(QName.create(FOO, "odl"), odl.getQName());
178     }
179
180     @Test
181     void testAugmentedChoice() {
182         final Module module2 = AUGMENT_IN_AUGMENT.findModules("bar").iterator().next();
183         final ContainerSchemaNode interfaces = (ContainerSchemaNode) module2.getDataChildByName(QName.create(
184             module2.getQNameModule(), "interfaces"));
185         final ListSchemaNode ifEntry = (ListSchemaNode) interfaces.getDataChildByName(QName.create(
186             module2.getQNameModule(), "ifEntry"));
187         final ContainerSchemaNode augmentedHolder = (ContainerSchemaNode) ifEntry.getDataChildByName(QName.create(
188             BAZ, "augment-holder"));
189         checkIsAugmenting(augmentedHolder, true);
190
191         // foo.yang
192         // augment "/br:interfaces/br:ifEntry/bz:augment-holder"
193         final ChoiceSchemaNode odl = (ChoiceSchemaNode) augmentedHolder.getDataChildByName(QName.create(FOO, "odl"));
194         assertNotNull(odl);
195         final var cases = odl.getCases();
196         assertEquals(4, cases.size());
197
198         CaseSchemaNode id = null;
199         CaseSchemaNode node1 = null;
200         CaseSchemaNode node2 = null;
201         CaseSchemaNode node3 = null;
202
203         for (final CaseSchemaNode ccn : cases) {
204             if ("id".equals(ccn.getQName().getLocalName())) {
205                 id = ccn;
206             } else if ("node1".equals(ccn.getQName().getLocalName())) {
207                 node1 = ccn;
208             } else if ("node2".equals(ccn.getQName().getLocalName())) {
209                 node2 = ccn;
210             } else if ("node3".equals(ccn.getQName().getLocalName())) {
211                 node3 = ccn;
212             }
213         }
214
215         assertNotNull(id);
216         assertNotNull(node1);
217         assertNotNull(node2);
218         assertNotNull(node3);
219
220         // case id
221         assertEquals(QName.create(FOO, "id"), id.getQName());
222         final var idChildren = id.getChildNodes();
223         assertEquals(1, idChildren.size());
224
225         // case node1
226         assertEquals(QName.create(FOO, "node1"), node1.getQName());
227         final var node1Children = node1.getChildNodes();
228         assertTrue(node1Children.isEmpty());
229
230         // case node2
231         assertEquals(QName.create(FOO, "node2"), node2.getQName());
232         final var node2Children = node2.getChildNodes();
233         assertTrue(node2Children.isEmpty());
234
235         // case node3
236         assertEquals(QName.create(FOO, "node3"), node3.getQName());
237         final var node3Children = node3.getChildNodes();
238         assertEquals(1, node3Children.size());
239
240         // test cases
241         // case id child
242         final LeafSchemaNode caseIdChild = (LeafSchemaNode) idChildren.iterator().next();
243         assertNotNull(caseIdChild);
244         assertEquals(QName.create(FOO, "id"), caseIdChild.getQName());
245
246         // case node3 child
247         final ContainerSchemaNode caseNode3Child = (ContainerSchemaNode) node3Children.iterator().next();
248         assertNotNull(caseNode3Child);
249         assertEquals(QName.create(FOO, "node3"), caseNode3Child.getQName());
250     }
251
252     @Test
253     void testAugmentRpc() throws Exception {
254         final EffectiveModelContext context = assertEffectiveModelDir("/augment-test/rpc");
255         final XMLNamespace NS_BAR = XMLNamespace.of("urn:opendaylight:bar");
256         final XMLNamespace NS_FOO = XMLNamespace.of("urn:opendaylight:foo");
257         final Revision revision = Revision.of("2013-10-11");
258         final Module bar = context.findModules("bar").iterator().next();
259         final var rpcs = bar.getRpcs();
260         assertEquals(2, rpcs.size());
261
262         RpcDefinition submit = null;
263         for (final RpcDefinition rpc : rpcs) {
264             if ("submit".equals(rpc.getQName().getLocalName())) {
265                 submit = rpc;
266                 break;
267             }
268         }
269         assertNotNull(submit);
270
271         final QName submitQName = QName.create(NS_BAR, revision, "submit");
272         assertEquals(submitQName, submit.getQName());
273         final InputSchemaNode input = submit.getInput();
274         final QName inputQName = QName.create(NS_BAR, revision, "input");
275         assertEquals(inputQName, input.getQName());
276         final ChoiceSchemaNode arguments = (ChoiceSchemaNode) input.getDataChildByName(QName.create(NS_BAR, revision,
277             "arguments"));
278         final QName argumentsQName = QName.create(NS_BAR, revision, "arguments");
279         assertEquals(argumentsQName, arguments.getQName());
280         assertFalse(arguments.isAugmenting());
281         final var cases = arguments.getCases();
282         assertEquals(3, cases.size());
283
284         CaseSchemaNode attach = null;
285         CaseSchemaNode create = null;
286         CaseSchemaNode destroy = null;
287         for (final CaseSchemaNode child : cases) {
288             if ("attach".equals(child.getQName().getLocalName())) {
289                 attach = child;
290             } else if ("create".equals(child.getQName().getLocalName())) {
291                 create = child;
292             } else if ("destroy".equals(child.getQName().getLocalName())) {
293                 destroy = child;
294             }
295         }
296         assertNotNull(attach);
297         assertNotNull(create);
298         assertNotNull(destroy);
299
300         assertTrue(attach.isAugmenting());
301         assertTrue(create.isAugmenting());
302         assertTrue(destroy.isAugmenting());
303
304         // case attach
305         assertEquals(QName.create(NS_FOO, revision, "attach"), attach.getQName());
306         final var attachChildren = attach.getChildNodes();
307         assertEquals(1, attachChildren.size());
308
309         // case create
310         assertEquals(QName.create(NS_FOO, revision, "create"), create.getQName());
311         final var createChildren = create.getChildNodes();
312         assertEquals(1, createChildren.size());
313
314         // case attach
315         assertEquals(QName.create(NS_FOO, revision, "destroy"), destroy.getQName());
316         final var destroyChildren = destroy.getChildNodes();
317         assertEquals(1, destroyChildren.size());
318     }
319
320     @Test
321     void testAugmentInUsesResolving() throws Exception {
322         final EffectiveModelContext context = assertEffectiveModelDir("/augment-test/augment-in-uses");
323         assertEquals(1, context.getModules().size());
324
325         final Module test = context.getModules().iterator().next();
326         final DataNodeContainer links = (DataNodeContainer) test.getDataChildByName(QName.create(test.getQNameModule(),
327             "links"));
328         final DataNodeContainer link = (DataNodeContainer) links.getDataChildByName(QName.create(test.getQNameModule(),
329             "link"));
330         final DataNodeContainer nodes = (DataNodeContainer) link.getDataChildByName(QName.create(test.getQNameModule(),
331             "nodes"));
332         final ContainerSchemaNode node = (ContainerSchemaNode) nodes.getDataChildByName(QName.create(
333             test.getQNameModule(), "node"));
334         final var augments = node.getAvailableAugmentations();
335         assertEquals(1, augments.size());
336         assertEquals(1, node.getChildNodes().size());
337         final LeafSchemaNode id = (LeafSchemaNode) node.getDataChildByName(QName.create(test.getQNameModule(), "id"));
338         assertTrue(id.isAugmenting());
339     }
340
341     /**
342      * Test if node has augmenting flag set to expected value. In case this is  DataNodeContainer/ChoiceNode, check its
343      * child nodes/case nodes too.
344      *
345      * @param node node to check
346      * @param expected expected value
347      */
348     private static void checkIsAugmenting(final DataSchemaNode node, final boolean expected) {
349         assertEquals(expected, node.isAugmenting());
350         if (node instanceof DataNodeContainer) {
351             for (DataSchemaNode child : ((DataNodeContainer) node).getChildNodes()) {
352                 checkIsAugmenting(child, expected);
353             }
354         } else if (node instanceof ChoiceSchemaNode) {
355             for (CaseSchemaNode caseNode : ((ChoiceSchemaNode) node).getCases()) {
356                 checkIsAugmenting(caseNode, expected);
357             }
358         }
359     }
360 }