Added JSON config file format utils 09/79309/10
authorpbiniek <pawel.biniek@nokia.com>
Wed, 27 Feb 2019 22:31:15 +0000 (23:31 +0100)
committerpbiniek <pawel.biniek@nokia.com>
Mon, 11 Mar 2019 11:43:48 +0000 (12:43 +0100)
Change-Id: I97fdd72324495b4c838e44c306cbcacac6b11bc1
Signed-off-by: Pawel Biniek <pawel.biniek@nokia.com>
Issue-ID: DCAEGEN2-1323

12 files changed:
pom.xml
sources/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/model/routing.kt
sources/hv-collector-main/pom.xml
sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/ConfigFactory.kt [new file with mode: 0644]
sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/PartialConfiguration.kt [new file with mode: 0644]
sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/AddressAdapter.kt [new file with mode: 0644]
sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/OptionAdapter.kt [new file with mode: 0644]
sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/RouteAdapter.kt [new file with mode: 0644]
sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/RoutingAdapter.kt [new file with mode: 0644]
sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/SecurityKeysAdapter.kt [new file with mode: 0644]
sources/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ConfigFactoryTest.kt [new file with mode: 0644]
sources/hv-collector-main/src/test/resources/sampleConfig.json [new file with mode: 0644]

diff --git a/pom.xml b/pom.xml
index c769dcc..7d11f03 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -65,6 +65,7 @@
         <junit-platform.version>1.2.0-RC1</junit-platform.version>
         <junit-jupiter.version>5.2.0-RC1</junit-jupiter.version>
         <spek.version>1.1.5</spek.version>
+        <gson.version>2.8.5</gson.version>
         <maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>
         <failIfMissingUnitTests>false</failIfMissingUnitTests>
         <failIfMissingComponentTests>false</failIfMissingComponentTests>
                 <artifactId>kotlinx-coroutines-core</artifactId>
                 <version>1.0.0</version>
             </dependency>
+            <dependency>
+                <groupId>com.google.code.gson</groupId>
+                <artifactId>gson</artifactId>
+                <version>${gson.version}</version>
+            </dependency>
             <dependency>
                 <groupId>io.arrow-kt</groupId>
                 <artifactId>arrow-core</artifactId>
index ad97a3f..dc7db5a 100644 (file)
@@ -29,7 +29,7 @@ data class Routing(val routes: List<Route>) {
             Option.fromNullable(routes.find { it.applies(commonHeader) })
 }
 
