Do not attempt to parse empty RPC/action reply
[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_DISCARD_CHANGES_QNAME;
21 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_EDIT_CONFIG_QNAME;
22 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME;
23 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_QNAME;
24 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_LOCK_QNAME;
25 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_RUNNING_QNAME;
26 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.createEditConfigStructure;
27 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toFilterStructure;
28 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toId;
29 import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath;
30 import static org.opendaylight.netconf.util.NetconfUtil.NETCONF_DATA_QNAME;
31
32 import com.google.common.collect.Iterables;
33 import com.google.common.collect.Lists;
34 import java.io.IOException;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.HashSet;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Optional;
42 import java.util.Set;
43 import javax.xml.transform.dom.DOMSource;
44 import org.custommonkey.xmlunit.Diff;
45 import org.custommonkey.xmlunit.ElementNameAndAttributeQualifier;
46 import org.custommonkey.xmlunit.XMLUnit;
47 import org.hamcrest.CoreMatchers;
48 import org.junit.AfterClass;
49 import org.junit.Before;
50 import org.junit.BeforeClass;
51 import org.junit.Test;
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.mdsal.dom.api.DOMRpcResult;
56 import org.opendaylight.netconf.api.NetconfMessage;
57 import org.opendaylight.netconf.api.xml.XmlUtil;
58 import org.opendaylight.netconf.sal.connect.netconf.schema.NetconfRemoteSchemaYangSourceProvider;
59 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
60 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
61 import org.opendaylight.netconf.util.NetconfUtil;
62 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.$YangModuleInfoImpl;
63 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
64 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Capabilities;
65 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
66 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
67 import org.opendaylight.yangtools.rcf8528.data.util.EmptyMountPointContext;
68 import org.opendaylight.yangtools.yang.common.QName;
69 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
70 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
71 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
72 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
73 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
74 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
75 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
76 import org.opendaylight.yangtools.yang.data.api.schema.DOMSourceAnyxmlNode;
77 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
78 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
79 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
80 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
81 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
82 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
83 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
84 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
85 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
86 import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
87 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
88 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
89 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
90 import org.w3c.dom.Node;
91 import org.xml.sax.SAXException;
92
93 public class NetconfMessageTransformerTest {
94
95     private static final String REVISION_EXAMPLE_SERVER_FARM = "2018-08-07";
96     private static final String URN_EXAMPLE_SERVER_FARM = "urn:example:server-farm";
97
98     private static final String REVISION_EXAMPLE_SERVER_FARM_2 = "2019-05-20";
99     private static final String URN_EXAMPLE_SERVER_FARM_2 = "urn:example:server-farm-2";
100
101     private static final String URN_EXAMPLE_CONFLICT = "urn:example:conflict";
102
103     private static final String URN_EXAMPLE_AUGMENTED_ACTION = "urn:example:augmented-action";
104
105     private static final String URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS = "urn:example:rpcs-actions-outputs";
106
107     private static final QName SERVER_QNAME =
108             QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "server");
109     private static final QName RESET_QNAME = QName.create(SERVER_QNAME, "reset");
110     private static final SchemaPath RESET_SERVER_PATH = SchemaPath.create(true, SERVER_QNAME, RESET_QNAME);
111     private static final QName APPLICATIONS_QNAME = QName.create(URN_EXAMPLE_SERVER_FARM_2,
112             REVISION_EXAMPLE_SERVER_FARM_2, "applications");
113     private static final QName APPLICATION_QNAME = QName.create(APPLICATIONS_QNAME, "application");
114     private static final QName KILL_QNAME = QName.create(APPLICATION_QNAME, "kill");
115     private static final SchemaPath KILL_SERVER_APP_PATH =
116             SchemaPath.create(true, SERVER_QNAME, APPLICATIONS_QNAME, APPLICATION_QNAME, KILL_QNAME);
117
118     private static final QName DEVICE_QNAME =
119             QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "device");
120     private static final QName START_QNAME = QName.create(DEVICE_QNAME, "start");
121     private static final SchemaPath START_DEVICE_PATH = SchemaPath.create(true, DEVICE_QNAME, START_QNAME);
122     private static final QName INTERFACE_QNAME = QName.create(DEVICE_QNAME, "interface");
123     private static final QName ENABLE_QNAME = QName.create(INTERFACE_QNAME, "enable");
124     private static final SchemaPath ENABLE_INTERFACE_PATH =
125             SchemaPath.create(true, DEVICE_QNAME, INTERFACE_QNAME, ENABLE_QNAME);
126
127     private static final QName DISABLE_QNAME = QName.create(URN_EXAMPLE_AUGMENTED_ACTION, "disable");
128     private static final SchemaPath DISABLE_INTERFACE_PATH =
129             SchemaPath.create(true, DEVICE_QNAME, INTERFACE_QNAME, DISABLE_QNAME);
130
131     private static final QName CHECK_WITH_OUTPUT_QNAME =
132             QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "check-with-output");
133     private static final SchemaPath CHECK_WITH_OUTPUT_INTERFACE_PATH =
134             SchemaPath.create(true, DEVICE_QNAME, INTERFACE_QNAME, CHECK_WITH_OUTPUT_QNAME);
135     private static final QName CHECK_WITHOUT_OUTPUT_QNAME =
136             QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "check-without-output");
137     private static final SchemaPath CHECK_WITHOUT_OUTPUT_INTERFACE_PATH =
138             SchemaPath.create(true, DEVICE_QNAME, INTERFACE_QNAME, CHECK_WITHOUT_OUTPUT_QNAME);
139     private static final QName RPC_WITH_OUTPUT_QNAME =
140             QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "rpc-with-output");
141     private static final QName RPC_WITHOUT_OUTPUT_QNAME =
142             QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "rpc-without-output");
143
144     private static final QName BOX_OUT_QNAME =
145             QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "box-out");
146     private static final QName BOX_IN_QNAME = QName.create(BOX_OUT_QNAME, "box-in");
147     private static final QName OPEN_QNAME = QName.create(BOX_IN_QNAME, "open");
148     private static final SchemaPath OPEN_BOXES_PATH =
149             SchemaPath.create(true, BOX_OUT_QNAME, BOX_IN_QNAME, OPEN_QNAME);
150
151     private static final QName FOO_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "foo");
152     private static final QName BAR_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "bar");
153     private static final QName XYZZY_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "xyzzy");
154     private static final SchemaPath XYZZY_FOO_PATH = SchemaPath.create(true, FOO_QNAME, XYZZY_QNAME);
155     private static final SchemaPath XYZZY_BAR_PATH = SchemaPath.create(true, BAR_QNAME, XYZZY_QNAME);
156
157     private static final QName CONFLICT_CHOICE_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "conflict-choice");
158     private static final QName CHOICE_CONT_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "choice-cont");
159     private static final QName CHOICE_ACTION_QNAME = QName.create(URN_EXAMPLE_CONFLICT, "choice-action");
160     private static final SchemaPath CHOICE_ACTION_PATH =
161             SchemaPath.create(true, CONFLICT_CHOICE_QNAME, CHOICE_CONT_QNAME, CHOICE_CONT_QNAME, CHOICE_ACTION_QNAME);
162
163     private static SchemaContext PARTIAL_SCHEMA;
164     private static SchemaContext SCHEMA;
165     private static SchemaContext ACTION_SCHEMA;
166
167     private NetconfMessageTransformer actionNetconfMessageTransformer;
168     private NetconfMessageTransformer netconfMessageTransformer;
169
170     @BeforeClass
171     public static void beforeClass() {
172         final ModuleInfoBackedContext context = ModuleInfoBackedContext.create();
173         context.addModuleInfos(Collections.singleton(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
174             .netconf.monitoring.rev101004.$YangModuleInfoImpl.getInstance()));
175         PARTIAL_SCHEMA = context.tryToCreateSchemaContext().get();
176
177         context.addModuleInfos(Collections.singleton($YangModuleInfoImpl.getInstance()));
178         SCHEMA = context.tryToCreateSchemaContext().get();
179
180         ACTION_SCHEMA = YangParserTestUtils.parseYangResources(NetconfMessageTransformerTest.class,
181             "/schemas/example-server-farm.yang","/schemas/example-server-farm-2.yang",
182             "/schemas/conflicting-actions.yang", "/schemas/augmented-action.yang",
183             "/schemas/rpcs-actions-outputs.yang");
184     }
185
186     @AfterClass
187     public static void afterClass() {
188         PARTIAL_SCHEMA = null;
189         SCHEMA = null;
190         ACTION_SCHEMA = null;
191     }
192
193     @Before
194     public void setUp() throws Exception {
195         XMLUnit.setIgnoreWhitespace(true);
196         XMLUnit.setIgnoreAttributeOrder(true);
197         XMLUnit.setIgnoreComments(true);
198
199         netconfMessageTransformer = getTransformer(SCHEMA);
200         actionNetconfMessageTransformer = new NetconfMessageTransformer(new EmptyMountPointContext(ACTION_SCHEMA),
201             true);
202     }
203
204     @Test
205     public void testLockRequestBaseSchemaNotPresent() throws Exception {
206         final NetconfMessageTransformer transformer = getTransformer(PARTIAL_SCHEMA);
207         final NetconfMessage netconfMessage = transformer.toRpcRequest(toPath(NETCONF_LOCK_QNAME),
208                 NetconfBaseOps.getLockContent(NETCONF_CANDIDATE_QNAME));
209
210         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<lock"));
211         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<rpc"));
212     }
213
214     @Test
215     public void testCreateSubscriberNotificationSchemaNotPresent() throws Exception {
216         final NetconfMessageTransformer transformer = new NetconfMessageTransformer(new EmptyMountPointContext(SCHEMA),
217             true, BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS);
218         NetconfMessage netconfMessage = transformer.toRpcRequest(
219                 toPath(CREATE_SUBSCRIPTION_RPC_QNAME),
220                 CREATE_SUBSCRIPTION_RPC_CONTENT
221         );
222         String documentString = XmlUtil.toString(netconfMessage.getDocument());
223         assertThat(documentString, CoreMatchers.containsString("<create-subscription"));
224         assertThat(documentString, CoreMatchers.containsString("<rpc"));
225     }
226
227     @Test
228     public void tesLockSchemaRequest() throws Exception {
229         final NetconfMessageTransformer transformer = getTransformer(PARTIAL_SCHEMA);
230         final String result = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>";
231
232         transformer.toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)), toPath(NETCONF_LOCK_QNAME));
233     }
234
235     @Test
236     public void testRpcEmptyBodyWithOutputDefinedSchemaResult() throws Exception {
237         final String result = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>";
238
239         DOMRpcResult domRpcResult = actionNetconfMessageTransformer
240                 .toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)),
241                         toPath(RPC_WITH_OUTPUT_QNAME));
242         assertNotNull(domRpcResult);
243     }
244
245     @Test
246     public void testRpcEmptyBodyWithoutOutputDefinedSchemaResult() throws Exception {
247         final String result = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>";
248
249         DOMRpcResult domRpcResult = actionNetconfMessageTransformer
250                 .toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)),
251                         toPath(RPC_WITHOUT_OUTPUT_QNAME));
252         assertNotNull(domRpcResult);
253     }
254
255     @Test
256     public void testDiscardChangesRequest() throws Exception {
257         final NetconfMessage netconfMessage =
258                 netconfMessageTransformer.toRpcRequest(toPath(NETCONF_DISCARD_CHANGES_QNAME), null);
259         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<discard"));
260         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("<rpc"));
261         assertThat(XmlUtil.toString(netconfMessage.getDocument()), CoreMatchers.containsString("message-id"));
262     }
263
264     @Test
265     public void testGetSchemaRequest() throws Exception {
266         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(GET_SCHEMA_QNAME),
267                 NetconfRemoteSchemaYangSourceProvider.createGetSchemaRequest("module", Optional.of("2012-12-12")));
268         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
269                 + "<get-schema xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
270                 + "<format>yang</format>\n"
271                 + "<identifier>module</identifier>\n"
272                 + "<version>2012-12-12</version>\n"
273                 + "</get-schema>\n"
274                 + "</rpc>");
275     }
276
277     @Test
278     public void testGetSchemaResponse() throws Exception {
279         final NetconfMessageTransformer transformer = getTransformer(SCHEMA);
280         final NetconfMessage response = new NetconfMessage(XmlUtil.readXmlToDocument(
281                 "<rpc-reply message-id=\"101\"\n"
282                         + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
283                         + "<data\n"
284                         + "xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
285                         + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
286                         + "Random YANG SCHEMA\n"
287                         + "</xs:schema>\n"
288                         + "</data>\n"
289                         + "</rpc-reply>"
290         ));
291         final DOMRpcResult compositeNodeRpcResult = transformer.toRpcResult(response, toPath(GET_SCHEMA_QNAME));
292         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
293         assertNotNull(compositeNodeRpcResult.getResult());
294         final DOMSource schemaContent = ((DOMSourceAnyxmlNode) ((ContainerNode) compositeNodeRpcResult.getResult())
295                 .getValue().iterator().next()).getValue();
296         assertThat(schemaContent.getNode().getTextContent(),
297                 CoreMatchers.containsString("Random YANG SCHEMA"));
298     }
299
300     @Test
301     public void testGetConfigResponse() throws Exception {
302         final NetconfMessage response = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc-reply message-id=\"101\"\n"
303                 + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
304                 + "<data>\n"
305                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
306                 + "<schemas>\n"
307                 + "<schema>\n"
308                 + "<identifier>module</identifier>\n"
309                 + "<version>2012-12-12</version>\n"
310                 + "<format xmlns:x=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">x:yang</format>\n"
311                 + "</schema>\n"
312                 + "</schemas>\n"
313                 + "</netconf-state>\n"
314                 + "</data>\n"
315                 + "</rpc-reply>"));
316
317         final NetconfMessageTransformer transformer = getTransformer(SCHEMA);
318         final DOMRpcResult compositeNodeRpcResult =
319                 transformer.toRpcResult(response, toPath(NETCONF_GET_CONFIG_QNAME));
320         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
321         assertNotNull(compositeNodeRpcResult.getResult());
322
323         final List<DataContainerChild<?, ?>> values = Lists.newArrayList(
324                 NetconfRemoteSchemaYangSourceProvider
325                         .createGetSchemaRequest("module", Optional.of("2012-12-12")).getValue());
326
327         final Map<QName, Object> keys = new HashMap<>();
328         for (final DataContainerChild<?, ?> value : values) {
329             keys.put(value.getNodeType(), value.getValue());
330         }
331
332         final NodeIdentifierWithPredicates identifierWithPredicates =
333                 NodeIdentifierWithPredicates.of(Schema.QNAME, keys);
334         final MapEntryNode schemaNode =
335                 Builders.mapEntryBuilder().withNodeIdentifier(identifierWithPredicates).withValue(values).build();
336
337         final DOMSourceAnyxmlNode data = (DOMSourceAnyxmlNode) ((ContainerNode) compositeNodeRpcResult.getResult())
338                 .getChild(toId(NETCONF_DATA_QNAME)).get();
339
340         NormalizedNodeResult nodeResult =
341                 NetconfUtil.transformDOMSourceToNormalizedNode(SCHEMA, data.getValue());
342         ContainerNode result = (ContainerNode) nodeResult.getResult();
343         final ContainerNode state = (ContainerNode) result.getChild(toId(NetconfState.QNAME)).get();
344         final ContainerNode schemas = (ContainerNode) state.getChild(toId(Schemas.QNAME)).get();
345         final MapNode schemaParent = (MapNode) schemas.getChild(toId(Schema.QNAME)).get();
346         assertEquals(1, Iterables.size(schemaParent.getValue()));
347
348         assertEquals(schemaNode, schemaParent.getValue().iterator().next());
349     }
350
351     @Test
352     public void testGetConfigLeafRequest() throws Exception {
353         final DataContainerChild<?, ?> filter = toFilterStructure(
354                 YangInstanceIdentifier.create(toId(NetconfState.QNAME), toId(Schemas.QNAME), toId(Schema.QNAME),
355                     NodeIdentifierWithPredicates.of(Schema.QNAME),
356                     toId(QName.create(Schemas.QNAME, "version"))), SCHEMA);
357
358         final DataContainerChild<?, ?> source = NetconfBaseOps.getSourceNode(NETCONF_RUNNING_QNAME);
359
360         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(NETCONF_GET_CONFIG_QNAME),
361                 NetconfMessageTransformUtil.wrap(NETCONF_GET_CONFIG_QNAME, source, filter));
362
363         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
364                 + "<get-config xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
365                 + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
366                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
367                 + "<schemas>\n"
368                 + "<schema>\n"
369                 + "<version/>\n"
370                 + "</schema>\n"
371                 + "</schemas>\n"
372                 + "</netconf-state>\n"
373                 + "</filter>\n"
374                 + "<source>\n"
375                 + "<running/>\n"
376                 + "</source>\n"
377                 + "</get-config>\n"
378                 + "</rpc>");
379     }
380
381     @Test
382     public void testGetConfigRequest() throws Exception {
383         final DataContainerChild<?, ?> filter = toFilterStructure(
384                 YangInstanceIdentifier.create(toId(NetconfState.QNAME), toId(Schemas.QNAME)), SCHEMA);
385
386         final DataContainerChild<?, ?> source = NetconfBaseOps.getSourceNode(NETCONF_RUNNING_QNAME);
387
388         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(NETCONF_GET_CONFIG_QNAME),
389                 NetconfMessageTransformUtil.wrap(NETCONF_GET_CONFIG_QNAME, source, filter));
390
391         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
392                 + "<get-config xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
393                 + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
394                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
395                 + "<schemas/>\n"
396                 + "</netconf-state>"
397                 + "</filter>\n"
398                 + "<source>\n"
399                 + "<running/>\n"
400                 + "</source>\n"
401                 + "</get-config>"
402                 + "</rpc>");
403     }
404
405     @Test
406     public void testEditConfigRequest() throws Exception {
407         final List<DataContainerChild<?, ?>> values = Lists.newArrayList(
408                 NetconfRemoteSchemaYangSourceProvider
409                         .createGetSchemaRequest("module", Optional.of("2012-12-12")).getValue());
410
411         final Map<QName, Object> keys = new HashMap<>();
412         for (final DataContainerChild<?, ?> value : values) {
413             keys.put(value.getNodeType(), value.getValue());
414         }
415
416         final NodeIdentifierWithPredicates identifierWithPredicates =
417                 NodeIdentifierWithPredicates.of(Schema.QNAME, keys);
418         final MapEntryNode schemaNode =
419                 Builders.mapEntryBuilder().withNodeIdentifier(identifierWithPredicates).withValue(values).build();
420
421         final YangInstanceIdentifier id = YangInstanceIdentifier.builder()
422                 .node(NetconfState.QNAME).node(Schemas.QNAME).node(Schema.QNAME)
423                 .nodeWithKey(Schema.QNAME, keys).build();
424         final DataContainerChild<?, ?> editConfigStructure =
425                 createEditConfigStructure(BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS.getSchemaContext(), id,
426                     Optional.empty(), Optional.ofNullable(schemaNode));
427
428         final DataContainerChild<?, ?> target = NetconfBaseOps.getTargetNode(NETCONF_CANDIDATE_QNAME);
429
430         final ContainerNode wrap =
431                 NetconfMessageTransformUtil.wrap(NETCONF_EDIT_CONFIG_QNAME, editConfigStructure, target);
432         final NetconfMessage netconfMessage =
433                 netconfMessageTransformer.toRpcRequest(toPath(NETCONF_EDIT_CONFIG_QNAME), wrap);
434
435         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
436                 + "<edit-config>\n"
437                 + "<target>\n"
438                 + "<candidate/>\n"
439                 + "</target>\n"
440                 + "<config>\n"
441                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
442                 + "<schemas>\n"
443                 + "<schema>\n"
444                 + "<identifier>module</identifier>\n"
445                 + "<version>2012-12-12</version>\n"
446                 + "<format>yang</format>\n"
447                 + "</schema>\n"
448                 + "</schemas>\n"
449                 + "</netconf-state>\n"
450                 + "</config>\n"
451                 + "</edit-config>\n"
452                 + "</rpc>");
453     }
454
455     private static void assertSimilarXml(final NetconfMessage netconfMessage, final String xmlContent)
456             throws SAXException, IOException {
457         final Diff diff = XMLUnit.compareXML(netconfMessage.getDocument(), XmlUtil.readXmlToDocument(xmlContent));
458         diff.overrideElementQualifier(new ElementNameAndAttributeQualifier());
459         assertTrue(diff.toString(), diff.similar());
460     }
461
462     @Test
463     public void testGetRequest() throws Exception {
464
465         final QName capability = QName.create(Capabilities.QNAME, "capability");
466         final DataContainerChild<?, ?> filter = toFilterStructure(
467                 YangInstanceIdentifier.create(toId(NetconfState.QNAME), toId(Capabilities.QNAME), toId(capability),
468                     new NodeWithValue<>(capability, "a:b:c")), SCHEMA);
469
470         final NetconfMessage netconfMessage = netconfMessageTransformer.toRpcRequest(toPath(NETCONF_GET_QNAME),
471                 NetconfMessageTransformUtil.wrap(NETCONF_GET_QNAME, filter));
472
473         assertSimilarXml(netconfMessage, "<rpc message-id=\"m-0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
474                 + "<get xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
475                 + "<filter xmlns:ns0=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ns0:type=\"subtree\">\n"
476                 + "<netconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring\">\n"
477                 + "<capabilities>\n"
478                 + "<capability>a:b:c</capability>\n"
479                 + "</capabilities>\n"
480                 + "</netconf-state>"
481                 + "</filter>\n"
482                 + "</get>"
483                 + "</rpc>");
484     }
485
486     private static NetconfMessageTransformer getTransformer(final SchemaContext schema) {
487         return new NetconfMessageTransformer(new EmptyMountPointContext(schema), true);
488     }
489
490     @Test
491     public void testCommitResponse() throws Exception {
492         final NetconfMessage response = new NetconfMessage(XmlUtil.readXmlToDocument(
493                 "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>"
494         ));
495         final DOMRpcResult compositeNodeRpcResult =
496                 netconfMessageTransformer.toRpcResult(response, toPath(NETCONF_COMMIT_QNAME));
497         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
498         assertNull(compositeNodeRpcResult.getResult());
499     }
500
501     @Test
502     public void getActionsTest() {
503         Set<SchemaPath> schemaPaths = new HashSet<>();
504         schemaPaths.add(RESET_SERVER_PATH);
505         schemaPaths.add(START_DEVICE_PATH);
506         schemaPaths.add(ENABLE_INTERFACE_PATH);
507         schemaPaths.add(OPEN_BOXES_PATH);
508         schemaPaths.add(KILL_SERVER_APP_PATH);
509         schemaPaths.add(XYZZY_FOO_PATH);
510         schemaPaths.add(XYZZY_BAR_PATH);
511         schemaPaths.add(CHOICE_ACTION_PATH);
512         schemaPaths.add(DISABLE_INTERFACE_PATH);
513         schemaPaths.add(CHECK_WITH_OUTPUT_INTERFACE_PATH);
514         schemaPaths.add(CHECK_WITHOUT_OUTPUT_INTERFACE_PATH);
515
516         List<ActionDefinition> actions = NetconfMessageTransformer.getActions(ACTION_SCHEMA);
517         assertEquals(schemaPaths.size(), actions.size());
518         for (ActionDefinition actionDefinition : actions) {
519             SchemaPath path = actionDefinition.getPath();
520             assertTrue(schemaPaths.remove(path));
521         }
522     }
523
524     @Test
525     public void toActionRequestListTopLevelTest() {
526         QName nameQname = QName.create(SERVER_QNAME, "name");
527         List<PathArgument> nodeIdentifiers = new ArrayList<>();
528         nodeIdentifiers.add(new NodeIdentifier(SERVER_QNAME));
529         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(SERVER_QNAME, nameQname, "test"));
530         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
531
532         ContainerNode data = initInputAction(QName.create(SERVER_QNAME, "reset-at"), "now");
533
534         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
535                 RESET_SERVER_PATH, domDataTreeIdentifier, data);
536
537         Node childAction = checkBasePartOfActionRequest(actionRequest);
538
539         Node childServer = childAction.getFirstChild();
540         checkNode(childServer, "server", "server", URN_EXAMPLE_SERVER_FARM);
541
542         Node childName = childServer.getFirstChild();
543         checkNode(childName, "name", "name", URN_EXAMPLE_SERVER_FARM);
544
545         Node childTest = childName.getFirstChild();
546         assertEquals(childTest.getNodeValue(), "test");
547
548         checkAction(RESET_QNAME, childName.getNextSibling(), "reset-at", "reset-at", "now");
549     }
550
551     @Test
552     public void toActionRequestContainerTopLevelTest() {
553         List<PathArgument> nodeIdentifiers = Collections.singletonList(NodeIdentifier.create(DEVICE_QNAME));
554         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
555
556         NormalizedNode<?, ?> payload = initInputAction(QName.create(DEVICE_QNAME, "start-at"), "now");
557         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
558                 START_DEVICE_PATH, domDataTreeIdentifier, payload);
559
560         Node childAction = checkBasePartOfActionRequest(actionRequest);
561
562         Node childDevice = childAction.getFirstChild();
563         checkNode(childDevice, "device", "device", URN_EXAMPLE_SERVER_FARM);
564
565         checkAction(START_QNAME, childDevice.getFirstChild(), "start-at", "start-at", "now");
566     }
567
568     @Test
569     public void toActionRequestContainerInContainerTest() {
570         List<PathArgument> nodeIdentifiers = new ArrayList<>();
571         nodeIdentifiers.add(NodeIdentifier.create(BOX_OUT_QNAME));
572         nodeIdentifiers.add(NodeIdentifier.create(BOX_IN_QNAME));
573
574         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
575
576         NormalizedNode<?, ?> payload = initInputAction(QName.create(BOX_OUT_QNAME, "start-at"), "now");
577         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
578                 OPEN_BOXES_PATH, domDataTreeIdentifier, payload);
579
580         Node childAction = checkBasePartOfActionRequest(actionRequest);
581
582         Node childBoxOut = childAction.getFirstChild();
583         checkNode(childBoxOut, "box-out", "box-out", URN_EXAMPLE_SERVER_FARM);
584
585         Node childBoxIn = childBoxOut.getFirstChild();
586         checkNode(childBoxIn, "box-in", "box-in", URN_EXAMPLE_SERVER_FARM);
587
588         Node action = childBoxIn.getFirstChild();
589         checkNode(action, OPEN_QNAME.getLocalName(), OPEN_QNAME.getLocalName(), OPEN_QNAME.getNamespace().toString());
590     }
591
592     @Test
593     public void toActionRequestListInContainerTest() {
594         QName nameQname = QName.create(INTERFACE_QNAME, "name");
595
596         List<PathArgument> nodeIdentifiers = new ArrayList<>();
597         nodeIdentifiers.add(NodeIdentifier.create(DEVICE_QNAME));
598         nodeIdentifiers.add(NodeIdentifier.create(INTERFACE_QNAME));
599         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(INTERFACE_QNAME, nameQname, "test"));
600
601         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
602
603         NormalizedNode<?, ?> payload = initEmptyInputAction(INTERFACE_QNAME);
604         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
605                 ENABLE_INTERFACE_PATH, domDataTreeIdentifier, payload);
606
607         Node childAction = checkBasePartOfActionRequest(actionRequest);
608
609         Node childDevice = childAction.getFirstChild();
610         checkNode(childDevice, "device", "device", URN_EXAMPLE_SERVER_FARM);
611
612         Node childInterface = childDevice.getFirstChild();
613         checkNode(childInterface, "interface", "interface", URN_EXAMPLE_SERVER_FARM);
614
615         Node childName = childInterface.getFirstChild();
616         checkNode(childName, "name", "name", nameQname.getNamespace().toString());
617
618         Node childTest = childName.getFirstChild();
619         assertEquals(childTest.getNodeValue(), "test");
620
621         Node action = childInterface.getLastChild();
622         checkNode(action, ENABLE_QNAME.getLocalName(), ENABLE_QNAME.getLocalName(),
623                 ENABLE_QNAME.getNamespace().toString());
624     }
625
626     @Test
627     public void toActionRequestListInContainerAugmentedIntoListTest() {
628         QName serverNameQname = QName.create(SERVER_QNAME, "name");
629         QName applicationNameQname = QName.create(APPLICATION_QNAME, "name");
630
631         List<PathArgument> nodeIdentifiers = new ArrayList<>();
632         nodeIdentifiers.add(NodeIdentifier.create(SERVER_QNAME));
633         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(SERVER_QNAME, serverNameQname, "testServer"));
634         nodeIdentifiers.add(new AugmentationIdentifier(Collections.singleton(APPLICATIONS_QNAME)));
635         nodeIdentifiers.add(NodeIdentifier.create(APPLICATIONS_QNAME));
636         nodeIdentifiers.add(NodeIdentifier.create(APPLICATION_QNAME));
637         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(APPLICATION_QNAME,
638                 applicationNameQname, "testApplication"));
639
640         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
641
642         NormalizedNode<?, ?> payload = initEmptyInputAction(APPLICATION_QNAME);
643         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
644                 KILL_SERVER_APP_PATH, domDataTreeIdentifier, payload);
645
646         Node childAction = checkBasePartOfActionRequest(actionRequest);
647
648         Node childServer = childAction.getFirstChild();
649         checkNode(childServer, "server", "server", URN_EXAMPLE_SERVER_FARM);
650
651         Node childServerName = childServer.getFirstChild();
652         checkNode(childServerName, "name", "name", URN_EXAMPLE_SERVER_FARM);
653
654         Node childServerNameTest = childServerName.getFirstChild();
655         assertEquals(childServerNameTest.getNodeValue(), "testServer");
656
657         Node childApplications = childServer.getLastChild();
658         checkNode(childApplications, "applications", "applications", URN_EXAMPLE_SERVER_FARM_2);
659
660         Node childApplication = childApplications.getFirstChild();
661         checkNode(childApplication, "application", "application", URN_EXAMPLE_SERVER_FARM_2);
662
663         Node childApplicationName = childApplication.getFirstChild();
664         checkNode(childApplicationName, "name", "name", URN_EXAMPLE_SERVER_FARM_2);
665
666         Node childApplicationNameTest = childApplicationName.getFirstChild();
667         assertEquals(childApplicationNameTest.getNodeValue(), "testApplication");
668
669         Node childKillAction = childApplication.getLastChild();
670         checkNode(childApplication, "application", "application", URN_EXAMPLE_SERVER_FARM_2);
671         checkNode(childKillAction, KILL_QNAME.getLocalName(), KILL_QNAME.getLocalName(),
672                 KILL_QNAME.getNamespace().toString());
673     }
674
675     @Test
676     public void toActionRequestConflictingInListTest() {
677         QName barInputQname = QName.create(BAR_QNAME, "bar");
678         QName barIdQname = QName.create(BAR_QNAME, "bar-id");
679         Byte barInput = new Byte("1");
680
681         List<PathArgument> nodeIdentifiers = new ArrayList<>();
682         nodeIdentifiers.add(NodeIdentifier.create(BAR_QNAME));
683         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(BAR_QNAME, barIdQname, "test"));
684
685         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
686
687         ImmutableLeafNodeBuilder<Byte> immutableLeafNodeBuilder = new ImmutableLeafNodeBuilder<>();
688         DataContainerChild<NodeIdentifier, Byte> build = immutableLeafNodeBuilder.withNodeIdentifier(
689                 NodeIdentifier.create(barInputQname)).withValue(barInput).build();
690         NormalizedNode<?, ?> payload = ImmutableContainerNodeBuilder.create().withNodeIdentifier(NodeIdentifier.create(
691                 QName.create(barInputQname, "input"))).withChild(build).build();
692
693         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
694                 XYZZY_BAR_PATH, domDataTreeIdentifier, payload);
695
696         Node childAction = checkBasePartOfActionRequest(actionRequest);
697
698         Node childBar = childAction.getFirstChild();
699         checkNode(childBar, "bar", "bar", URN_EXAMPLE_CONFLICT);
700
701         Node childBarId = childBar.getFirstChild();
702         checkNode(childBarId, "bar-id", "bar-id", URN_EXAMPLE_CONFLICT);
703
704         Node childTest = childBarId.getFirstChild();
705         assertEquals(childTest.getNodeValue(), "test");
706
707         Node action = childBar.getLastChild();
708         checkNode(action, XYZZY_QNAME.getLocalName(), XYZZY_QNAME.getLocalName(),
709                 XYZZY_QNAME.getNamespace().toString());
710     }
711
712     @Test
713     public void toActionRequestConflictingInContainerTest() {
714         QName fooInputQname = QName.create(FOO_QNAME, "foo");
715
716         List<PathArgument> nodeIdentifiers = new ArrayList<>();
717         nodeIdentifiers.add(NodeIdentifier.create(FOO_QNAME));
718         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
719         NormalizedNode<?, ?> payload = initInputAction(fooInputQname, "test");
720
721         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
722                 XYZZY_FOO_PATH, domDataTreeIdentifier, payload);
723
724         Node childAction = checkBasePartOfActionRequest(actionRequest);
725
726         Node childBar = childAction.getFirstChild();
727         checkNode(childBar, "foo", "foo", URN_EXAMPLE_CONFLICT);
728
729         Node action = childBar.getLastChild();
730         checkNode(action, XYZZY_QNAME.getLocalName(), XYZZY_QNAME.getLocalName(),
731                 XYZZY_QNAME.getNamespace().toString());
732     }
733
734     @Test
735     public void toActionRequestChoiceTest() {
736         List<PathArgument> nodeIdentifiers = new ArrayList<>();
737         nodeIdentifiers.add(NodeIdentifier.create(CONFLICT_CHOICE_QNAME));
738         nodeIdentifiers.add(NodeIdentifier.create(CHOICE_CONT_QNAME));
739         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
740         NormalizedNode<?, ?> payload = initEmptyInputAction(CHOICE_ACTION_QNAME);
741
742         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
743                 CHOICE_ACTION_PATH, domDataTreeIdentifier, payload);
744
745         Node childAction = checkBasePartOfActionRequest(actionRequest);
746
747         Node childChoiceCont = childAction.getFirstChild();
748         checkNode(childChoiceCont, "choice-cont", "choice-cont", URN_EXAMPLE_CONFLICT);
749
750         Node action = childChoiceCont.getLastChild();
751         checkNode(action, CHOICE_ACTION_QNAME.getLocalName(), CHOICE_ACTION_QNAME.getLocalName(),
752                 CHOICE_ACTION_QNAME.getNamespace().toString());
753     }
754
755     @Test
756     public void toAugmentedActionRequestListInContainerTest() {
757         QName nameQname = QName.create(INTERFACE_QNAME, "name");
758
759         List<PathArgument> nodeIdentifiers = new ArrayList<>();
760         nodeIdentifiers.add(NodeIdentifier.create(DEVICE_QNAME));
761         nodeIdentifiers.add(NodeIdentifier.create(INTERFACE_QNAME));
762         nodeIdentifiers.add(NodeIdentifierWithPredicates.of(INTERFACE_QNAME, nameQname, "test"));
763
764         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
765
766         NormalizedNode<?, ?> payload = initEmptyInputAction(INTERFACE_QNAME);
767         NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
768                 DISABLE_INTERFACE_PATH, domDataTreeIdentifier, payload);
769
770         Node childAction = checkBasePartOfActionRequest(actionRequest);
771
772         Node childDevice = childAction.getFirstChild();
773         checkNode(childDevice, "device", "device", URN_EXAMPLE_SERVER_FARM);
774
775         Node childInterface = childDevice.getFirstChild();
776         checkNode(childInterface, "interface", "interface", URN_EXAMPLE_SERVER_FARM);
777
778         Node childName = childInterface.getFirstChild();
779         checkNode(childName, "name", "name", nameQname.getNamespace().toString());
780
781         Node childTest = childName.getFirstChild();
782         assertEquals(childTest.getNodeValue(), "test");
783
784         Node action = childInterface.getLastChild();
785         checkNode(action, DISABLE_QNAME.getLocalName(), DISABLE_QNAME.getLocalName(),
786                 DISABLE_QNAME.getNamespace().toString());
787     }
788
789     @SuppressWarnings({ "rawtypes", "unchecked" })
790     @Test
791     public void toActionResultTest() throws Exception {
792         NetconfMessage message = new NetconfMessage(XmlUtil.readXmlToDocument(
793                 "<rpc-reply message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
794                 + "<reset-finished-at xmlns=\"urn:example:server-farm\">"
795                 + "now"
796                 + "</reset-finished-at>"
797                 + "</rpc-reply>"));
798         DOMActionResult actionResult = actionNetconfMessageTransformer.toActionResult(RESET_SERVER_PATH, message);
799         assertNotNull(actionResult);
800         ContainerNode containerNode = actionResult.getOutput().get();
801         assertNotNull(containerNode);
802         LeafNode<String> leaf = (LeafNode) containerNode.getValue().iterator().next();
803         assertEquals("now", leaf.getValue());
804     }
805
806     @Test
807     public void toActionEmptyBodyWithOutputDefinedResultTest() throws Exception {
808         NetconfMessage message = new NetconfMessage(XmlUtil.readXmlToDocument(
809                 "<rpc-reply message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
810                 + "<ok/>"
811                 + "</rpc-reply>"));
812         DOMActionResult actionResult =
813                 actionNetconfMessageTransformer.toActionResult(CHECK_WITH_OUTPUT_INTERFACE_PATH, message);
814         assertNotNull(actionResult);
815         assertTrue(actionResult.getOutput().isEmpty());
816     }
817
818     @Test
819     public void toActionEmptyBodyWithoutOutputDefinedResultTest() throws Exception {
820         NetconfMessage message = new NetconfMessage(XmlUtil.readXmlToDocument(
821                 "<rpc-reply message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
822                 + "<ok/>"
823                 + "</rpc-reply>"));
824         DOMActionResult actionResult =
825                 actionNetconfMessageTransformer.toActionResult(CHECK_WITHOUT_OUTPUT_INTERFACE_PATH, message);
826         assertNotNull(actionResult);
827         assertTrue(actionResult.getOutput().isEmpty());
828     }
829
830     private static void checkAction(final QName actionQname, final Node action , final String inputLocalName,
831             final String inputNodeName, final String inputValue) {
832         checkNode(action, actionQname.getLocalName(), actionQname.getLocalName(),
833                 actionQname.getNamespace().toString());
834
835         Node childResetAt = action.getFirstChild();
836         checkNode(childResetAt, inputLocalName, inputNodeName, actionQname.getNamespace().toString());
837
838         Node firstChild = childResetAt.getFirstChild();
839         assertEquals(firstChild.getNodeValue(), inputValue);
840     }
841
842     private static Node checkBasePartOfActionRequest(final NetconfMessage actionRequest) {
843         Node baseRpc = actionRequest.getDocument().getFirstChild();
844         checkNode(baseRpc, "rpc", "rpc", NetconfUtil.NETCONF_QNAME.getNamespace().toString());
845         assertTrue(baseRpc.getLocalName().equals("rpc"));
846         assertTrue(baseRpc.getNodeName().equals("rpc"));
847
848         Node messageId = baseRpc.getAttributes().getNamedItem("message-id");
849         assertNotNull(messageId);
850         assertTrue(messageId.getNodeValue().contains("m-"));
851
852         Node childAction = baseRpc.getFirstChild();
853         checkNode(childAction, "action", "action", NetconfMessageTransformUtil.NETCONF_ACTION_NAMESPACE.toString());
854         return childAction;
855     }
856
857     private static DOMDataTreeIdentifier prepareDataTreeId(final List<PathArgument> nodeIdentifiers) {
858         YangInstanceIdentifier yangInstanceIdentifier =
859                 YangInstanceIdentifier.builder().append(nodeIdentifiers).build();
860         DOMDataTreeIdentifier domDataTreeIdentifier =
861                 new DOMDataTreeIdentifier(org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION,
862                         yangInstanceIdentifier);
863         return domDataTreeIdentifier;
864     }
865
866     private static ContainerNode initInputAction(final QName qname, final String value) {
867         ImmutableLeafNodeBuilder<String> immutableLeafNodeBuilder = new ImmutableLeafNodeBuilder<>();
868         DataContainerChild<NodeIdentifier, String> build = immutableLeafNodeBuilder.withNodeIdentifier(
869                 NodeIdentifier.create(qname)).withValue(value).build();
870         ContainerNode data = ImmutableContainerNodeBuilder.create().withNodeIdentifier(NodeIdentifier.create(
871                 QName.create(qname, "input"))).withChild(build).build();
872         return data;
873     }
874
875     private static ContainerNode initEmptyInputAction(final QName qname) {
876         return ImmutableContainerNodeBuilder.create().withNodeIdentifier(NodeIdentifier.create(
877                 QName.create(qname, "input"))).build();
878     }
879
880     private static void checkNode(final Node childServer, final String expectedLocalName, final String expectedNodeName,
881             final String expectedNamespace) {
882         assertNotNull(childServer);
883         assertEquals(childServer.getLocalName(), expectedLocalName);
884         assertEquals(childServer.getNodeName(), expectedNodeName);
885         assertEquals(childServer.getNamespaceURI(), expectedNamespace);
886     }
887 }