Merge "netconf-executor tests: adding MessageStateTests"
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt
index cfdd010..23982dc 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/api/NetconfSessionListener.kt
@@ -16,6 +16,5 @@
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api
 
 interface NetconfSessionListener {
-
-    fun notify(event: NetconfReceivedEvent)
+    fun accept(event: NetconfReceivedEvent)
 }
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt
index 4199998..12e3b83 100644
--- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfDeviceCommunicator.kt
@@ -57,11 +57,7 @@
                 val cInt = bufferReader.read()
                 if (cInt == -1) {
                     log.error("$deviceInfo: Received cInt = -1")
-//                    bufferReader.close()
                     socketClosed = true
-//                    sessionListener.notify(NetconfReceivedEvent(
-//                        NetconfReceivedEvent.Type.SESSION_CLOSED,
-//                        deviceInfo = deviceInfo))
                 }
                 val c = cInt.toChar()
                 state = state.evaluateChar(c)
@@ -71,7 +67,7 @@
                     if (deviceReply == RpcMessageUtils.END_PATTERN) {
                         socketClosed = true
                         bufferReader.close()
-                        sessionListener.notify(NetconfReceivedEvent(
+                        sessionListener.accept(NetconfReceivedEvent(
                             NetconfReceivedEvent.Type.DEVICE_UNREGISTERED,
                             deviceInfo = deviceInfo))
                     } else {
@@ -84,7 +80,7 @@
                     if (!NetconfMessageUtils.validateChunkedFraming(deviceReply)) {
                         log.debug("$deviceInfo: Received badly framed message $deviceReply")
                         socketClosed = true
-                        sessionListener.notify(NetconfReceivedEvent(
+                        sessionListener.accept(NetconfReceivedEvent(
                             NetconfReceivedEvent.Type.DEVICE_ERROR,
                             deviceInfo = deviceInfo))
                     } else {
@@ -98,98 +94,89 @@
 
         } catch (e: IOException) {
             log.warn("$deviceInfo: Fail while reading from channel", e)
-            sessionListener.notify(NetconfReceivedEvent(
+            sessionListener.accept(NetconfReceivedEvent(
                 NetconfReceivedEvent.Type.DEVICE_ERROR,
                 deviceInfo = deviceInfo))
         }
 
     }
 
-    private enum class NetconfMessageState {
+    /**
+     * State machine for the Netconf message parser
+     */
+    internal enum class NetconfMessageState {
         NO_MATCHING_PATTERN {
             override fun evaluateChar(c: Char): NetconfMessageState {
-                return if (c == ']') {
-                    FIRST_BRACKET
-                } else if (c == '\n') {
-                    FIRST_LF
-                } else {
-                    this
+                return when (c) {
+                    ']' -> FIRST_BRACKET
+                    '\n' -> FIRST_LF
+                    else -> this
                 }
             }
         },
         FIRST_BRACKET {
             override fun evaluateChar(c: Char): NetconfMessageState {
-                return if (c == ']') {
-                    SECOND_BRACKET
-                } else {
-                    NO_MATCHING_PATTERN
+                return when (c) {
+                    ']' -> SECOND_BRACKET
+                    else -> NO_MATCHING_PATTERN
                 }
             }
         },
         SECOND_BRACKET {
             override fun evaluateChar(c: Char): NetconfMessageState {
-                return if (c == '>') {
-                    FIRST_BIGGER
-                } else {
-                    NO_MATCHING_PATTERN
+                return when (c) {
+                    '>' -> FIRST_BIGGER
+                    else -> NO_MATCHING_PATTERN
                 }
             }
         },
         FIRST_BIGGER {
             override fun evaluateChar(c: Char): NetconfMessageState {
-                return if (c == ']') {
-                    THIRD_BRACKET
-                } else {
-                    NO_MATCHING_PATTERN
+                return when (c) {
+                    ']' -> THIRD_BRACKET
+                    else -> NO_MATCHING_PATTERN
                 }
             }
         },
         THIRD_BRACKET {
             override fun evaluateChar(c: Char): NetconfMessageState {
-                return if (c == ']') {
-                    ENDING_BIGGER
-                } else {
-                    NO_MATCHING_PATTERN
+                return when (c) {
+                    ']' -> ENDING_BIGGER
+                    else -> NO_MATCHING_PATTERN
                 }
             }
         },
         ENDING_BIGGER {
             override fun evaluateChar(c: Char): NetconfMessageState {
-                return if (c == '>') {
-                    END_PATTERN
-                } else {
-                    NO_MATCHING_PATTERN
+                return when (c) {
+                    '>' -> END_PATTERN
+                    else -> NO_MATCHING_PATTERN
                 }
             }
         },
         FIRST_LF {
             override fun evaluateChar(c: Char): NetconfMessageState {
-                return if (c == '#') {
-                    FIRST_HASH
-                } else if (c == ']') {
-                    FIRST_BRACKET
-                } else if (c == '\n') {
-                    this
-                } else {
-                    NO_MATCHING_PATTERN
+                return when (c) {
+                    '#' -> FIRST_HASH
+                    ']' -> FIRST_BRACKET
+                    '\n' -> this
+                    else -> NO_MATCHING_PATTERN
                 }
             }
         },
         FIRST_HASH {
             override fun evaluateChar(c: Char): NetconfMessageState {
-                return if (c == '#') {
-                    SECOND_HASH
-                } else {
-                    NO_MATCHING_PATTERN
+                return when (c) {
+                    '#' -> SECOND_HASH
+                    else -> NO_MATCHING_PATTERN
                 }
             }
         },
         SECOND_HASH {
             override fun evaluateChar(c: Char): NetconfMessageState {
-                return if (c == '\n') {
-                    END_CHUNKED_PATTERN
-                } else {
-                    NO_MATCHING_PATTERN
+                return when (c) {
+                    '\n' -> END_CHUNKED_PATTERN
+                    else -> NO_MATCHING_PATTERN
                 }
             }
         },
@@ -204,6 +191,11 @@
             }
         };
 
+        /**
+         * Evaluate next transition state based on current state and the character read
+         * @param c character read in
+         * @return result of lookup of transition to the next {@link NetconfMessageState}
+         */
         internal abstract fun evaluateChar(c: Char): NetconfMessageState
     }
 
@@ -234,7 +226,7 @@
         } else {
             log.error("$deviceInfo: Invalid message received: \n $deviceReply")
         }
-        sessionListener.notify(NetconfReceivedEvent(
+        sessionListener.accept(NetconfReceivedEvent(
             NetconfReceivedEvent.Type.DEVICE_REPLY,
             deviceReply,
             NetconfMessageUtils.getMsgId(deviceReply),
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 ae4d844..d0f4a1d 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
@@ -263,7 +263,7 @@
     }
 
     inner class NetconfSessionListenerImpl : NetconfSessionListener {
-        override fun notify(event: NetconfReceivedEvent) {
+        override fun accept(event: NetconfReceivedEvent) {
             val messageId = event.messageId
 
             when (event.type) {
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfMessageStateTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfMessageStateTest.kt
new file mode 100644
index 0000000..95148dd
--- /dev/null
+++ b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/core/NetconfMessageStateTest.kt
@@ -0,0 +1,146 @@
+/*
+ * 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.Test
+import kotlin.test.assertEquals
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.core.NetconfDeviceCommunicator.NetconfMessageState
+class NetconfMessageStateTest {
+
+    private val charList: List<Char> = Char.MIN_VALUE.toInt().rangeTo(Char.MAX_VALUE.toInt())
+        .map { it -> it.toChar() }
+
+    @Test
+    fun `NO_MATCHING_PATTERN transitions`() {
+        assertEquals(NetconfMessageState.FIRST_BRACKET,
+            NetconfMessageState.NO_MATCHING_PATTERN.evaluateChar(']'))
+        assertEquals(NetconfMessageState.FIRST_LF,
+            NetconfMessageState.NO_MATCHING_PATTERN.evaluateChar('\n'))
+
+        charList.minus(listOf(']','\n')).forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.NO_MATCHING_PATTERN.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `FIRST_BRACKET transitions`() {
+        assertEquals(NetconfMessageState.SECOND_BRACKET,
+            NetconfMessageState.FIRST_BRACKET.evaluateChar(']'))
+
+        charList.minus( ']').forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.FIRST_BRACKET.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `SECOND_BRACKET transitions`() {
+        assertEquals(NetconfMessageState.FIRST_BIGGER,
+            NetconfMessageState.SECOND_BRACKET.evaluateChar('>'))
+
+        charList.minus('>').forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.SECOND_BRACKET.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `FIRST_BIGGER transitions`() {
+        assertEquals(NetconfMessageState.THIRD_BRACKET,
+            NetconfMessageState.FIRST_BIGGER.evaluateChar(']'))
+
+        charList.minus(']').forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.FIRST_BIGGER.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `THIRD_BRACKET transitions`() {
+        assertEquals(NetconfMessageState.ENDING_BIGGER,
+            NetconfMessageState.THIRD_BRACKET.evaluateChar(']'))
+
+        charList.minus(']').forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.THIRD_BRACKET.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `ENDING_BIGGER transitions`() {
+        assertEquals(NetconfMessageState.END_PATTERN,
+            NetconfMessageState.ENDING_BIGGER.evaluateChar('>'))
+
+        charList.minus('>').forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.ENDING_BIGGER.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `FIRST_LF transitions`() {
+        assertEquals(NetconfMessageState.FIRST_HASH,
+            NetconfMessageState.FIRST_LF.evaluateChar('#'))
+        assertEquals(NetconfMessageState.FIRST_BRACKET,
+            NetconfMessageState.FIRST_LF.evaluateChar(']'))
+        assertEquals(NetconfMessageState.FIRST_LF,
+            NetconfMessageState.FIRST_LF.evaluateChar('\n'))
+        charList.minus(listOf('#', ']', '\n')).forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.FIRST_LF.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `FIRST_HASH transitions`() {
+        assertEquals(NetconfMessageState.SECOND_HASH,
+            NetconfMessageState.FIRST_HASH.evaluateChar('#'))
+        charList.minus('#').forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.FIRST_HASH.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `SECOND_HASH transitions`() {
+        assertEquals(NetconfMessageState.END_CHUNKED_PATTERN,
+            NetconfMessageState.SECOND_HASH.evaluateChar('\n'))
+
+        charList.minus( '\n').forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.SECOND_HASH.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `END_CHUNKED_PATTERN transitions`() {
+        charList.forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.END_CHUNKED_PATTERN.evaluateChar(it))
+        }
+    }
+
+    @Test
+    fun `END_PATTERN transitions`() {
+        charList.forEach {
+            assertEquals(NetconfMessageState.NO_MATCHING_PATTERN,
+                NetconfMessageState.END_PATTERN.evaluateChar(it))
+        }
+    }
+
+}
\ No newline at end of file