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
index ebba50649337f02381f7d83560a4ba3d735f943e..0aae2221882676dd2cd66eac6b56ab89a8ad7764 100644 (file)
@@ -48,7 +48,6 @@ import org.hamcrest.CoreMatchers;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
 import org.opendaylight.mdsal.dom.api.DOMActionResult;
@@ -65,6 +64,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.mon
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Capabilities;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
+import org.opendaylight.yangtools.rcf8528.data.util.EmptyMountPointContext;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
@@ -72,8 +72,8 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DOMSourceAnyxmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
@@ -100,6 +100,10 @@ public class NetconfMessageTransformerTest {
 
     private static final String URN_EXAMPLE_CONFLICT = "urn:example:conflict";
 
+    private static final String URN_EXAMPLE_AUGMENTED_ACTION = "urn:example:augmented-action";
+
+    private static final String URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS = "urn:example:rpcs-actions-outputs";
+
     private static final QName SERVER_QNAME =
             QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "server");
     private static final QName RESET_QNAME = QName.create(SERVER_QNAME, "reset");
@@ -120,6 +124,23 @@ public class NetconfMessageTransformerTest {
     private static final SchemaPath ENABLE_INTERFACE_PATH =
             SchemaPath.create(true, DEVICE_QNAME, INTERFACE_QNAME, ENABLE_QNAME);
 
+    private static final QName DISABLE_QNAME = QName.create(URN_EXAMPLE_AUGMENTED_ACTION, "disable");
+    private static final SchemaPath DISABLE_INTERFACE_PATH =
+            SchemaPath.create(true, DEVICE_QNAME, INTERFACE_QNAME, DISABLE_QNAME);
+
+    private static final QName CHECK_WITH_OUTPUT_QNAME =
+            QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "check-with-output");
+    private static final SchemaPath CHECK_WITH_OUTPUT_INTERFACE_PATH =
+            SchemaPath.create(true, DEVICE_QNAME, INTERFACE_QNAME, CHECK_WITH_OUTPUT_QNAME);
+    private static final QName CHECK_WITHOUT_OUTPUT_QNAME =
+            QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "check-without-output");
+    private static final SchemaPath CHECK_WITHOUT_OUTPUT_INTERFACE_PATH =
+            SchemaPath.create(true, DEVICE_QNAME, INTERFACE_QNAME, CHECK_WITHOUT_OUTPUT_QNAME);
+    private static final QName RPC_WITH_OUTPUT_QNAME =
+            QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "rpc-with-output");
+    private static final QName RPC_WITHOUT_OUTPUT_QNAME =
+            QName.create(URN_EXAMPLE_RPCS_ACTIONS_OUTPUTS, "rpc-without-output");
+
     private static final QName BOX_OUT_QNAME =
             QName.create(URN_EXAMPLE_SERVER_FARM, REVISION_EXAMPLE_SERVER_FARM, "box-out");
     private static final QName BOX_IN_QNAME = QName.create(BOX_OUT_QNAME, "box-in");
@@ -158,7 +179,8 @@ public class NetconfMessageTransformerTest {
 
         ACTION_SCHEMA = YangParserTestUtils.parseYangResources(NetconfMessageTransformerTest.class,
             "/schemas/example-server-farm.yang","/schemas/example-server-farm-2.yang",
-            "/schemas/conflicting-actions.yang");
+            "/schemas/conflicting-actions.yang", "/schemas/augmented-action.yang",
+            "/schemas/rpcs-actions-outputs.yang");
     }
 
     @AfterClass
@@ -175,7 +197,8 @@ public class NetconfMessageTransformerTest {
         XMLUnit.setIgnoreComments(true);
 
         netconfMessageTransformer = getTransformer(SCHEMA);
-        actionNetconfMessageTransformer = new NetconfMessageTransformer(ACTION_SCHEMA, true);
+        actionNetconfMessageTransformer = new NetconfMessageTransformer(new EmptyMountPointContext(ACTION_SCHEMA),
+            true);
     }
 
     @Test
