Merge "Applied bootstrap styles"
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.html b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.html
index ea4c298..5a3973a 100644
--- a/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.html
+++ b/cds-ui/client/src/app/feature-modules/blueprint/modify-template/editor/editor.component.html
@@ -17,7 +17,6 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 ============LICENSE_END============================================ -->
-
 <div class="containerDiv">
     <div class="fileViewContainer">
         <!-- <div style="width:inherit; height: inherit; position: fixed;z-index: 1; background-color: rgb(0,0,0);background-color: rgba(0,0,0,0.4);"></div> -->
@@ -46,7 +45,7 @@
             </mat-tree-node>
         </mat-tree>
     </div>
-    <div class="editorConatiner">
+    <div class="editorConatiner" [ngClass] = "{ 'apply-scrol-to-editor-container' : viewTemplateMode}">
         <!-- <i class="fa fa-save save-icon" style="font-size:24px" (click)="updateBlueprint()"></i>
         <ace-editor [(text)]="text" [(mode)]="mode" #editor class="aceEditor"></ace-editor> -->
         <div class="normal-editor-mode" [ngClass]="{ 'resource-mapping-mode': viewTemplateMode}">
diff --git a/cds-ui/server/src/controllers/blueprint-rest.controller.ts b/cds-ui/server/src/controllers/blueprint-rest.controller.ts
index c630ce0..c1f7f96 100644
--- a/cds-ui/server/src/controllers/blueprint-rest.controller.ts
+++ b/cds-ui/server/src/controllers/blueprint-rest.controller.ts
@@ -135,14 +135,15 @@
     });
   }
 