-data class Route(val domain: String, val targetTopic: String, val partitioning: (CommonEventHeader) -> Int) {
+data class Route(val domain: String, val targetTopic: String, val partitioning: (CommonEventHeader) -> Int = {0}) {
 
     fun applies(commonHeader: CommonEventHeader) = commonHeader.domain == domain
 
@@ -67,15 +67,15 @@ class RouteBuilder {
     private lateinit var targetTopic: String
     private lateinit var partitioning: (CommonEventHeader) -> Int
 
-    fun fromDomain(domain: String) {
+    fun fromDomain(domain: String) : RouteBuilder = apply {
         this.domain = domain
     }
 
-    fun toTopic(targetTopic: String) {
+    fun toTopic(targetTopic: String) : RouteBuilder = apply {
         this.targetTopic = targetTopic
     }
 
-    fun withFixedPartitioning(num: Int = 0) {
+    fun withFixedPartitioning(num: Int = 0) : RouteBuilder = apply {
         partitioning = { num }
     }
 
index d08a21e..bc3039b 100644 (file)
             <groupId>io.micrometer</groupId>
             <artifactId>micrometer-registry-prometheus</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
     </dependencies>
 
 
diff --git a/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/ConfigFactory.kt b/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/ConfigFactory.kt
new file mode 100644 (file)
index 0000000..2262b6f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.main.config
+
+import arrow.core.Option
+import com.google.gson.GsonBuilder
+import org.onap.dcae.collectors.veshv.main.config.adapters.*
+import org.onap.dcae.collectors.veshv.model.Route
+import org.onap.dcae.collectors.veshv.model.Routing
+import org.onap.dcaegen2.services.sdk.security.ssl.SecurityKeys
+import java.io.Reader
+import java.net.InetSocketAddress
+
+/**
+ * @author Pawel Biniek <pawel.biniek@nokia.com>
+ * @since February 2019
+ */
+class ConfigFactory {
+    private val gson = GsonBuilder()
+            .registerTypeAdapter(InetSocketAddress::class.java, AddressAdapter())
+            .registerTypeAdapter(Route::class.java, RouteAdapter())
+            .registerTypeAdapter(Routing::class.java, RoutingAdapter())
+            .registerTypeAdapter(Option::class.java, OptionAdapter())
+            .registerTypeAdapter(SecurityKeys::class.java, SecurityKeysAdapter())
+            .create()
+
+    fun loadConfig(input: Reader): PartialConfiguration =
+        gson.fromJson(input, PartialConfiguration::class.java)
+}
diff --git a/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/PartialConfiguration.kt b/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/PartialConfiguration.kt
new file mode 100644 (file)
index 0000000..1bccc21
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.main.config
+
+import arrow.core.Option
+import org.onap.dcae.collectors.veshv.model.Routing
+import org.onap.dcae.collectors.veshv.utils.logging.LogLevel
+import org.onap.dcaegen2.services.sdk.security.ssl.SecurityKeys
+import java.net.InetSocketAddress
+
+/**
+ * @author Pawel Biniek <pawel.biniek@nokia.com>
+ * @since February 2019
+ */
+data class PartialConfiguration(
+        val server : Option<PartialServerConfig>,
+        val cbs : Option<PartialCbsConfig>,
+        val security : Option<PartialSecurityConfig>,
+        val kafka : Option<PartialKafkaConfig>,
+        val logLevel : Option<LogLevel>
+)
+data class PartialSecurityConfig(
+        val sslDisable : Option<Boolean>,
+        val keys : Option<SecurityKeys>)
+
+data class PartialCbsConfig(
+        val firstRequestDelaySec : Option<Int>,
+        val requestIntervalSec : Option<Int>
+)
+
+data class PartialServerConfig(
+        val healthCheckApiPort : Option<Int>,
+        val listenPort : Option<Int>,
+        val idleTimeoutSec : Option<Int>,
+        val maximumPayloadSizeBytes : Option<Int>,
+        val dummyMode : Option<Boolean>
+)
+
+data class PartialKafkaConfig(
+    val kafkaServers : Option<Array<InetSocketAddress>>,
+    val routing : Option<Routing>
+)
diff --git a/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/AddressAdapter.kt b/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/AddressAdapter.kt
new file mode 100644 (file)
index 0000000..6e616f5
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.main.config.adapters
+
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonDeserializer
+import com.google.gson.JsonElement
+import java.lang.reflect.Type
+import java.net.InetSocketAddress
+
+
+/**
+ * @author Pawel Biniek <pawel.biniek@nokia.com>
+ * @since February 2019
+ */
+class AddressAdapter : JsonDeserializer<InetSocketAddress> {
+    override fun deserialize(
+            json: JsonElement,
+            typeOfT: Type,
+            context: JsonDeserializationContext?): InetSocketAddress
+        {
+            val portStart = json.asString.lastIndexOf(":")
+            if (portStart > 0) {
+                val address = json.asString.substring(0, portStart)
+                val port = json.asString.substring(portStart + 1)
+                return InetSocketAddress(address, port.toInt())
+            } else throw InvalidAddressException("Cannot parse '" + json.asString + "' to address")
+        }
+
+    class InvalidAddressException(reason:String) : RuntimeException(reason)
+}
+
+
diff --git a/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/OptionAdapter.kt b/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/OptionAdapter.kt
new file mode 100644 (file)
index 0000000..62d107a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.main.config.adapters
+
+import arrow.core.Option
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonDeserializer
+import com.google.gson.JsonElement
+import java.lang.reflect.ParameterizedType
+import java.lang.reflect.Type
+
+/**
+ * @author Pawel Biniek <pawel.biniek@nokia.com>
+ * @since March 2019
+ */
+class OptionAdapter : JsonDeserializer<Option<Any>> {
+    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Option<Any> {
+        val parametrizedType = typeOfT as ParameterizedType
+        val typeParameter = parametrizedType.actualTypeArguments.first()
+        return Option.fromNullable(context.deserialize<Any>(json, typeParameter))
+    }
+
+}
diff --git a/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/RouteAdapter.kt b/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/RouteAdapter.kt
new file mode 100644 (file)
index 0000000..a617abc
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.main.config.adapters
+
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonDeserializer
+import com.google.gson.JsonElement
+import org.onap.dcae.collectors.veshv.model.Route
+import org.onap.dcae.collectors.veshv.model.RouteBuilder
+import java.lang.reflect.Type
+
+/**
+ * @author Pawel Biniek <pawel.biniek@nokia.com>
+ * @since March 2019
+ */
+class RouteAdapter : JsonDeserializer<Route> {
+    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext?): Route {
+        val jobj = json.asJsonObject
+        return RouteBuilder()
+                .fromDomain(jobj["fromDomain"].asString)
+                .toTopic(jobj["toTopic"].asString)
+                .withFixedPartitioning()
+                .build()
+    }
+
+}
diff --git a/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/RoutingAdapter.kt b/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/RoutingAdapter.kt
new file mode 100644 (file)
index 0000000..d0c5ff3
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.main.config.adapters
+
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonDeserializer
+import com.google.gson.JsonElement
+import com.google.gson.reflect.TypeToken
+import org.onap.dcae.collectors.veshv.model.Route
+import org.onap.dcae.collectors.veshv.model.Routing
+import java.lang.reflect.Type
+
+/**
+ * @author Pawel Biniek <pawel.biniek@nokia.com>
+ * @since March 2019
+ */
+class RoutingAdapter : JsonDeserializer<Routing> {
+    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Routing {
+        val parametrizedType = TypeToken.getParameterized(List::class.java, Route::class.java).type
+        return Routing(context.deserialize<List<Route>>(json, parametrizedType))
+    }
+
+}
diff --git a/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/SecurityKeysAdapter.kt b/sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/config/adapters/SecurityKeysAdapter.kt
new file mode 100644 (file)
index 0000000..7c22e0f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.main.config.adapters
+
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonDeserializer
+import com.google.gson.JsonElement
+import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeys
+import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeysStore
+import org.onap.dcaegen2.services.sdk.security.ssl.Passwords
+import org.onap.dcaegen2.services.sdk.security.ssl.SecurityKeys
+import java.io.File
+import java.lang.reflect.Type
+
+/**
+ * @author Pawel Biniek <pawel.biniek@nokia.com>
+ * @since March 2019
+ */
+class SecurityKeysAdapter : JsonDeserializer<SecurityKeys> {
+    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext?): SecurityKeys {
+        val obj = json.asJsonObject
+        return ImmutableSecurityKeys.builder()
+                .keyStore(ImmutableSecurityKeysStore.of(
+                        File(obj["keyStoreFile"].asString).toPath()))
+                .keyStorePassword(
+                        Passwords.fromString(obj["keyStorePassword"].asString))
+                .trustStore(ImmutableSecurityKeysStore.of(
+                        File(obj["trustStoreFile"].asString).toPath()))
+                .trustStorePassword(
+                        Passwords.fromString(obj["trustStorePassword"].asString))
+                .build()
+    }
+
+}
diff --git a/sources/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ConfigFactoryTest.kt b/sources/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ConfigFactoryTest.kt
new file mode 100644 (file)
index 0000000..c384923
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.main
+
+import arrow.core.Some
+import org.jetbrains.spek.api.Spek
+import org.assertj.core.api.Assertions.assertThat
+import org.jetbrains.spek.api.dsl.describe
+import org.jetbrains.spek.api.dsl.it
+import org.onap.dcae.collectors.veshv.main.config.*
+import org.onap.dcae.collectors.veshv.model.Routing
+import org.onap.dcae.collectors.veshv.utils.logging.LogLevel
+import java.io.InputStreamReader
+import java.io.StringReader
+import java.net.InetSocketAddress
+
+/**
+ * @author Pawel Biniek <pawel.biniek@nokia.com>
+ * @since February 2019
+ */
+internal object ConfigFactoryTest : Spek({
+    describe("A configuration loader utility") {
+
+        describe("partial configuration loading") {
+            it("parses enumerations") {
+                val input = """{"logLevel":"ERROR"}"""
+
+                val config = ConfigFactory().loadConfig(StringReader(input))
+                assertThat(config.logLevel).isEqualTo(Some(LogLevel.ERROR))
+            }
+
+            it("parses simple structure") {
+                val input = """{
+                "server" : {
+                    "healthCheckApiPort" : 12002,
+                    "listenPort" : 12003
+                }
+            }
+            """.trimIndent()
+                val config = ConfigFactory().loadConfig(StringReader(input))
+                assertThat(config.server.nonEmpty()).isTrue()
+                assertThat(config.server.orNull()?.healthCheckApiPort).isEqualTo(Some(12002))
+                assertThat(config.server.orNull()?.listenPort).isEqualTo(Some(12003))
+            }
+
+            it("parses ip address") {
+                val input = """{  "kafka" : {
+                    "kafkaServers": [
+                      "192.168.255.1:5005",
+                      "192.168.255.26:5006"
+                    ]
+                  }
+                }"""
+
+                val config = ConfigFactory().loadConfig(StringReader(input))
+                assertThat(config.kafka.nonEmpty()).isTrue()
+                val kafka = config.kafka.orNull() as PartialKafkaConfig
+                assertThat(kafka.kafkaServers.nonEmpty()).isTrue()
+                val addresses = kafka.kafkaServers.orNull() as Array<InetSocketAddress>
+                assertThat(addresses)
+                        .isEqualTo(arrayOf(
+                                InetSocketAddress("192.168.255.1", 5005),
+                                InetSocketAddress("192.168.255.26", 5006)
+                        ))
+            }
+
+            it("parses routing array with RoutingAdapter") {
+                val input = """{
+                    "kafka" : {
+                        "routing" : [
+                            {
+                              "fromDomain": "perf3gpp",
+                              "toTopic": "HV_VES_PERF3GPP"
+                            }
+                        ]
+                    }
+                }""".trimIndent()
+                val config = ConfigFactory().loadConfig(StringReader(input))
+                assertThat(config.kafka.nonEmpty()).isTrue()
+                val kafka = config.kafka.orNull() as PartialKafkaConfig
+                assertThat(kafka.routing.nonEmpty()).isTrue()
+                val routing = kafka.routing.orNull() as Routing
+                routing.run {
+                    assertThat(routes.size).isEqualTo(1)
+                    assertThat(routes[0].domain).isEqualTo("perf3gpp")
+                    assertThat(routes[0].targetTopic).isEqualTo("HV_VES_PERF3GPP")
+                }
+            }
+        }
+
+        describe("complete file loading") {
+            it("loads actual file") {
+                val config = ConfigFactory().loadConfig(
+                        InputStreamReader(
+                                ConfigFactoryTest.javaClass.getResourceAsStream("/sampleConfig.json")))
+                assertThat(config).isNotNull
+                assertThat(config.logLevel).isEqualTo(Some(LogLevel.ERROR))
+
+                assertThat(config.security.nonEmpty()).isTrue()
+                val security = config.security.orNull() as PartialSecurityConfig
+                assertThat(security.sslDisable.orNull()).isFalse()
+                assertThat(security.keys.nonEmpty()).isTrue()
+
+                assertThat(config.cbs.nonEmpty()).isTrue()
+                val cbs = config.cbs.orNull() as PartialCbsConfig
+                assertThat(cbs.firstRequestDelaySec).isEqualTo(Some(7))
+                assertThat(cbs.requestIntervalSec).isEqualTo(Some(900))
+
+                assertThat(config.kafka.nonEmpty()).isTrue()
+                val kafka = config.kafka.orNull() as PartialKafkaConfig
+                assertThat(kafka.kafkaServers.nonEmpty()).isTrue()
+                assertThat(kafka.routing.nonEmpty()).isTrue()
+
+                assertThat(config.server.nonEmpty()).isTrue()
+                val server = config.server.orNull() as PartialServerConfig
+                server.run {
+                    assertThat(dummyMode).isEqualTo(Some(false))
+                    assertThat(healthCheckApiPort).isEqualTo(Some(5000))
+                    assertThat(idleTimeoutSec).isEqualTo(Some(1200))
+                    assertThat(listenPort).isEqualTo(Some(6000))
+                    assertThat(maximumPayloadSizeBytes).isEqualTo(Some(512000))
+                }
+            }
+        }
+    }
+})
\ No newline at end of file
diff --git a/sources/hv-collector-main/src/test/resources/sampleConfig.json b/sources/hv-collector-main/src/test/resources/sampleConfig.json
new file mode 100644 (file)
index 0000000..b64df05
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "server" : {
+    "healthCheckApiPort" : 5000,
+    "listenPort" : 6000,
+    "idleTimeoutSec" : 1200,
+    "maximumPayloadSizeBytes" : 512000,
+    "dummyMode" : false
+  },
+  "cbs" : {
+    "firstRequestDelaySec": 7,
+    "requestIntervalSec": 900
+  },
+  "security" : {
+    "sslDisable": false,
+    "keys": {
+      "keyStoreFile": "test.ks.pkcs12",
+      "keyStorePassword": "changeMe",
+      "trustStoreFile": "trust.ks.pkcs12",
+      "trustStorePassword": "changeMeToo"
+    }
+  },
+  "kafka" : {
+    "kafkaServers": [
+      "192.168.255.1:5005",
+      "192.168.255.1:5006"
+    ],
+    "routing": [
+      {
+        "fromDomain": "perf3gpp",
+        "toTopic": "HV_VES_PERF3GPP"
+      }
+    ]
+  },
+  "logLevel" : "ERROR"
+}
\ No newline at end of file