@@ -190,8 +213,8 @@ public class NetconfMessageTransformerTest {
 
     @Test
     public void testCreateSubscriberNotificationSchemaNotPresent() throws Exception {
-        final NetconfMessageTransformer transformer = new NetconfMessageTransformer(SCHEMA, true,
-                BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS);
+        final NetconfMessageTransformer transformer = new NetconfMessageTransformer(new EmptyMountPointContext(SCHEMA),
+            true, BaseSchema.BASE_NETCONF_CTX_WITH_NOTIFICATIONS);
         NetconfMessage netconfMessage = transformer.toRpcRequest(
                 toPath(CREATE_SUBSCRIPTION_RPC_QNAME),
                 CREATE_SUBSCRIPTION_RPC_CONTENT
@@ -209,6 +232,26 @@ public class NetconfMessageTransformerTest {
         transformer.toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)), toPath(NETCONF_LOCK_QNAME));
     }
 
+    @Test
+    public void testRpcEmptyBodyWithOutputDefinedSchemaResult() throws Exception {
+        final String result = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>";
+
+        DOMRpcResult domRpcResult = actionNetconfMessageTransformer
+                .toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)),
+                        toPath(RPC_WITH_OUTPUT_QNAME));
+        assertNotNull(domRpcResult);
+    }
+
+    @Test
+    public void testRpcEmptyBodyWithoutOutputDefinedSchemaResult() throws Exception {
+        final String result = "<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><ok/></rpc-reply>";
+
+        DOMRpcResult domRpcResult = actionNetconfMessageTransformer
+                .toRpcResult(new NetconfMessage(XmlUtil.readXmlToDocument(result)),
+                        toPath(RPC_WITHOUT_OUTPUT_QNAME));
+        assertNotNull(domRpcResult);
+    }
+
     @Test
     public void testDiscardChangesRequest() throws Exception {
         final NetconfMessage netconfMessage =
@@ -248,8 +291,8 @@ public class NetconfMessageTransformerTest {
         final DOMRpcResult compositeNodeRpcResult = transformer.toRpcResult(response, toPath(GET_SCHEMA_QNAME));
         assertTrue(compositeNodeRpcResult.getErrors().isEmpty());
         assertNotNull(compositeNodeRpcResult.getResult());
-        final DOMSource schemaContent =
-            ((AnyXmlNode) ((ContainerNode) compositeNodeRpcResult.getResult()).getValue().iterator().next()).getValue();
+        final DOMSource schemaContent = ((DOMSourceAnyxmlNode) ((ContainerNode) compositeNodeRpcResult.getResult())
+                .getValue().iterator().next()).getValue();
         assertThat(schemaContent.getNode().getTextContent(),
                 CoreMatchers.containsString("Random YANG SCHEMA"));
     }
@@ -291,8 +334,8 @@ public class NetconfMessageTransformerTest {
         final MapEntryNode schemaNode =
                 Builders.mapEntryBuilder().withNodeIdentifier(identifierWithPredicates).withValue(values).build();
 
-        final AnyXmlNode data = (AnyXmlNode) ((ContainerNode) compositeNodeRpcResult
-                .getResult()).getChild(toId(NETCONF_DATA_QNAME)).get();
+        final DOMSourceAnyxmlNode data = (DOMSourceAnyxmlNode) ((ContainerNode) compositeNodeRpcResult.getResult())
+                .getChild(toId(NETCONF_DATA_QNAME)).get();
 
         NormalizedNodeResult nodeResult =
                 NetconfUtil.transformDOMSourceToNormalizedNode(SCHEMA, data.getValue());
@@ -441,7 +484,7 @@ public class NetconfMessageTransformerTest {
     }
 
     private static NetconfMessageTransformer getTransformer(final SchemaContext schema) {
-        return new NetconfMessageTransformer(schema, true);
+        return new NetconfMessageTransformer(new EmptyMountPointContext(schema), true);
     }
 
     @Test
@@ -466,6 +509,9 @@ public class NetconfMessageTransformerTest {
         schemaPaths.add(XYZZY_FOO_PATH);
         schemaPaths.add(XYZZY_BAR_PATH);
         schemaPaths.add(CHOICE_ACTION_PATH);
+        schemaPaths.add(DISABLE_INTERFACE_PATH);
+        schemaPaths.add(CHECK_WITH_OUTPUT_INTERFACE_PATH);
+        schemaPaths.add(CHECK_WITHOUT_OUTPUT_INTERFACE_PATH);
 
         List<ActionDefinition> actions = NetconfMessageTransformer.getActions(ACTION_SCHEMA);
         assertEquals(schemaPaths.size(), actions.size());
@@ -540,7 +586,7 @@ public class NetconfMessageTransformerTest {
         checkNode(childBoxIn, "box-in", "box-in", URN_EXAMPLE_SERVER_FARM);
 
         Node action = childBoxIn.getFirstChild();
-        checkNode(action, null, OPEN_QNAME.getLocalName(), null);
+        checkNode(action, OPEN_QNAME.getLocalName(), OPEN_QNAME.getLocalName(), OPEN_QNAME.getNamespace().toString());
     }
 
     @Test
@@ -573,7 +619,8 @@ public class NetconfMessageTransformerTest {
         assertEquals(childTest.getNodeValue(), "test");
 
         Node action = childInterface.getLastChild();
-        checkNode(action, null, ENABLE_QNAME.getLocalName(), null);
+        checkNode(action, ENABLE_QNAME.getLocalName(), ENABLE_QNAME.getLocalName(),
+                ENABLE_QNAME.getNamespace().toString());
     }
 
     @Test
@@ -621,7 +668,8 @@ public class NetconfMessageTransformerTest {
 
         Node childKillAction = childApplication.getLastChild();
         checkNode(childApplication, "application", "application", URN_EXAMPLE_SERVER_FARM_2);
-        checkNode(childKillAction, null, KILL_QNAME.getLocalName(), null);
+        checkNode(childKillAction, KILL_QNAME.getLocalName(), KILL_QNAME.getLocalName(),
+                KILL_QNAME.getNamespace().toString());
     }
 
     @Test
@@ -657,7 +705,8 @@ public class NetconfMessageTransformerTest {
         assertEquals(childTest.getNodeValue(), "test");
 
         Node action = childBar.getLastChild();
-        checkNode(action, null, XYZZY_QNAME.getLocalName(), null);
+        checkNode(action, XYZZY_QNAME.getLocalName(), XYZZY_QNAME.getLocalName(),
+                XYZZY_QNAME.getNamespace().toString());
     }
 
     @Test
@@ -678,13 +727,14 @@ public class NetconfMessageTransformerTest {
         checkNode(childBar, "foo", "foo", URN_EXAMPLE_CONFLICT);
 
         Node action = childBar.getLastChild();
-        checkNode(action, null, XYZZY_QNAME.getLocalName(), null);
+        checkNode(action, XYZZY_QNAME.getLocalName(), XYZZY_QNAME.getLocalName(),
+                XYZZY_QNAME.getNamespace().toString());
     }
 
     @Test
-    @Ignore
     public void toActionRequestChoiceTest() {
         List<PathArgument> nodeIdentifiers = new ArrayList<>();
+        nodeIdentifiers.add(NodeIdentifier.create(CONFLICT_CHOICE_QNAME));
         nodeIdentifiers.add(NodeIdentifier.create(CHOICE_CONT_QNAME));
         DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
         NormalizedNode<?, ?> payload = initEmptyInputAction(CHOICE_ACTION_QNAME);
@@ -698,7 +748,42 @@ public class NetconfMessageTransformerTest {
         checkNode(childChoiceCont, "choice-cont", "choice-cont", URN_EXAMPLE_CONFLICT);
 
         Node action = childChoiceCont.getLastChild();
-        checkNode(action, null, CHOICE_ACTION_QNAME.getLocalName(), null);
+        checkNode(action, CHOICE_ACTION_QNAME.getLocalName(), CHOICE_ACTION_QNAME.getLocalName(),
+                CHOICE_ACTION_QNAME.getNamespace().toString());
+    }
+
+    @Test
+    public void toAugmentedActionRequestListInContainerTest() {
+        QName nameQname = QName.create(INTERFACE_QNAME, "name");
+
+        List<PathArgument> nodeIdentifiers = new ArrayList<>();
+        nodeIdentifiers.add(NodeIdentifier.create(DEVICE_QNAME));
+        nodeIdentifiers.add(NodeIdentifier.create(INTERFACE_QNAME));
+        nodeIdentifiers.add(NodeIdentifierWithPredicates.of(INTERFACE_QNAME, nameQname, "test"));
+
+        DOMDataTreeIdentifier domDataTreeIdentifier = prepareDataTreeId(nodeIdentifiers);
+
+        NormalizedNode<?, ?> payload = initEmptyInputAction(INTERFACE_QNAME);
+        NetconfMessage actionRequest = actionNetconfMessageTransformer.toActionRequest(
+                DISABLE_INTERFACE_PATH, domDataTreeIdentifier, payload);
+
+        Node childAction = checkBasePartOfActionRequest(actionRequest);
+
+        Node childDevice = childAction.getFirstChild();
+        checkNode(childDevice, "device", "device", URN_EXAMPLE_SERVER_FARM);
+
+        Node childInterface = childDevice.getFirstChild();
+        checkNode(childInterface, "interface", "interface", URN_EXAMPLE_SERVER_FARM);
+
+        Node childName = childInterface.getFirstChild();
+        checkNode(childName, "name", "name", nameQname.getNamespace().toString());
+
+        Node childTest = childName.getFirstChild();
+        assertEquals(childTest.getNodeValue(), "test");
+
+        Node action = childInterface.getLastChild();
+        checkNode(action, DISABLE_QNAME.getLocalName(), DISABLE_QNAME.getLocalName(),
+                DISABLE_QNAME.getNamespace().toString());
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
@@ -718,9 +803,34 @@ public class NetconfMessageTransformerTest {
         assertEquals("now", leaf.getValue());
     }
 
+    @Test
+    public void toActionEmptyBodyWithOutputDefinedResultTest() throws Exception {
+        NetconfMessage message = new NetconfMessage(XmlUtil.readXmlToDocument(
+                "<rpc-reply message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
+                + "<ok/>"
+                + "</rpc-reply>"));
+        DOMActionResult actionResult =
+                actionNetconfMessageTransformer.toActionResult(CHECK_WITH_OUTPUT_INTERFACE_PATH, message);
+        assertNotNull(actionResult);
+        assertTrue(actionResult.getOutput().isEmpty());
+    }
+
+    @Test
+    public void toActionEmptyBodyWithoutOutputDefinedResultTest() throws Exception {
+        NetconfMessage message = new NetconfMessage(XmlUtil.readXmlToDocument(
+                "<rpc-reply message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
+                + "<ok/>"
+                + "</rpc-reply>"));
+        DOMActionResult actionResult =
+                actionNetconfMessageTransformer.toActionResult(CHECK_WITHOUT_OUTPUT_INTERFACE_PATH, message);
+        assertNotNull(actionResult);
+        assertTrue(actionResult.getOutput().isEmpty());
+    }
+
     private static void checkAction(final QName actionQname, final Node action , final String inputLocalName,
             final String inputNodeName, final String inputValue) {
-        checkNode(action, null, actionQname.getLocalName(), null);
+        checkNode(action, actionQname.getLocalName(), actionQname.getLocalName(),
+                actionQname.getNamespace().toString());
 
         Node childResetAt = action.getFirstChild();
         checkNode(childResetAt, inputLocalName, inputNodeName, actionQname.getNamespace().toString());