Add test for CreateStreamUtil class 90/44390/9
authormiroslav.kovac <miroslav.kovac@pantheon.sk>
Fri, 19 Aug 2016 11:30:51 +0000 (13:30 +0200)
committerMiroslav Kovac <miroslav.kovac@pantheon.tech>
Mon, 5 Sep 2016 09:00:42 +0000 (09:00 +0000)
Redundant condition removed from CreateStreamUtil class

Change-Id: I6ed7c88b05c895bcf21c70eb533f742bca30ee49
Signed-off-by: miroslav.kovac <miroslav.kovac@pantheon.sk>
Signed-off-by: miroslav.kovac <miroslav.kovac@pantheon.tech>
restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/CreateStreamUtil.java
restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/CreateStreamUtilTest.java [new file with mode: 0644]
restconf/sal-rest-connector/src/test/resources/streams/sal-remote@2014-01-14.yang [new file with mode: 0644]
restconf/sal-rest-connector/src/test/resources/streams/toaster.yang [new file with mode: 0644]

index 03b04182471fdf85202d26a81729d6d74af3fc5e..e4f867c61331ff2e0e2fb7eadf661e19b9183789 100644 (file)
@@ -89,7 +89,7 @@ public final class CreateStreamUtil {
             final SchemaContextRef refSchemaCtx) {
         final ContainerNode data = (ContainerNode) payload.getData();
         final QName qname = payload.getInstanceIdentifierContext().getSchemaNode().getQName();
-        final YangInstanceIdentifier path = preparePath(payload, data, qname);
+        final YangInstanceIdentifier path = preparePath(data, qname);
         final String streamName = prepareStream(path, refSchemaCtx.get(), data);
 
         final QName outputQname = QName.create(qname, "output");
@@ -118,11 +118,6 @@ public final class CreateStreamUtil {
         final String streamName = Notificator
                 .createStreamNameFromUri(ParserIdentifier.stringFromYangInstanceIdentifier(path, schemaContext)
                 + RestconfStreamsConstants.DS_URI + ds + RestconfStreamsConstants.SCOPE_URI + scope);
-        if((streamName == null) || streamName.equals("")){
-            final String errMsg = "Path is empty or contains value node which is not Container or List build-in type.";
-            LOG.debug(errMsg + path);
-            throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
-        }
         return streamName;
     }
 
@@ -146,8 +141,7 @@ public final class CreateStreamUtil {
         return StreamUtil.resolveEnum(clazz, (String) value);
     }
 
-    private static YangInstanceIdentifier preparePath(final NormalizedNodeContext payload, final ContainerNode data,
-            final QName qName) {
+    private static YangInstanceIdentifier preparePath(final ContainerNode data, final QName qName) {
         final Optional<DataContainerChild<? extends PathArgument, ?>> path = data
                 .getChild(new YangInstanceIdentifier.NodeIdentifier(QName.create(qName, "path")));
         Object pathValue = null;
diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/CreateStreamUtilTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/CreateStreamUtilTest.java
new file mode 100644 (file)
index 0000000..7ca7627
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.restconf.restful.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
+import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
+import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.restconf.common.references.SchemaContextRef;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
+
+public class CreateStreamUtilTest {
+
+    private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/streams";
+
+    private NormalizedNodeContext payload;
+    private SchemaContextRef refSchemaCtx;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        refSchemaCtx = new SchemaContextRef(TestRestconfUtils.loadSchemaContext(PATH_FOR_NEW_SCHEMA_CONTEXT));
+    }
+
+    @Test
+    public void createStreamTest() {
+        payload = prepareDomPayload("create-data-change-event-subscription", "input", "toaster", "path");
+        final DOMRpcResult result = CreateStreamUtil.createStream(payload, refSchemaCtx);
+        assertEquals(result.getErrors(), Collections.emptyList());
+        final NormalizedNode<?, ?> testedNn = result.getResult();
+        assertNotNull(testedNn);
+        final NormalizedNodeContext contextRef = prepareDomPayload("create-data-change-event-subscription", "output", "toaster:toaster/datastore=CONFIGURATION/scope=BASE", "stream-name");
+        assertEquals(contextRef.getData(), testedNn);
+    }
+
+    @Test(expected = RestconfDocumentedException.class)
+    public void createStreamWrongValueTest() {
+        payload = prepareDomPayload("create-data-change-event-subscription", "input", "String value", "path");
+        final DOMRpcResult result = CreateStreamUtil.createStream(payload, refSchemaCtx);
+        assertEquals(result.getErrors(), Collections.emptyList());
+    }
+
+    @Test(expected = RestconfDocumentedException.class)
+    public void createStreamWrongInputRpcTest() {
+        payload = prepareDomPayload("create-data-change-event-subscription2", "input", "toaster", "path2");
+        final DOMRpcResult result = CreateStreamUtil.createStream(payload, refSchemaCtx);
+        assertEquals(result.getErrors(), Collections.emptyList());
+    }
+
+    private NormalizedNodeContext prepareDomPayload(final String rpcName, final String inputOutput, final String toasterValue, final String inputOutputName) {
+        final SchemaContext schema = refSchemaCtx.get();
+        final Module rpcModule = schema.findModuleByName("sal-remote", null);
+        assertNotNull(rpcModule);
+        final QName rpcQName = QName.create(rpcModule.getQNameModule(), rpcName);
+        final QName rpcInputQName = QName.create(rpcModule.getQNameModule(), inputOutput);
+        final Set<RpcDefinition> setRpcs = rpcModule.getRpcs();
+        ContainerSchemaNode rpcInputSchemaNode = null;
+        for (final RpcDefinition rpc : setRpcs) {
+            if (rpcQName.isEqualWithoutRevision(rpc.getQName())) {
+                rpcInputSchemaNode = SchemaNodeUtils.getRpcDataSchema(rpc, rpcInputQName);
+                break;
+            }
+        }
+        assertNotNull(rpcInputSchemaNode);
+
+        final DataContainerNodeAttrBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> container = Builders.containerBuilder(rpcInputSchemaNode);
+
+        final QName lfQName = QName.create(rpcModule.getQNameModule(), inputOutputName);
+        final DataSchemaNode lfSchemaNode = rpcInputSchemaNode.getDataChildByName(lfQName);
+
+        assertTrue(lfSchemaNode instanceof LeafSchemaNode);
+
+        final QName rpcQname = QName.create("http://netconfcentral.org/ns/toaster", "2009-11-20", toasterValue);
+        final Object o;
+        if ("toaster".equals(toasterValue)) {
+            o = YangInstanceIdentifier.builder().node(rpcQname).build();
+        } else {
+            o = toasterValue;
+        }
+        final LeafNode<Object> lfNode = (Builders.leafBuilder((LeafSchemaNode) lfSchemaNode)
+                .withValue(o)).build();
+        container.withChild(lfNode);
+
+        return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, rpcInputSchemaNode, null, schema), container.build());
+    }
+}
diff --git a/restconf/sal-rest-connector/src/test/resources/streams/sal-remote@2014-01-14.yang b/restconf/sal-rest-connector/src/test/resources/streams/sal-remote@2014-01-14.yang
new file mode 100644 (file)
index 0000000..0f6aebf
--- /dev/null
@@ -0,0 +1,112 @@
+module sal-remote {
+
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote";
+    prefix "sal-remote";
+
+    organization "Cisco Systems, Inc.";
+    contact "Martin Bobak <mbobak@cisco.com>";
+
+    description
+          "This module contains the definition of methods related to
+           sal remote model.
+
+           Copyright (c)2013 Cisco Systems, Inc. All rights reserved.
+
+           This program and the accompanying materials are made available
+           under the terms of the Eclipse Public License v1.0 which
+           accompanies this distribution, and is available at
+           http://www.eclipse.org/legal/epl-v10.html";
+
+    revision "2014-01-14" {
+        description
+            "Initial revision";
+    }
+
+
+     typedef q-name {
+       type string;
+       reference
+         "http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#QName";
+     }
+
+    rpc create-data-change-event-subscription {
+        input {
+            leaf path {
+                type instance-identifier;
+                description "Subtree path. ";
+            }
+         }
+         output {
+            leaf stream-name {
+                type string;
+                description "Notification stream name.";
+            }
+         }
+    }
+
+        rpc create-data-change-event-subscription2 {
+            input {
+                leaf path2 {
+                    type instance-identifier;
+                    description "Subtree path. ";
+                }
+             }
+             output {
+                leaf stream-name2 {
+                    type string;
+                    description "Notification stream name.";
+                }
+             }
+        }
+
+    notification data-changed-notification {
+        description "Data change notification.";
+        list data-change-event {
+            key path;
+            leaf path {
+                type instance-identifier;
+            }
+            leaf store {
+                type enumeration {
+                    enum config;
+                    enum operation;
+                }
+            }
+            leaf operation {
+                type enumeration {
+                    enum created;
+                    enum updated;
+                    enum deleted;
+                }
+            }
+            anyxml data{
+                description "DataObject ";
+            }
+         }
+    }
+
+    rpc create-notification-stream {
+        input {
+            leaf-list notifications {
+                type q-name;
+                description "Notification QNames";
+            }
+         }
+        output {
+            leaf notification-stream-identifier {
+                type string;
+                description "Unique notification stream identifier, in which notifications will be propagated";
+            }
+        }
+    }
+
+    rpc begin-transaction{
+        output{
+            anyxml data-modification-transaction{
+                description "DataModificationTransaction xml";
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/restconf/sal-rest-connector/src/test/resources/streams/toaster.yang b/restconf/sal-rest-connector/src/test/resources/streams/toaster.yang
new file mode 100644 (file)
index 0000000..ad6b9b0
--- /dev/null
@@ -0,0 +1,197 @@
+  module toaster {
+
+    yang-version 1;
+
+    namespace
+      "http://netconfcentral.org/ns/toaster";
+
+    prefix toast;
+
+    organization "Netconf Central";
+
+    contact
+      "Andy Bierman <andy@netconfcentral.org>";
+
+    description
+      "YANG version of the TOASTER-MIB.";
+
+    revision "2009-11-20" {
+      description
+        "Toaster module in progress.";
+    }
+
+
+    identity toast-type {
+      description
+        "Base for all bread types supported by the toaster.
+           New bread types not listed here nay be added in the
+           future.";
+    }
+
+    identity white-bread {
+      base toast:toast-type;
+      description "White bread.";
+    }
+
+    identity wheat-bread {
+      base toast-type;
+      description "Wheat bread.";
+    }
+
+    identity wonder-bread {
+      base toast-type;
+      description "Wonder bread.";
+    }
+
+    identity frozen-waffle {
+      base toast-type;
+      description "Frozen waffle.";
+    }
+
+    identity frozen-bagel {
+      base toast-type;
+      description "Frozen bagel.";
+    }
+
+    identity hash-brown {
+      base toast-type;
+      description "Hash browned potatos.";
+    }
+
+    typedef DisplayString {
+      type string {
+        length "0 .. 255";
+      }
+      description
+        "YANG version of the SMIv2 DisplayString TEXTUAL-CONVENTION.";
+      reference
+        "RFC 2579, section 2.";
+
+    }
+
+    container toaster {
+      presence
+        "Indicates the toaster service is available";
+      description
+        "Top-level container for all toaster database objects.";
+      leaf toasterManufacturer {
+        type DisplayString;
+        config false;
+        mandatory true;
+        description
+          "The name of the toaster's manufacturer. For instance, 
+                Microsoft Toaster.";
+      }
+
+      leaf toasterModelNumber {
+        type DisplayString;
+        config false;
+        mandatory true;
+        description
+          "The name of the toaster's model. For instance,
+               Radiant Automatic.";
+      }
+
+      leaf toasterStatus {
+        type enumeration {
+          enum "up" {
+            value 1;
+            description
+              "The toaster knob position is up.
+                      No toast is being made now.";
+          }
+          enum "down" {
+            value 2;
+            description
+              "The toaster knob position is down.
+                      Toast is being made now.";
+          }
+        }
+        config false;
+        mandatory true;
+        description
+          "This variable indicates the current state of 
+               the toaster.";
+      }
+    }  // container toaster
+
+    rpc make-toast {
+      description
+        "Make some toast.
+           The toastDone notification will be sent when 
+           the toast is finished.
+           An 'in-use' error will be returned if toast
+           is already being made.
+           A 'resource-denied' error will be returned 
+           if the toaster service is disabled.";
+      input {
+        leaf toasterDoneness {
+          type uint32 {
+            range "1 .. 10";
+          }
+          default '5';
+          description
+            "This variable controls how well-done is the 
+                   ensuing toast. It should be on a scale of 1 to 10.
+                   Toast made at 10 generally is considered unfit 
+                   for human consumption; toast made at 1 is warmed 
+                   lightly.";
+        }
+
+        leaf toasterToastType {
+          type identityref {
+            base toast:toast-type;
+          }
+          default 'wheat-bread';
+          description
+            "This variable informs the toaster of the type of 
+                   material that is being toasted. The toaster 
+                   uses this information, combined with 
+                   toasterDoneness, to compute for how 
+                   long the material must be toasted to achieve 
+                   the required doneness.";
+        }
+      }
+    }  // rpc make-toast
+
+    rpc testOutput { 
+        output {
+            leaf textOut {
+                type string;
+            }        
+        }
+    }
+
+    rpc cancel-toast {
+      description
+        "Stop making toast, if any is being made.
+           A 'resource-denied' error will be returned 
+           if the toaster service is disabled.";
+    }  // rpc cancel-toast
+
+    notification toastDone {
+      description
+        "Indicates that the toast in progress has completed.";
+      leaf toastStatus {
+        type enumeration {
+          enum "done" {
+            value 0;
+            description "The toast is done.";
+          }
+          enum "cancelled" {
+            value 1;
+            description
+              "The toast was cancelled.";
+          }
+          enum "error" {
+            value 2;
+            description
+              "The toaster service was disabled or
+                     the toaster is broken.";
+          }
+        }
+        description
+          "Indicates the final toast status";
+      }
+    }  // notification toastDone
+  }  // module toaster