-  @get('/download-blueprint/{id}')
+  @get('/download-blueprint/{name}/{version}')
   async download(
-    @param.path.string('id') id: string,
-    @inject(RestBindings.Http.REQUEST) request: Request,
+    @param.path.string('name') name: string,
+    @param.path.string('version') version:string,
+    // @inject(RestBindings.Http.REQUEST) request: Request,
     @inject(RestBindings.Http.RESPONSE) response: Response,
   ): Promise<any> {
     return new Promise((resolve, reject) => { 
-      this.downloadFileFromBlueprintController("/blueprint-model/download/" + id).then(resp=>{
+      this.downloadFileFromBlueprintController("/blueprint-model/download/by-name/"+name+"/version/"+version).then(resp=>{
         response.setHeader("X-ONAP-RequestID", resp.headers['x-onap-requestid']);
         response.setHeader("Content-Disposition", resp.headers['content-disposition']);
         resolve(resp.body);
diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/config-deploy-pnf-mapping.json b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/config-deploy-pnf-mapping.json
index 536295e..d87b8d1 100644
--- a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/config-deploy-pnf-mapping.json
+++ b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/config-deploy-pnf-mapping.json
@@ -1,11 +1,11 @@
 [
   {
-    "name": "nf-id",
+    "name": "pnf-id",
     "input-param": true,
     "property": {
       "type": "string"
     },
-    "dictionary-name": "nf-id",
+    "dictionary-name": "pnf-id",
     "dictionary-source": "input",
     "dependencies": [
     ]
diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/data_types.json b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/data_types.json
index e94bb0f..a0804bb 100644
--- a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/data_types.json
+++ b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/data_types.json
@@ -13,7 +13,7 @@
         "pnf-ipv4-address" : {
           "type" : "string"
         },
-        "nf-id" : {
+        "pnf-id" : {
           "type" : "string"
         }
       },
diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/resources_definition_types.json b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/resources_definition_types.json
index 0153276..114eb19 100644
--- a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/resources_definition_types.json
+++ b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Definitions/resources_definition_types.json
@@ -1,9 +1,9 @@
 {
-  "nf-id" : {
-    "tags" : "nf-id",
-    "name" : "nf-id",
+  "pnf-id" : {
+    "tags" : "pnf-id",
+    "name" : "pnf-id",
     "property" : {
-      "description" : "nf-id",
+      "description" : "pnf-id",
       "type" : "string"
     },
     "updated-by" : "Rodrigo Ottero <rodrigo.ottero@est.tech>",
diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Scripts/python/RestconfConfigDeploy.py b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Scripts/python/RestconfConfigDeploy.py
index 2402c5b..d65aefa 100644
--- a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Scripts/python/RestconfConfigDeploy.py
+++ b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Scripts/python/RestconfConfigDeploy.py
@@ -67,9 +67,9 @@
     def retrieve_parameters(self, execution_request):
         resolution_key = self.getDynamicProperties("resolution-key").asText()
         self.log.info("resolution_key: {}", resolution_key)
-        pnf_id = execution_request.payload.get("config-deploy-request").get("config-deploy-properties").get("nf-id")
+        pnf_id = execution_request.payload.get("config-deploy-request").get("config-deploy-properties").get("pnf-id")
         pnf_id = str(pnf_id).strip('\"')
-        self.log.info("nf-id: {}", pnf_id)
+        self.log.info("pnf-id: {}", pnf_id)
         return pnf_id, resolution_key
 
     def recover(self, runtime_exception, execution_request):
diff --git a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Templates/config-deploy-restconf-mount-template.vtl b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Templates/config-deploy-restconf-mount-template.vtl
index caad02b..ad03321 100644
--- a/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Templates/config-deploy-restconf-mount-template.vtl
+++ b/components/model-catalog/blueprint-model/test-blueprint/capability_restconf/Templates/config-deploy-restconf-mount-template.vtl
@@ -1,7 +1,7 @@
 <node xmlns="urn:TBD:params:xml:ns:yang:network-topology">
-    <node-id>$nf-id</node-id>
+    <node-id>$pnf-id</node-id>
     <key-based xmlns="urn:opendaylight:netconf-node-topology">
-        <key-id xmlns="urn:opendaylight:netconf-node-topology">ODL-private-key</key-id>
+        <key-id xmlns="urn:opendaylight:netconf-node-topology">ODL_private_key_0</key-id>
         <username xmlns="urn:opendaylight:netconf-node-topology">netconf</username>
      </key-based>
     <host xmlns="urn:opendaylight:netconf-node-topology">$pnf-ipv4-address</host>
diff --git a/components/model-catalog/resource-dictionary/starter-dictionary/nf-id.json b/components/model-catalog/resource-dictionary/starter-dictionary/pnf-id.json
similarity index 74%
rename from components/model-catalog/resource-dictionary/starter-dictionary/nf-id.json
rename to components/model-catalog/resource-dictionary/starter-dictionary/pnf-id.json
index a140a44..3246853 100755
--- a/components/model-catalog/resource-dictionary/starter-dictionary/nf-id.json
+++ b/components/model-catalog/resource-dictionary/starter-dictionary/pnf-id.json
@@ -1,9 +1,9 @@
 {
-  "name" : "nf-id",
-  "tags" : "nf-id",
+  "name" : "pnf-id",
+  "tags" : "pnf-id",
   "updated-by" : "Rodrigo Ottero <rodrigo.ottero@est.tech>",
   "property" : {
-    "description" : "nf-id",
+    "description" : "pnf-id",
     "type" : "string"
   },
   "sources" : {
diff --git a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties
index fc148bf..0e2cdf9 100755
--- a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties
+++ b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties
@@ -18,10 +18,10 @@
 #logging.level.web=DEBUG

 

 # Web server config

-server.port=8080

+server.port=8081

 

 blueprintsprocessor.grpcEnable=false

-blueprintsprocessor.httpPort=8080

+blueprintsprocessor.httpPort=8081

 blueprintsprocessor.grpcPort=9111

 

 # Blueprint Processor File Execution and Handling Properties

diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt
index ef3605c..1d5f515 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfMessage.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017-2019 AT&T, Bell Canada
+ * Copyright © 2019 Bell Canada
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,25 +18,13 @@
 
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.RpcStatus
 
-class DeviceResponse {
-    var status: String? = null
-    var errorMessage: String? = null
-    var responseMessage: String? = null
-    var requestMessage: String? = null
-    private var subDeviceResponse: MutableMap<Any, Any>? = null
-
-    fun addSubDeviceResponse(key: String, subDeviceResponse: DeviceResponse) {
-        if (this.subDeviceResponse == null) {
-            this.subDeviceResponse = hashMapOf()
-        }
-        this.subDeviceResponse!![key] = subDeviceResponse
-    }
+data class DeviceResponse(var status: String? = null,
+                          var errorMessage: String? = null,
+                          var responseMessage: String? = null,
+                          var requestMessage: String? = null) {
 
     fun isSuccess(): Boolean {
-        if (this.status != RpcStatus.SUCCESS && !this.errorMessage.isNullOrEmpty()) {
-            return false
-        }
-        return true
+        return this.status == RpcStatus.SUCCESS && this.errorMessage.isNullOrEmpty()
     }
 }
 
@@ -45,13 +33,14 @@
  * Creates an event of a given type and for the specified subject and the current time.
  *
  * @param type event type
- * @param payload message from the device
+ * @param messagePayload message from the device
  * @param messageId id of the message related to the event
  * @param deviceInfo device of event
  */
-class NetconfReceivedEvent
-    (private var type: Type, private var payload: String = "", private var messageId: String = "",
-     private var deviceInfo: DeviceInfo) {
+class NetconfReceivedEvent(val type: Type,
+                           val messagePayload: String = "",
+                           val messageId: String = "",
+                           val deviceInfo: DeviceInfo) {
 
     enum class Type {
         DEVICE_REPLY,
@@ -59,16 +48,4 @@
         DEVICE_ERROR,
         SESSION_CLOSED
     }
-
-    fun getType(): Type {
-        return type
-    }
-
-    fun getMessagePayload(): String {
-        return payload
-    }
-
-    fun getMessageID(): String {
-        return messageId
-    }
 }
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt
index 4619460..e4e3ffe 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImpl.kt
@@ -49,7 +49,7 @@
             output = asyncRpc(rpc, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in invokeRpc command $e.message"
+            output.errorMessage = "$deviceInfo: failed in 'invokeRpc' command ${e.message}"
         }
         return output
     }
@@ -63,7 +63,7 @@
             output = asyncRpc(message, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in get-config command $e.message"
+            output.errorMessage = "$deviceInfo: failed in 'get-config' command ${e.message}"
         }
         return output
     }
@@ -78,7 +78,7 @@
             output = asyncRpc(deleteConfigMessage, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in delete config command $e.message"
+            output.errorMessage = "$deviceInfo: failed in 'delete-config' command ${e.message}"
         }
         return output
     }
@@ -93,7 +93,7 @@
             output = asyncRpc(lockMessage, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in lock command $e.message"
+            output.errorMessage = "$deviceInfo: failed in 'lock' command ${e.message}"
         }
 
         return output
@@ -109,7 +109,7 @@
             output = asyncRpc(unlockMessage, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in lock command $e.message"
+            output.errorMessage = "$deviceInfo: failed in 'unLock' command ${e.message}"
         }
         return output
     }
@@ -123,7 +123,7 @@
             output = asyncRpc(messageContent, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in commit command $e.message"
+            output.errorMessage = "$deviceInfo: failed in 'commit' command ${e.message}"
         }
         return output
     }
@@ -137,7 +137,7 @@
             output = asyncRpc(messageContent, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in cancelCommit command $e.message"
+            output.errorMessage = "$deviceInfo: failed in 'cancelCommit' command ${e.message}"
         }
         return output
     }
@@ -152,7 +152,7 @@
             output = asyncRpc(discardChangesMessage, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in discard changes command " + e.message
+            output.errorMessage = "$deviceInfo: failed in 'discard-config' command ${e.message}"
         }
         return output
     }
@@ -169,7 +169,7 @@
             response = asyncRpc(editMessage, messageId)
         } catch (e: Exception) {
             response.status = RpcStatus.FAILURE
-            response.errorMessage = e.message
+            response.errorMessage = "$deviceInfo: failed in 'editConfig' command ${e.message}"
         }
         return response
     }
@@ -183,7 +183,7 @@
             output = asyncRpc(validateMessage, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in validate command " + e.message
+            output.errorMessage = "$deviceInfo: failed in 'validate' command ${e.message}"
         }
         return output
     }
@@ -197,7 +197,7 @@
             output = asyncRpc(messageContent, messageId)
         } catch (e: Exception) {
             output.status = RpcStatus.FAILURE
-            output.errorMessage = "$deviceInfo: failed in closeSession command " + e.message
+            output.errorMessage = "$deviceInfo: failed in 'closeSession' command ${e.message}"
         }
         return output
     }
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt
index de4cda9..ae4d844 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfSessionImpl.kt
@@ -264,12 +264,12 @@
 
     inner class NetconfSessionListenerImpl : NetconfSessionListener {
         override fun notify(event: NetconfReceivedEvent) {
-            val messageId = event.getMessageID()
+            val messageId = event.messageId
 
-            when (event.getType()) {
+            when (event.type) {
                 NetconfReceivedEvent.Type.DEVICE_UNREGISTERED -> disconnect()
-                NetconfReceivedEvent.Type.DEVICE_ERROR -> errorReplies.add(event.getMessagePayload())
-                NetconfReceivedEvent.Type.DEVICE_REPLY -> replies[messageId]?.complete(event.getMessagePayload())
+                NetconfReceivedEvent.Type.DEVICE_ERROR -> errorReplies.add(event.messagePayload)
+                NetconfReceivedEvent.Type.DEVICE_REPLY -> replies[messageId]?.complete(event.messagePayload)
                 NetconfReceivedEvent.Type.SESSION_CLOSED -> disconnect()
             }
         }
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt
index 68d3e24..eb32c54 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfRpcServiceImplTest.kt
@@ -1,124 +1,356 @@
+/*
+ * Copyright © 2019 Bell Canada
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core
 
-import org.junit.After
-import org.junit.Assert
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.spyk
 import org.junit.Before
-import org.junit.Test
 
-import org.junit.Assert.*
+import org.junit.Test
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo
-import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.mocks.NetconfDeviceSimulator
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceResponse
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfException
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils.RpcStatus
+import java.io.IOException
+import java.util.concurrent.CompletableFuture
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+import kotlin.test.assertTrue
 
 class NetconfRpcServiceImplTest {
+    private lateinit var mockNetconfSession: NetconfSessionImpl
 
-    private var device: NetconfDeviceSimulator? = null
-    private var deviceInfo: DeviceInfo? = null
-
-    @Before
-    fun before() {
-        deviceInfo = DeviceInfo().apply {
+    companion object {
+        private const val someString = "someString"
+        private const val replyStr = "this is a reply"
+        private val failedDeviceResponse = DeviceResponse(status = RpcStatus.FAILURE,
+            requestMessage = "request message", responseMessage = replyStr) //responseMessage will be null in this POJO
+        private val successfulDeviceResponse = DeviceResponse(status = RpcStatus.SUCCESS,
+            requestMessage = "request message", responseMessage = replyStr) //responseMessage will be null in this POJO
+        //but will be set later from mockSession
+        private const val msgId = "100"
+        private const val timeout = 5
+        private val deviceInfo: DeviceInfo = DeviceInfo().apply {
             username = "username"
             password = "password"
             ipAddress = "localhost"
             port = 2224
-            connectTimeout = 10
+            connectTimeout = 5
         }
-
-        device = NetconfDeviceSimulator(deviceInfo!!.port)
-        device!!.start()
     }
 
-    @After
-    fun after() {
-        device!!.stop()
+    @Before
+    fun setup() {
+        mockNetconfSession = mockk()
     }
 
     @Test
-    fun setNetconfSession() {
-
+    fun `invokeRpc completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val invokeRpcrResult = spy.invokeRpc(someString)
+        assertEquals(successfulDeviceResponse, invokeRpcrResult)
     }
 
     @Test
-    fun getConfig() {
-
-        val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!)
-        val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl)
-        netconfRpcServiceImpl.setNetconfSession(netconfSession)
-        netconfSession.connect()
-        Assert.assertTrue(netconfRpcServiceImpl.getConfig("filter","target").status.equals("failure"))
-    }
-
-
-    @Test
-    fun deleteConfig() {
-
-        val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!)
-        val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl)
-        netconfRpcServiceImpl.setNetconfSession(netconfSession)
-        netconfSession.connect()
-        Assert.assertTrue(netconfRpcServiceImpl.deleteConfig("target").status.equals("failure"))
+    fun `invokeRpc on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val invokeRpcrResult = spy.invokeRpc(someString)
+        assertEquals(failedDeviceResponse.status, invokeRpcrResult.status)
+        assertTrue { invokeRpcrResult.errorMessage!!.contains("failed in 'invokeRpc' command") }
     }
 
     @Test
-    fun lock() {
-        val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!)
-        val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl)
-        netconfRpcServiceImpl.setNetconfSession(netconfSession)
-        netconfSession.connect()
-        Assert.assertTrue(netconfRpcServiceImpl.lock("target").status.equals("failure"))
+    fun `getConfig completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val invokeRpcrResult = spy.getConfig(someString)
+        assertEquals(successfulDeviceResponse, invokeRpcrResult)
     }
 
     @Test
-    fun unLock() {
-        val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!)
-        val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl)
-        netconfRpcServiceImpl.setNetconfSession(netconfSession)
-        netconfSession.connect()
-        Assert.assertTrue(netconfRpcServiceImpl.unLock("target").status.equals("failure"))
+    fun `getConfig on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val getConfigRpcResult = spy.getConfig(someString)
+        assertEquals(failedDeviceResponse.status, getConfigRpcResult.status)
+        assertTrue { getConfigRpcResult.errorMessage!!.contains("failed in 'get-config' command") }
     }
 
     @Test
-    fun commit() {
-        val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!)
-        val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl)
-        netconfRpcServiceImpl.setNetconfSession(netconfSession)
-        netconfSession.connect()
-        Assert.assertTrue(netconfRpcServiceImpl.commit(true,60,"persist","1").status.equals("failure"))
-
+    fun `deleteConfig completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.deleteConfig(someString)
+        assertEquals(successfulDeviceResponse, rpcResult)
     }
 
     @Test
-    fun cancelCommit() {
-        val netconfSession = NetconfSessionImpl(deviceInfo!!, NetconfRpcServiceImpl(DeviceInfo()))
-        val netconfRpcServiceImpl = NetconfRpcServiceImpl(DeviceInfo())
-        netconfRpcServiceImpl.setNetconfSession(netconfSession)
-        netconfSession.connect()
-
-        Assert.assertNotNull(netconfRpcServiceImpl.cancelCommit("1"))
+    fun `deleteConfig on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val rpcResult = spy.deleteConfig(someString)
+        assertEquals(failedDeviceResponse.status, rpcResult.status)
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'delete-config' command") }
     }
 
     @Test
-    fun discardConfig() {
-        val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!)
-        val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl)
-        netconfRpcServiceImpl.setNetconfSession(netconfSession)
-        netconfSession.connect()
-        Assert.assertTrue(netconfRpcServiceImpl.discardConfig().status.equals("failure"))
-
+    fun `lock completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.lock(someString)
+        assertEquals(successfulDeviceResponse, rpcResult)
     }
 
     @Test
-    fun editConfig() {
+    fun `lock on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val rpcResult = spy.lock(someString)
+        assertEquals(failedDeviceResponse.status, rpcResult.status)
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'lock' command") }
     }
 
     @Test
-    fun validate() {
-        val netconfRpcServiceImpl = NetconfRpcServiceImpl(deviceInfo!!)
-        val netconfSession = NetconfSessionImpl(deviceInfo!!, netconfRpcServiceImpl)
-        netconfRpcServiceImpl.setNetconfSession(netconfSession)
-        netconfSession.connect()
-        Assert.assertTrue(netconfRpcServiceImpl.validate("target").status.equals("failure"))
-
+    fun `unLock completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.unLock(someString)
+        assertEquals(successfulDeviceResponse, rpcResult)
     }
 
+    @Test
+    fun `unLock on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val rpcResult = spy.unLock(someString)
+        assertEquals(failedDeviceResponse.status, rpcResult.status)
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'unLock' command") }
+    }
+
+    @Test
+    fun `commit completes normally on confirmed flag and only persist but not persistId specified`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.commit(true, timeout, persist = "blah", persistId = "")
+        assertEquals(successfulDeviceResponse, rpcResult)
+    }
+
+    @Test
+    fun `commit completes normally on no confirm flag and only persistId but not persist specified`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.commit(false, timeout, persistId = "blah")
+        assertEquals(successfulDeviceResponse, rpcResult)
+    }
+
+    @Test
+    fun `commit fails on confirm flag with persistId specified`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns failedDeviceResponse
+        val rpcResult = spy.commit(true, timeout, persistId = "blah")
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'commit' command") }
+    }
+
+    @Test
+    fun `commit fails on confirm flag with persist and persistId specified`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns failedDeviceResponse
+        val rpcResult = spy.commit(true, timeout, persist = "blah", persistId = "blah")
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'commit' command") }
+    }
+
+    @Test
+    fun `commit fails on no confirm flag with persist and persistId specified`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns failedDeviceResponse
+        val rpcResult = spy.commit(false, timeout, persist = "blah", persistId = "blah")
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'commit' command") }
+    }
+
+    @Test
+    fun `cancelCommit completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.cancelCommit(someString)
+        assertEquals(successfulDeviceResponse, rpcResult)
+    }
+
+    @Test
+    fun `cancelCommit on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val rpcResult = spy.cancelCommit(someString)
+        assertEquals(failedDeviceResponse.status, rpcResult.status)
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'cancelCommit' command") }
+    }
+
+    @Test
+    fun `discardConfig completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.discardConfig()
+        assertEquals(successfulDeviceResponse, rpcResult)
+    }
+
+    @Test
+    fun `discardConfig on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val rpcResult = spy.discardConfig()
+        assertEquals(failedDeviceResponse.status, rpcResult.status)
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'discard-config' command") }
+    }
+
+    @Test
+    fun `editConfig completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.editConfig("blah1", "blah2", "blah3")
+        assertEquals(successfulDeviceResponse, rpcResult)
+    }
+
+    @Test
+    fun `editConfig on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val rpcResult = spy.editConfig("blah1", "blah2", "blah3")
+        assertEquals(failedDeviceResponse.status, rpcResult.status)
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'editConfig' command") }
+    }
+
+    @Test
+    fun `validate completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.validate("blah1")
+        assertEquals(successfulDeviceResponse, rpcResult)
+    }
+
+    @Test
+    fun `validate on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val rpcResult = spy.validate("blah1")
+        assertEquals(failedDeviceResponse.status, rpcResult.status)
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'validate' command") }
+    }
+
+    @Test
+    fun `closeSession completes normally without force`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.closeSession(false)
+        assertEquals(successfulDeviceResponse, rpcResult)
+    }
+
+    @Test
+    fun `closeSession completes normally with force`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.closeSession(true)
+        assertEquals(successfulDeviceResponse, rpcResult)
+    }
+
+    @Test
+    fun `closeSession on error sets DeviceResponse status to FAILURE`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } throws IOException("Some IO exception...")
+        val rpcResult = spy.closeSession(true)
+        assertEquals(failedDeviceResponse.status, rpcResult.status)
+        assertTrue { rpcResult.errorMessage!!.contains("failed in 'closeSession' command") }
+    }
+
+    @Test
+    fun `asyncRpc completes normally`() {
+        val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+        netconfRpcService.setNetconfSession(mockNetconfSession)
+        val spy = spyk(netconfRpcService)
+        every { spy.asyncRpc(any(), any()) } returns successfulDeviceResponse
+        val rpcResult = spy.asyncRpc("blah1", "blah2")
+        assertEquals(successfulDeviceResponse, rpcResult)
+    }
+
+    @Test
+    fun `asyncRpc on error throws NetconfException`() {
+        assertFailsWith(exceptionClass = NetconfException::class) {
+            val netconfRpcService = NetconfRpcServiceImpl(deviceInfo)
+            netconfRpcService.setNetconfSession(mockNetconfSession)
+            val spy = spyk(netconfRpcService)
+            val erroneousFuture = CompletableFuture<String>()
+            erroneousFuture.complete("something something rpc-error>")
+            every { mockNetconfSession.asyncRpc(any(), any()) } returns erroneousFuture
+            val rpcResult = spy.asyncRpc("blah1", "blah2")
+            assertEquals(failedDeviceResponse.status, rpcResult.status)
+            assertTrue { rpcResult.errorMessage!!.contains("failed in 'closeSession' command") }
+        }
+    }
 }
\ No newline at end of file