Adding tests to NetconfMessageUtilsTest.kt 66/90966/2
authorRodrigo Ottero <rodrigo.ottero@est.tech>
Thu, 13 Jun 2019 13:53:24 +0000 (14:53 +0100)
committerEliezio Oliveira <eliezio.oliveira@est.tech>
Mon, 8 Jul 2019 10:27:20 +0000 (11:27 +0100)
Change-Id: If7a0d90ce264e7362e7118132303653eaaef9e69
Issue-ID: CCSDK-1046
Signed-off-by: Rodrigo Ottero <rodrigo.ottero@est.tech>
18 files changed:
ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtilsTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/cancelCommit-response-all-parameters-not-empty.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/cancelCommit-response-persistId-empty.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/closeSession-response-force-false.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/closeSession-response-force-true.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/commit-response-confirmed-false-and-persistId-empty-and-persist-not-empty.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/commit-response-confirmed-false-and-persistId-not-empty-and-persist-empty.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/commit-response-confirmed-true-and-persistId-empty-and-persist-empty.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/deleteConfig-response-all-parameters-not-empty.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/discardChanges-response-all-parameters-not-empty.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/doWrappedRpc-response.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/editConfig-response-all-parameters.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/editConfig-response-defaultOperation-null.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/getConfig-response-all-parameters.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/getConfig-response-filterContent-null.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/lock-response-all-parameters-not-empty.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/unlock-response-all-parameters-not-empty.xml [new file with mode: 0644]
ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/validate-response.xml [new file with mode: 0644]

diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtilsTest.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/utils/NetconfMessageUtilsTest.kt
new file mode 100644 (file)
index 0000000..e24659d
--- /dev/null
@@ -0,0 +1,179 @@
+package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.utils
+
+import org.junit.Assert.*
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.NetconfException
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import kotlin.test.Test
+import kotlin.test.assertFailsWith
+
+class NetconfMessageUtilsTest {
+
+    @Test
+    fun `test getConfig with all parameters present`() {
+        val outcome = NetconfMessageUtils.getConfig("customMessageId", "customConfigType", "customFilterContent")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/getConfig-response-all-parameters.xml")
+        assertEquals("getConfig return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test getConfig with filterContent parameter null`() {
+        val outcome = NetconfMessageUtils.getConfig("customMessageId", "customConfigType",null)
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/getConfig-response-filterContent-null.xml")
+        assertEquals("getConfig return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test doWrappedRpc`() {
+        val outcome = NetconfMessageUtils.doWrappedRpc("customMessageId", "customRequest")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/doWrappedRpc-response.xml")
+        assertEquals("doWrappedRpc return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test editConfig with all parameters present`() {
+        val outcome = NetconfMessageUtils.editConfig("customMessageId", "customConfigType", "customDefaultOperation",
+                "customNewConfiguration")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/editConfig-response-all-parameters.xml")
+        assertEquals("editConfig return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test editConfig with defaultOperation parameter null`() {
+        val outcome = NetconfMessageUtils.editConfig("customMessageId", "customConfigType", null,
+                "customNewConfiguration")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/editConfig-response-defaultOperation-null.xml")
+        assertEquals("editConfig return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test validate`() {
+        val outcome = NetconfMessageUtils.validate("customMessageId", "customConfigType")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/validate-response.xml")
+        assertEquals("validate return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test commit with both persistId and persist non-empty`() {
+        assertFailsWith(exceptionClass = NetconfException::class, message = "commit should have thrown an exception") {
+            NetconfMessageUtils.commit("customMessageId", false, 1, "customPersist", "customPersistId")
+        }
+    }
+
+    @Test
+    fun `test commit with confirmed true, persist empty and persistId non-empty`() {
+        assertFailsWith(exceptionClass = NetconfException::class, message = "commit should have thrown an exception") {
+            NetconfMessageUtils.commit("customMessageId", true, 1, "", "customPersistId")
+        }
+    }
+
+    @Test
+    fun `test commit with confirmed true, persistId empty and persist empty`() {
+        val outcome = NetconfMessageUtils.commit("customMessageId", true, 1, "", "")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/commit-response-confirmed-true-and-persistId-empty-and-persist-empty.xml")
+        assertEquals("commit return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test commit with confirmed false, persistId non-empty and persist empty`() {
+        val outcome = NetconfMessageUtils.commit("customMessageId", false, 1, "", "customPersistId")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/commit-response-confirmed-false-and-persistId-empty-and-persist-not-empty.xml")
+        assertEquals("commit return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test commit with confirmed false, persistId empty and persist non-empty`() {
+        val outcome = NetconfMessageUtils.commit("customMessageId", false, 1, "customPersist", "")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/commit-response-confirmed-false-and-persistId-not-empty-and-persist-empty.xml")
+        assertEquals("commit return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test cancelCommit with all parameters not empty`() {
+        val outcome = NetconfMessageUtils.cancelCommit("customMessageId", "customPersistId")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/cancelCommit-response-all-parameters-not-empty.xml")
+        assertEquals("cancelCommit return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test cancelCommit with persistId empty`() {
+        val outcome = NetconfMessageUtils.cancelCommit("customMessageId", "")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/cancelCommit-response-persistId-empty.xml")
+        assertEquals("cancelCommit return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test unlock with all parameters not empty`() {
+        val outcome = NetconfMessageUtils.unlock("customMessageId", "customConfigType")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/unlock-response-all-parameters-not-empty.xml")
+        assertEquals("unlock return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test deleteConfig with all parameters not empty`() {
+        val outcome = NetconfMessageUtils.deleteConfig("customMessageId", "customConfigType")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/deleteConfig-response-all-parameters-not-empty.xml")
+        assertEquals("deleteConfig return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test deleteConfig with configType equals to NetconfDatastore_RUNNING_datastore`() {
+        assertFailsWith(exceptionClass = NetconfException::class, message = "deleteConfig should have thrown an exception") {
+            NetconfMessageUtils.deleteConfig("customMessageId", NetconfDatastore.RUNNING.datastore)
+        }
+    }
+
+    @Test
+    fun `test discardChanges with all parameters not empty`() {
+        val outcome = NetconfMessageUtils.discardChanges("customMessageId")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/discardChanges-response-all-parameters-not-empty.xml")
+        assertEquals("discardChanges return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test lock with all parameters not empty`() {
+        val outcome = NetconfMessageUtils.lock("customMessageId", "customConfigType")
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/lock-response-all-parameters-not-empty.xml")
+        assertEquals("lock return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test closeSession with force true`() {
+        val outcome = NetconfMessageUtils.closeSession("customMessageId", true)
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/closeSession-response-force-true.xml")
+        assertEquals("closeSession return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test closeSession with force false`() {
+        val outcome = NetconfMessageUtils.closeSession("customMessageId", false)
+        val expectation = JacksonUtils.getClassPathFileContent("netconf-messages/closeSession-response-force-false.xml")
+        assertEquals("closeSession return was not correct", expectation, outcome)
+    }
+
+    //TODO validateRPCXML
+
+    @Test
+    fun `test getMsgId with valid message`() {
+        val messageId = "1234"
+        val outcome = NetconfMessageUtils.getMsgId("message-id=\"${messageId}\"")
+        val expectation = messageId
+        assertEquals("getMsgId return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test getMsgId with RpcMessageUtils_HELLO message`() {
+        val outcome = NetconfMessageUtils.getMsgId(RpcMessageUtils.HELLO)
+        val expectation = "-1"
+        assertEquals("getMsgId return was not correct", expectation, outcome)
+    }
+
+    @Test
+    fun `test getMsgId with invalid message`() {
+        val outcome = NetconfMessageUtils.getMsgId("invalid message")
+        val expectation = ""
+        assertEquals("getMsgId return was not correct", expectation, outcome)
+    }
+
+//TODO validateChunkedFraming
+
+}
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/cancelCommit-response-all-parameters-not-empty.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/cancelCommit-response-all-parameters-not-empty.xml
new file mode 100644 (file)
index 0000000..7f5a44c
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<cancel-commit>
+<persist-id>customPersistId</persist-id></cancel-commit>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/cancelCommit-response-persistId-empty.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/cancelCommit-response-persistId-empty.xml
new file mode 100644 (file)
index 0000000..5ffaf6f
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<cancel-commit>
+</cancel-commit>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/closeSession-response-force-false.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/closeSession-response-force-false.xml
new file mode 100644 (file)
index 0000000..282097b
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<close-session/>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/closeSession-response-force-true.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/closeSession-response-force-true.xml
new file mode 100644 (file)
index 0000000..01a28d9
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<kill-session/>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/commit-response-confirmed-false-and-persistId-empty-and-persist-not-empty.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/commit-response-confirmed-false-and-persistId-empty-and-persist-not-empty.xml
new file mode 100644 (file)
index 0000000..d19e5b4
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<commit>
+<persist-id>customPersistId</persist-id></commit>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/commit-response-confirmed-false-and-persistId-not-empty-and-persist-empty.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/commit-response-confirmed-false-and-persistId-not-empty-and-persist-empty.xml
new file mode 100644 (file)
index 0000000..ac489b7
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<commit>
+</commit>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/commit-response-confirmed-true-and-persistId-empty-and-persist-empty.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/commit-response-confirmed-true-and-persistId-empty-and-persist-empty.xml
new file mode 100644 (file)
index 0000000..ad0fef8
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<commit>
+<confirmed/><confirm-timeout>1</confirm-timeout></commit>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/deleteConfig-response-all-parameters-not-empty.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/deleteConfig-response-all-parameters-not-empty.xml
new file mode 100644 (file)
index 0000000..1758bde
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<delete-config>
+<target>
+<customConfigType/>
+</target>
+</delete-config>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/discardChanges-response-all-parameters-not-empty.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/discardChanges-response-all-parameters-not-empty.xml
new file mode 100644 (file)
index 0000000..3559dd9
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<discard-changes/>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/doWrappedRpc-response.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/doWrappedRpc-response.xml
new file mode 100644 (file)
index 0000000..0f6c3e7
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+customRequest</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/editConfig-response-all-parameters.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/editConfig-response-all-parameters.xml
new file mode 100644 (file)
index 0000000..f4a789f
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<edit-config>
+<target>
+<customConfigType/>
+</target>
+<default-operation>customDefaultOperation</default-operation>
+<config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+customNewConfiguration
+</config>
+</edit-config>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/editConfig-response-defaultOperation-null.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/editConfig-response-defaultOperation-null.xml
new file mode 100644 (file)
index 0000000..8efa46e
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<edit-config>
+<target>
+<customConfigType/>
+</target>
+<config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+customNewConfiguration
+</config>
+</edit-config>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/getConfig-response-all-parameters.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/getConfig-response-all-parameters.xml
new file mode 100644 (file)
index 0000000..4135c16
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<get-config>
+<source>
+<customConfigType/>
+</source>
+<filter type="subtree">
+customFilterContent
+</filter>
+</get-config>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/getConfig-response-filterContent-null.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/getConfig-response-filterContent-null.xml
new file mode 100644 (file)
index 0000000..dee7519
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<get-config>
+<source>
+<customConfigType/>
+</source>
+</get-config>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/lock-response-all-parameters-not-empty.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/lock-response-all-parameters-not-empty.xml
new file mode 100644 (file)
index 0000000..1329e37
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<lock>
+<target>
+<customConfigType/>
+</target>
+</lock>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/unlock-response-all-parameters-not-empty.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/unlock-response-all-parameters-not-empty.xml
new file mode 100644 (file)
index 0000000..35a07f7
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<unlock>
+<target>
+<customConfigType/>
+</target>
+</unlock>
+</rpc>
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/validate-response.xml b/ms/blueprintsprocessor/functions/netconf-executor/src/test/resources/netconf-messages/validate-response.xml
new file mode 100644 (file)
index 0000000..3947be6
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rpc message-id="customMessageId" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+<validate>
+<source>
+<customConfigType/>
+</source>
+</validate>
+</rpc>
\ No newline at end of file