Remove test dependency on xerces
[netconf.git] / netconf / sal-netconf-connector / src / test / java / org / opendaylight / netconf / sal / connect / netconf / schema / mapping / NetconfMessageTransformerTest.java
1 /*
2  * Copyright (c) 2014, 2015 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.netconf.sal.connect.netconf.schema.mapping;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertThat;
14 import static org.junit.Assert.assertTrue;
15 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.CREATE_SUBSCRIPTION_RPC_CONTENT;
16 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.CREATE_SUBSCRIPTION_RPC_QNAME;
17 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.GET_SCHEMA_QNAME;
18 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_CANDIDATE_QNAME;
19 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME;
20 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_QNAME;
21 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DISCARD_CHANGES_QNAME;
22 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME;
23 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME;
24 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_QNAME;
25 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_LOCK_QNAME;
26 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_RUNNING_QNAME;
27 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.createEditConfigStructure;
28 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toFilterStructure;
29 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toId;
30 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
31
32 import com.google.common.base.Optional;
33 import com.google.common.collect.ImmutableMap;
34 import com.google.common.collect.Iterables;
35 import com.google.common.collect.Lists;
36 import com.google.common.collect.Maps;
37 import java.io.IOException;
38 import java.util.Arrays;
39 import java.util.Collections;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Set;
44 import javax.xml.transform.dom.DOMSource;
45 import org.custommonkey.xmlunit.Diff;
46 import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier;
47 import org.custommonkey.xmlunit.XMLUnit;
48 import org.hamcrest.CoreMatchers;
49 import org.junit.Before;
50 import org.junit.Test;
51 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
52 import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
53 import org.opendaylight.mdsal.dom.api.DOMActionResult;
54 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
55 import org.opendaylight.netconf.api.NetconfMessage;
56 import org.opendaylight.netconf.api.xml.XmlUtil;
57 import org.opendaylight.netconf.sal.connect.netconf.schema.NetconfRemoteSchemaYangSourceProvider;
58 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
59 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.$YangModuleInfoImpl;
61 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Capabilities;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
65 import org.opendaylight.yangtools.yang.common.QName;
66 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
67 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
68 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
69 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
70 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
71 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
72 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
73 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
74 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
75 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
76 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
77 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
78 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
79 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
80 import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
81 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
82 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
83 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
84 import org.w3c.dom.Node;
85 import org.xml.sax.SAXException;
86
87 public class NetconfMessageTransformerTest {
88
89     private static final String REVISION_EXAMPLE_SERVER_FARM = "2018-08-07";
90     private static final String URN_EXAMPLE_SERVER_FARM = "urn:example:server-farm";
91
92     private NetconfMessageTransformer actionNetconfMessageTransformer;
93     private NetconfMessageTransformer netconfMessageTransformer;
94     private SchemaContext schema;
95
96     @Before
97     public void setUp() throws Exception {
98         XMLUnit.setIgnoreWhitespace(true);
99         XMLUnit.setIgnoreAttributeOrder(true);
100         XMLUnit.setIgnoreComments(true);
101
102         schema = getSchema(true);
103         netconfMessageTransformer = getTransformer(schema);
104         actionNetconfMessageTransformer = getActionMessageTransformer();
105     }
106
107     @Test
108     public void testLockRequestBaseSchemaNotPresent() throws Exception {
109         final SchemaContext partialSchema = getSchema(false);
110         final NetconfMessageTransformer transformer = getTransformer(partialSchema);
111         final NetconfMessage netconfMessage = transformer.toRpcRequest(toPath(NETCONF_LOCK_QNAME),
112                 NetconfBaseOps.getLockContent(NETCONF_CANDIDATE_QNAME));
113
114         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<lock"));
115         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<rpc"));
116     }
117
118     @Test
119     public void testCreateSubscriberNotificationSchemaNotPresent() throws Exception {
120         final SchemaContext partialSchema = getSchema(true);
121         final NetconfMessageTransformer transformer = new NetconfMessageTransformer(
122                 partialSchema,
123                 true,
124                 BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS
125         );
126         NetconfMessage netconfMessage = transformer.toRpcRequest(
127                 toPath(CREATE_SUBSCRIPTION_RPC_QNAME),
128                 CREATE_SUBSCRIPTION_RPC_CONTENT
129         );
130         String documentString = XmlUtil.toString(netconfMessage.getDocument());
131         assertThat(documentString, CoreMatchers.containsString("<create-subscription"));
132         assertThat(documentString, CoreMatchers.containsString("<rpc"));
133     }
134
135     @Test
136     public void tesLockSchemaRequest() throws Exception {
137         final SchemaContext partialSchema = getSchema(false);
138         final NetconfMessageTransformer transformer = getTransformer(partialSchema);
139         final String result = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>";
140
141         transformer.toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)), toPath(NETCONF_LOCK_QNAME));
142     }
143
144     @Test
145     public void testDiscardChangesRequest() throws Exception {
146         final NetconfMessage netconfMessage =
147                 netconfMessageTransformer.toRpcRequest(toPath(NETCONF_DISCARD_CHANGES_QNAME), null);
148         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<discard"));
149         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<rpc"));
150         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("message-id"));
151     }
152
153     @Test
154     public void testGetSchemaRequest() throws Exception {
155         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(GET_SCHEMA_QNAME),
156                 NetconfRemoteSchemaYangSourceProvider.createGetSchemaRequest("module", Optional.of("2012-12-12")));
157         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
158                 + "<get-schema xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
159                 + "<format>yang</format>\n"
160                 + "<identifier>module</identifier>\n"
161                 + "<version>2012-12-12</version>\n"
162                 + "</get-schema>\n"
163                 + "</rpc>");
164     }
165
166     @Test
167     public void testGetSchemaResponse() throws Exception {
168         final NetconfMessageTransformer transformer = getTransformer(getSchema(true));
169         final NetconfMessage response = new NetconfMessage(XmlUtil.readXmlToDocument(
170                 "<rpc-reply message-id=\"101\"\n"
171                         + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
172                         + "<data\n"
173                         + "xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
174                         + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
175                         + "Random YANG SCHEMA\n"
176                         + "</xs:schema>\n"
177                         + "</data>\n"
178                         + "</rpc-reply>"
179         ));
180         final DOMRpcResult compositeNodeRpcResult = transformer.toRpcResult(response, toPath(GET_SCHEMA_QNAME));
181         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
182         assertNotNull(compositeNodeRpcResult.getResult());
183         final DOMSource schemaContent =
184             ((AnyXmlNode) ((ContainerNode) compositeNodeRpcResult.getResult()).getValue().iterator().next()).getValue();
185         assertThat(schemaContent.getNode().getTextContent(),
186                 CoreMatchers.containsString("Random YANG SCHEMA"));
187     }
188
189     @Test
190     public void testGetConfigResponse() throws Exception {
191         final NetconfMessage response = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc-reply message-id=\"101\"\n"
192                 + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
193                 + "<data>\n"
194                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
195                 + "<schemas>\n"
196                 + "<schema>\n"
197                 + "<identifier>module</identifier>\n"
198                 + "<version>2012-12-12</version>\n"
199                 + "<format xmlns:x=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">x:yang</format>\n"
200                 + "</schema>\n"
201                 + "</schemas>\n"
202                 + "</netconf-state>\n"
203                 + "</data>\n"
204                 + "</rpc-reply>"));
205
206         final NetconfMessageTransformer transformer = getTransformer(getSchema(true));
207         final DOMRpcResult compositeNodeRpcResult =
208                 transformer.toRpcResult(response, toPath(NETCONF_GET_CONFIG_QNAME));
209         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
210         assertNotNull(compositeNodeRpcResult.getResult());
211
212         final List<DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?>> values = Lists.newArrayList(
213                 NetconfRemoteSchemaYangSourceProvider
214                         .createGetSchemaRequest("module", Optional.of("2012-12-12")).getValue());
215
216         final Map<QName, Object> keys = Maps.newHashMap();
217         for (final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> value : values) {
218             keys.put(value.getNodeType(), value.getValue());
219         }
220
221         final YangInstanceIdentifier.NodeIdentifierWithPredicates identifierWithPredicates =
222                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(Schema.QNAME, keys);
223         final MapEntryNode schemaNode =
224                 Builders.mapEntryBuilder().withNodeIdentifier(identifierWithPredicates).withValue(values).build();
225
226         final ContainerNode data = (ContainerNode) ((ContainerNode) compositeNodeRpcResult
227                 .getResult()).getChild(toId(NETCONF_DATA_QNAME)).get();
228         final ContainerNode state = (ContainerNode) data.getChild(toId(NetconfState.QNAME)).get();
229         final ContainerNode schemas = (ContainerNode) state.getChild(toId(Schemas.QNAME)).get();
230         final MapNode schemaParent = (MapNode) schemas.getChild(toId(Schema.QNAME)).get();
231         assertEquals(1, Iterables.size(schemaParent.getValue()));
232
233         assertEquals(schemaNode, schemaParent.getValue().iterator().next());
234     }
235
236     @Test
237     public void testGetConfigLeafRequest() throws Exception {
238         final DataContainerChild<?, ?> filter = toFilterStructure(
239                 YangInstanceIdentifier.create(toId(NetconfState.QNAME), toId(Schemas.QNAME), toId(Schema.QNAME),
240                     new YangInstanceIdentifier.NodeIdentifierWithPredicates(Schema.QNAME, ImmutableMap.of()),
241                     toId(QName.create(Schemas.QNAME, "version"))), schema);
242
243         final DataContainerChild<?, ?> source = NetconfBaseOps.getSourceNode(NETCONF_RUNNING_QNAME);
244
245         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(NETCONF_GET_CONFIG_QNAME),
246                 NetconfMessageTransformUtil.wrap(NETCONF_GET_CONFIG_QNAME, source, filter));
247
248         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
249                 + "<get-config xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
250                 + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
251                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
252                 + "<schemas>\n"
253                 + "<schema>\n"
254                 + "<version/>\n"
255                 + "</schema>\n"
256                 + "</schemas>\n"
257                 + "</netconf-state>\n"
258                 + "</filter>\n"
259                 + "<source>\n"
260                 + "<running/>\n"
261                 + "</source>\n"
262                 + "</get-config>\n"
263                 + "</rpc>");
264     }
265
266     @Test
267     public void testGetConfigRequest() throws Exception {
268         final DataContainerChild<?, ?> filter = toFilterStructure(
269                 YangInstanceIdentifier.create(toId(NetconfState.QNAME), toId(Schemas.QNAME)), schema);
270
271         final DataContainerChild<?, ?> source = NetconfBaseOps.getSourceNode(NETCONF_RUNNING_QNAME);
272
273         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(NETCONF_GET_CONFIG_QNAME),
274                 NetconfMessageTransformUtil.wrap(NETCONF_GET_CONFIG_QNAME, source, filter));
275
276         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
277                 + "<get-config xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
278                 + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
279                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
280                 + "<schemas/>\n"
281                 + "</netconf-state>"
282                 + "</filter>\n"
283                 + "<source>\n"
284                 + "<running/>\n"
285                 + "</source>\n"
286                 + "</get-config>"
287                 + "</rpc>");
288     }
289
290     @Test
291     public void testEditConfigRequest() throws Exception {
292         final List<DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?>> values = Lists.newArrayList(
293                 NetconfRemoteSchemaYangSourceProvider
294                         .createGetSchemaRequest("module", Optional.of("2012-12-12")).getValue());
295
296         final Map<QName, Object> keys = Maps.newHashMap();
297         for (final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> value : values) {
298             keys.put(value.getNodeType(), value.getValue());
299         }
300
301         final YangInstanceIdentifier.NodeIdentifierWithPredicates identifierWithPredicates =
302                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(Schema.QNAME, keys);
303         final MapEntryNode schemaNode =
304                 Builders.mapEntryBuilder().withNodeIdentifier(identifierWithPredicates).withValue(values).build();
305
306         final YangInstanceIdentifier id = YangInstanceIdentifier.builder()
307                 .node(NetconfState.QNAME).node(Schemas.QNAME).node(Schema.QNAME)
308                 .nodeWithKey(Schema.QNAME, keys).build();
309         final DataContainerChild<?, ?> editConfigStructure =
310                 createEditConfigStructure(BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS.getSchemaContext(), id,
311                         Optional.absent(), Optional.fromNullable(schemaNode));
312
313         final DataContainerChild<?, ?> target = NetconfBaseOps.getTargetNode(NETCONF_CANDIDATE_QNAME);
314
315         final ContainerNode wrap =
316                 NetconfMessageTransformUtil.wrap(NETCONF_EDIT_CONFIG_QNAME, editConfigStructure, target);
317         final NetconfMessage netconfMessage =
318                 netconfMessageTransformer.toRpcRequest(toPath(NETCONF_EDIT_CONFIG_QNAME), wrap);
319
320         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
321                 + "<edit-config>\n"
322                 + "<target>\n"
323                 + "<candidate/>\n"
324                 + "</target>\n"
325                 + "<config>\n"
326                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
327                 + "<schemas>\n"
328                 + "<schema>\n"
329                 + "<identifier>module</identifier>\n"
330                 + "<version>2012-12-12</version>\n"
331                 + "<format>yang</format>\n"
332                 + "</schema>\n"
333                 + "</schemas>\n"
334                 + "</netconf-state>\n"
335                 + "</config>\n"
336                 + "</edit-config>\n"
337                 + "</rpc>");
338     }
339
340     private static void assertSimilarXml(final NetconfMessage netconfMessage, final String xmlContent)
341             throws SAXException, IOException {
342         final Diff diff = XMLUnit.compareXML(netconfMessage.getDocument(), XmlUtil.readXmlToDocument(xmlContent));
343         diff.overrideElementQualifier(new ElementNameAndAttributeQualifier());
344         assertTrue(diff.toString(), diff.similar());
345     }
346
347     @Test
348     public void testGetRequest() throws Exception {
349
350         final QName capability = QName.create(Capabilities.QNAME, "capability");
351         final DataContainerChild<?, ?> filter = toFilterStructure(
352                 YangInstanceIdentifier.create(toId(NetconfState.QNAME), toId(Capabilities.QNAME), toId(capability),
353                     new YangInstanceIdentifier.NodeWithValue<>(capability, "a:b:c")), schema);
354
355         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(NETCONF_GET_QNAME),
356                 NetconfMessageTransformUtil.wrap(NETCONF_GET_QNAME, filter));
357
358         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
359                 + "<get xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
360                 + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
361                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
362                 + "<capabilities>\n"
363                 + "<capability>a:b:c</capability>\n"
364                 + "</capabilities>\n"
365                 + "</netconf-state>"
366                 + "</filter>\n"
367                 + "</get>"
368                 + "</rpc>");
369     }
370
371     private static NetconfMessageTransformer getTransformer(final SchemaContext schema) {
372         return new NetconfMessageTransformer(schema, true);
373     }
374
375     @Test
376     public void testCommitResponse() throws Exception {
377         final NetconfMessage response = new NetconfMessage(XmlUtil.readXmlToDocument(
378                 "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>"
379         ));
380         final DOMRpcResult compositeNodeRpcResult =
381                 netconfMessageTransformer.toRpcResult(response, toPath(NETCONF_COMMIT_QNAME));
382         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
383         assertNull(compositeNodeRpcResult.getResult());
384     }
385
386     public SchemaContext getSchema(final boolean addBase) {
387         final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
388         if (addBase) {
389             moduleInfoBackedContext.addModuleInfos(Collections.singleton($YangModuleInfoImpl.getInstance()));
390         }
391         moduleInfoBackedContext
392                 .addModuleInfos(Collections.singleton(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
393                         .netconf.monitoring.rev101004.$YangModuleInfoImpl.getInstance()));
394         return moduleInfoBackedContext.tryToCreateSchemaContext().get();
395     }
396
397     @Test
398     public void getActionsTest() {
399         QName reset = QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "reset");
400         QName start = QName.create(reset, "start");
401         QName open = QName.create(start, "open");
402         Set<QName> qnames = new HashSet<>(Arrays.asList(reset, start, open));
403         Set<ActionDefinition> actions = actionNetconfMessageTransformer.getActions();
404         assertTrue(!actions.isEmpty());
405         for (ActionDefinition actionDefinition : actions) {
406             QName qname = actionDefinition.getQName();
407             assertTrue(qnames.contains(qname));
408             qnames.remove(qname);
409         }
410     }
411
412     @Test
413     public void toActionRequestListTopLevelTest() {
414         QName qname = QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "server");
415         QName nameQname = QName.create(qname, "name");
416         QName actionResetQName = QName.create(qname, "reset");
417
418         Set<PathArgument> nodeIdentifiers =
419                 Collections.singleton(new NodeIdentifierWithPredicates(qname, nameQname, "test"));
420         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
421
422         ContainerNode data = initInputAction(QName.create(qname, "reset-at"), "now");
423
424         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
425                 SchemaPath.create(true, actionResetQName), domDataTreeIdentifier, data);
426
427         Node childAction = checkBasePartOfActionRequest(actionRequest);
428
429         Node childServer = childAction.getFirstChild();
430         checkNode(childServer, "server", "server", qname.getNamespace().toString());
431
432         Node childName = childServer.getFirstChild();
433         checkNode(childName, "name", "name", qname.getNamespace().toString());
434
435         Node childTest = childName.getFirstChild();
436         assertEquals(childTest.getNodeValue(), "test");
437
438         checkAction(actionResetQName, childName.getNextSibling(), "reset-at", "reset-at", "now");
439     }
440
441     @Test
442     public void toActionRequestContainerTopLevelTest() {
443         QName qname = QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "device");
444         QName actionStartQName = QName.create(qname, "start");
445
446         Set<PathArgument> nodeIdentifiers = Collections.singleton(NodeIdentifier.create(qname));
447         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
448
449         NormalizedNode<?, ?> payload = initInputAction(QName.create(qname, "start-at"), "now");
450         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
451                 SchemaPath.create(true, actionStartQName), domDataTreeIdentifier, payload);
452
453         Node childAction = checkBasePartOfActionRequest(actionRequest);
454
455         Node childDevice = childAction.getFirstChild();
456         checkNode(childDevice, "device", "device", qname.getNamespace().toString());
457
458         checkAction(actionStartQName, childDevice.getFirstChild(), "start-at", "start-at", "now");
459     }
460
461     @Test
462     public void toActionRequestContainerInContainerTest() {
463         QName boxOutQName = QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "box-out");
464         QName boxInQName = QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "box-in");
465         QName actionOpenQName = QName.create(boxOutQName, "open");
466
467         Set<PathArgument> nodeIdentifiers = new HashSet<>();
468         nodeIdentifiers.add(NodeIdentifier.create(boxOutQName));
469         nodeIdentifiers.add(NodeIdentifier.create(boxInQName));
470
471         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
472
473         NormalizedNode<?, ?> payload = initInputAction(QName.create(boxOutQName, "start-at"), "now");
474         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
475                 SchemaPath.create(true, actionOpenQName), domDataTreeIdentifier, payload);
476
477         Node childAction = checkBasePartOfActionRequest(actionRequest);
478
479         Node childBoxOut = childAction.getFirstChild();
480         checkNode(childBoxOut, "box-out", "box-out", boxOutQName.getNamespace().toString());
481
482         Node childBoxIn = childBoxOut.getFirstChild();
483         checkNode(childBoxIn, "box-in", "box-in", boxOutQName.getNamespace().toString());
484
485         Node action = childBoxIn.getFirstChild();
486         checkNode(action, null, actionOpenQName.getLocalName(), null);
487     }
488
489     @SuppressWarnings({ "rawtypes", "unchecked" })
490     @Test
491     public void toActionResultTest() throws Exception {
492         QName qname = QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "reset");
493
494         NetconfMessage message = new NetconfMessage(XmlUtil.readXmlToDocument(
495                 "<rpc-reply message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
496                 + "<reset-finished-at xmlns=\"urn:example:server-farm\">"
497                 + "now"
498                 + "</reset-finished-at>"
499                 + "</rpc-reply>"));
500         DOMActionResult actionResult = actionNetconfMessageTransformer.toActionResult(
501                 SchemaPath.create(true, qname), message);
502         assertNotNull(actionResult);
503         ContainerNode containerNode = actionResult.getOutput().get();
504         assertNotNull(containerNode);
505         LeafNode<String> leaf = (LeafNode) containerNode.getValue().iterator().next();
506         assertEquals("now", leaf.getValue());
507     }
508
509     private static void checkAction(final QName actionQname, final Node action , final String inputLocalName,
510             final String inputNodeName, final String inputValue) {
511         checkNode(action, null, actionQname.getLocalName(), null);
512
513         Node childResetAt = action.getFirstChild();
514         checkNode(childResetAt, inputLocalName, inputNodeName, actionQname.getNamespace().toString());
515
516         Node firstChild = childResetAt.getFirstChild();
517         assertEquals(firstChild.getNodeValue(), inputValue);
518     }
519
520     private static Node checkBasePartOfActionRequest(final NetconfMessage actionRequest) {
521         Node baseRpc = actionRequest.getDocument().getFirstChild();
522         checkNode(baseRpc, "rpc", "rpc", NetconfMessageTransformUtil.NETCONF_QNAME.getNamespace().toString());
523         assertTrue(baseRpc.getLocalName().equals("rpc"));
524         assertTrue(baseRpc.getNodeName().equals("rpc"));
525
526         Node messageId = baseRpc.getAttributes().getNamedItem("message-id");
527         assertNotNull(messageId);
528         assertTrue(messageId.getNodeValue().contains("m-"));
529
530         Node childAction = baseRpc.getFirstChild();
531         checkNode(childAction, "action", "action", NetconfMessageTransformUtil.NETCONF_ACTION_NAMESPACE.toString());
532         return childAction;
533     }
534
535     private static DOMDataTreeIdentifier prepareDataTreeId(final Set<PathArgument> nodeIdentifiers) {
536         YangInstanceIdentifier yangInstanceIdentifier =
537                 YangInstanceIdentifier.builder().append(nodeIdentifiers).build();
538         DOMDataTreeIdentifier domDataTreeIdentifier =
539                 new DOMDataTreeIdentifier(org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION,
540                         yangInstanceIdentifier);
541         return domDataTreeIdentifier;
542     }
543
544     private static ContainerNode initInputAction(final QName qname, final String value) {
545         ImmutableLeafNodeBuilder<String> immutableLeafNodeBuilder = new ImmutableLeafNodeBuilder<>();
546         DataContainerChild<NodeIdentifier, String> build = immutableLeafNodeBuilder.withNodeIdentifier(
547                 NodeIdentifier.create(qname)).withValue(value).build();
548         ContainerNode data = ImmutableContainerNodeBuilder.create().withNodeIdentifier(NodeIdentifier.create(
549                 QName.create(qname, "input"))).withChild(build).build();
550         return data;
551     }
552
553     private static void checkNode(final Node childServer, final String expectedLocalName, final String expectedNodeName,
554             final String expectedNamespace) {
555         assertNotNull(childServer);
556         assertEquals(childServer.getLocalName(), expectedLocalName);
557         assertEquals(childServer.getNodeName(), expectedNodeName);
558         assertEquals(childServer.getNamespaceURI(), expectedNamespace);
559     }
560
561     private static SchemaContext getActionSchema() {
562         return YangParserTestUtils.parseYangResource("/schemas/example-server-farm.yang");
563     }
564
565     private static NetconfMessageTransformer getActionMessageTransformer() {
566         return new NetconfMessageTransformer(getActionSchema(), true);
567     }
568 }