aboutsummaryrefslogtreecommitdiffstats
path: root/ms/blueprintsprocessor/application/src/test/kotlin
diff options
context:
space:
mode:
authorSingal, Kapil (ks220y) <ks220y@att.com>2020-01-10 15:16:15 -0500
committerSingal, Kapil (ks220y) <ks220y@att.com>2020-01-12 18:34:12 -0500
commitd57c3727ee2d02e2b2f4c899647d4d9de7e72b43 (patch)
tree05736890a322f59f32a0e50b347633dfe1e3d29a /ms/blueprintsprocessor/application/src/test/kotlin
parent4786e0b9ef3b4b82f4ad14bcffafa222628011d6 (diff)
Refactoring Pom and Fixing Junits
Refactoring DepeendencyManagement section in parent pom and fixed Junit failing over Windows Issue-ID: CCSDK-2023 Signed-off-by: Singal, Kapil (ks220y) <ks220y@att.com> Change-Id: I5e09c4c6d6307c1dd93a40ab3601713b956dfc72
Diffstat (limited to 'ms/blueprintsprocessor/application/src/test/kotlin')
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BaseUatTest.kt2
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BlueprintsAcceptanceTest.kt2
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt4
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt24
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt45
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt65
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/SmartColorDiscriminator.kt41
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/ExtendedTemporaryFolder.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/ExtendedTemporaryFolder.kt)2
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt84
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/MarkedSlf4jNotifier.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/MarkedSlf4jNotifier.kt)2
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt52
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt34
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/TestSecuritySettings.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/TestSecuritySettings.kt)2
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt102
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt359
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt125
-rw-r--r--ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/WorkingFoldersInitializer.kt (renamed from ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/WorkingFoldersInitializer.kt)4
17 files changed, 944 insertions, 5 deletions
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BaseUatTest.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BaseUatTest.kt
index 0ff5dc55d..7f38608c9 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BaseUatTest.kt
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BaseUatTest.kt
@@ -23,6 +23,8 @@ import org.junit.runner.RunWith
import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.COLOR_TEST_CLIENT
import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.resetContextColor
import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.setContextColor
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.TestSecuritySettings
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.WorkingFoldersInitializer
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.TestPropertySource
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BlueprintsAcceptanceTest.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BlueprintsAcceptanceTest.kt
index ad97ce82a..ff7cd78c0 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BlueprintsAcceptanceTest.kt
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/BlueprintsAcceptanceTest.kt
@@ -24,6 +24,8 @@ import org.junit.ClassRule
import org.junit.Rule
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.ExtendedTemporaryFolder
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.UatExecutor
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.UAT_SPECIFICATION_FILE
import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintArchiveUtils.Companion.compressToBytes
import org.springframework.beans.factory.annotation.Autowired
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt
index 2df5f2940..688ba663c 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt
@@ -44,6 +44,10 @@ import org.hamcrest.Matchers.equalToIgnoringCase
import org.jetbrains.kotlin.konan.util.prefixIfNot
import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.COLOR_WIREMOCK
import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.markerOf
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.MarkedSlf4jNotifier
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.ServiceDefinition
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.TestSecuritySettings
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.UatDefinition
import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.UAT_SPECIFICATION_FILE
import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintArchiveUtils.Companion.compressToBytes
import org.skyscreamer.jsonassert.JSONAssert
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt
new file mode 100644
index 000000000..9ae3ff805
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/ColorMarker.kt
@@ -0,0 +1,24 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.logging
+
+import org.slf4j.Marker
+
+class ColorMarker internal constructor(private val dlg: Marker) : Marker by dlg
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt
new file mode 100644
index 000000000..f0cba2670
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/LogColor.kt
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.logging
+
+import org.slf4j.MDC
+import org.slf4j.MarkerFactory
+
+object LogColor {
+
+ const val COLOR_SERVICES = "green"
+ const val COLOR_TEST_CLIENT = "yellow"
+ const val COLOR_MOCKITO = "cyan"
+ const val COLOR_WIREMOCK = "blue"
+
+ // The Slf4j MDC key that will hold the global color
+ const val MDC_COLOR_KEY = "color"
+
+ fun setContextColor(color: String) {
+ MDC.put(MDC_COLOR_KEY, color)
+ }
+
+ fun resetContextColor() {
+ MDC.remove(MDC_COLOR_KEY)
+ }
+
+ fun markerOf(color: String): ColorMarker =
+ ColorMarker(MarkerFactory.getMarker(color))
+}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt
new file mode 100644
index 000000000..f8e6bd486
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/MockInvocationLogger.kt
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.logging
+
+import org.mockito.listeners.InvocationListener
+import org.mockito.listeners.MethodInvocationReport
+import org.slf4j.LoggerFactory
+import org.slf4j.Marker
+import java.util.concurrent.atomic.AtomicInteger
+
+/**
+ * Logs all Mockito's mock/spy invocations.
+ *
+ * Used for debugging interactions with a mock.
+ */
+class MockInvocationLogger(private val marker: Marker) : InvocationListener {
+
+ private val mockInvocationsCounter = AtomicInteger()
+
+ override fun reportInvocation(report: MethodInvocationReport) {
+ val sb = StringBuilder()
+ sb.appendln("Method invocation #${mockInvocationsCounter.incrementAndGet()} on mock/spy")
+ report.locationOfStubbing?.let { location ->
+ sb.append(INDENT).append("stubbed ").appendln(location)
+ }
+ sb.appendln(report.invocation)
+ sb.append(INDENT).append("invoked ").appendln(report.invocation.location)
+ if (report.threwException()) {
+ sb.append(INDENT).append("has thrown -> ").append(report.throwable.javaClass.name)
+ report.throwable.message?.let { message ->
+ sb.append(" with message ").append(message)
+ }
+ sb.appendln()
+ } else {
+ sb.append(INDENT).append("has returned -> \"").append(report.returnedValue).append('"')
+ report.returnedValue?.let { value ->
+ sb.append(" (").append(value.javaClass.name).append(')')
+ }
+ sb.appendln()
+ }
+ log.info(marker, sb.toString())
+ }
+
+ companion object {
+ private const val INDENT = " "
+ private val log = LoggerFactory.getLogger(MockInvocationLogger::class.java)
+ }
+}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/SmartColorDiscriminator.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/SmartColorDiscriminator.kt
new file mode 100644
index 000000000..cad235450
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/logging/SmartColorDiscriminator.kt
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.logging
+
+import ch.qos.logback.classic.spi.ILoggingEvent
+import ch.qos.logback.core.sift.AbstractDiscriminator
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.MDC_COLOR_KEY
+
+class SmartColorDiscriminator : AbstractDiscriminator<ILoggingEvent>() {
+ var defaultValue: String = "white"
+
+ override fun getKey(): String {
+ return MDC_COLOR_KEY
+ }
+
+ fun setKey() {
+ throw UnsupportedOperationException("Key not settable. Using $MDC_COLOR_KEY")
+ }
+
+ override fun getDiscriminatingValue(e: ILoggingEvent): String =
+ (e.marker as? ColorMarker)?.name
+ ?: e.mdcPropertyMap?.get(MDC_COLOR_KEY)
+ ?: defaultValue
+}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/ExtendedTemporaryFolder.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/ExtendedTemporaryFolder.kt
index c483d90b3..9090361fb 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/ExtendedTemporaryFolder.kt
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/ExtendedTemporaryFolder.kt
@@ -17,7 +17,7 @@
* SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
-package org.onap.ccsdk.cds.blueprintsprocessor.uat
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
import java.io.File
import java.io.IOException
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt
new file mode 100644
index 000000000..39caa0178
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/JsonNormalizer.kt
@@ -0,0 +1,84 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
+
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.node.ContainerNode
+import com.fasterxml.jackson.databind.node.ObjectNode
+import com.schibsted.spt.data.jslt.Parser
+
+internal class JsonNormalizer {
+
+ companion object {
+
+ fun getNormalizer(mapper: ObjectMapper, jsltSpec: JsonNode?): (String) -> String {
+ if (jsltSpec == null) {
+ return { it }
+ }
+ return { s: String ->
+ val input = mapper.readTree(s)
+ val expandedJstlSpec =
+ expandJstlSpec(jsltSpec)
+ val jslt = Parser.compileString(expandedJstlSpec)
+ val output = jslt.apply(input)
+ output.toString()
+ }
+ }
+
+ /**
+ * Creates an extended JSTL spec by appending the "*: ." wildcard pattern to every inner JSON object, and
+ * removing the extra quotes added by the standard YAML/JSON converters on fields prefixed by "?".
+ *
+ * @param jstlSpec the JSTL spec as a structured JSON object.
+ * @return the string representation of the extended JSTL spec.
+ */
+ private fun expandJstlSpec(jstlSpec: JsonNode): String {
+ val extendedJstlSpec =
+ updateObjectNodes(jstlSpec, "*", ".")
+ return extendedJstlSpec.toString()
+ // Handle the "?" as a prefix to literal/non-quoted values
+ .replace("\"\\?([^\"]+)\"".toRegex(), "$1")
+ // Also, remove the quotes added by Jackson for key and value of the wildcard matcher
+ .replace("\"([.*])\"".toRegex(), "$1")
+ }
+
+ /**
+ * Expands a structured JSON object, by adding the given key and value to every nested ObjectNode.
+ *
+ * @param jsonNode the root node.
+ * @param fieldName the fixed field name.
+ * @param fieldValue the fixed field value.
+ */
+ private fun updateObjectNodes(jsonNode: JsonNode, fieldName: String, fieldValue: String): JsonNode {
+ if (jsonNode is ContainerNode<*>) {
+ (jsonNode as? ObjectNode)?.put(fieldName, fieldValue)
+ jsonNode.forEach { child ->
+ updateObjectNodes(
+ child,
+ fieldName,
+ fieldValue
+ )
+ }
+ }
+ return jsonNode
+ }
+ }
+}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/MarkedSlf4jNotifier.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/MarkedSlf4jNotifier.kt
index 13ebd9e4b..e6198b1ba 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/MarkedSlf4jNotifier.kt
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/MarkedSlf4jNotifier.kt
@@ -17,7 +17,7 @@
* SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
-package org.onap.ccsdk.cds.blueprintsprocessor.uat
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
import com.github.tomakehurst.wiremock.common.Notifier
import org.slf4j.LoggerFactory
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt
new file mode 100644
index 000000000..6c5759155
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/PathDeserializer.kt
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
+
+import com.fasterxml.jackson.core.JsonParser
+import com.fasterxml.jackson.databind.DeserializationContext
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer
+
+internal class PathDeserializer : StdDeserializer<String>(String::class.java) {
+ override fun deserialize(jp: JsonParser, ctxt: DeserializationContext?): String {
+ val path = jp.codec.readValue(jp, Any::class.java)
+ return flatJoin(path)
+ }
+
+ /**
+ * Join a multilevel lists of strings.
+ * Example: flatJoin(listOf("a", listOf("b", "c"), "d")) will result in "a/b/c/d".
+ */
+ private fun flatJoin(path: Any): String {
+ fun flatJoinTo(sb: StringBuilder, path: Any): StringBuilder {
+ when (path) {
+ is List<*> -> path.filterNotNull().forEach { flatJoinTo(sb, it) }
+ is String -> {
+ if (sb.isNotEmpty()) {
+ sb.append('/')
+ }
+ sb.append(path)
+ }
+ else -> throw IllegalArgumentException("Unsupported type: ${path.javaClass}")
+ }
+ return sb
+ }
+ return flatJoinTo(StringBuilder(), path).toString()
+ }
+}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt
new file mode 100644
index 000000000..0f98d7213
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/RequiredMapEntriesMatcher.kt
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
+
+import com.google.common.collect.Maps
+import org.mockito.ArgumentMatcher
+
+class RequiredMapEntriesMatcher<K, V>(private val requiredEntries: Map<K, V>) : ArgumentMatcher<Map<K, V>> {
+ override fun matches(argument: Map<K, V>?): Boolean {
+ val missingEntries = Maps.difference(requiredEntries, argument).entriesOnlyOnLeft()
+ return missingEntries.isEmpty()
+ }
+
+ override fun toString(): String {
+ return requiredEntries.toString()
+ }
+}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/TestSecuritySettings.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/TestSecuritySettings.kt
index b0917cb7d..888ab8dcd 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/TestSecuritySettings.kt
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/TestSecuritySettings.kt
@@ -17,7 +17,7 @@
* SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
-package org.onap.ccsdk.cds.blueprintsprocessor.uat
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
import org.springframework.context.ApplicationContextInitializer
import org.springframework.context.ConfigurableApplicationContext
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt
new file mode 100644
index 000000000..c45ac45c6
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt
@@ -0,0 +1,102 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
+
+import com.fasterxml.jackson.annotation.JsonAlias
+import com.fasterxml.jackson.annotation.JsonInclude
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import com.fasterxml.jackson.module.kotlin.convertValue
+import org.yaml.snakeyaml.DumperOptions
+import org.yaml.snakeyaml.Yaml
+import org.yaml.snakeyaml.nodes.Tag
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+data class ProcessDefinition(
+ val name: String,
+ val request: JsonNode,
+ val expectedResponse: JsonNode? = null,
+ val responseNormalizerSpec: JsonNode? = null
+)
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+data class RequestDefinition(
+ val method: String,
+ @JsonDeserialize(using = PathDeserializer::class)
+ val path: String,
+ val headers: Map<String, String> = emptyMap(),
+ val body: JsonNode? = null
+)
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+data class ResponseDefinition(val status: Int = 200, val body: JsonNode? = null) {
+
+ companion object {
+ val DEFAULT_RESPONSE = ResponseDefinition()
+ }
+}
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+data class ExpectationDefinition(
+ val request: RequestDefinition,
+ val response: ResponseDefinition = ResponseDefinition.DEFAULT_RESPONSE
+)
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+data class ServiceDefinition(val selector: String, val expectations: List<ExpectationDefinition>)
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+data class UatDefinition(
+ val processes: List<ProcessDefinition>,
+ @JsonAlias("external-services")
+ val externalServices: List<ServiceDefinition> = emptyList()
+) {
+
+ fun dump(mapper: ObjectMapper, excludedProperties: List<String> = emptyList()): String {
+ val uatAsMap: Map<String, Any> = mapper.convertValue(this)
+ if (excludedProperties.isNotEmpty()) {
+ pruneTree(uatAsMap, excludedProperties)
+ }
+ return Yaml().dumpAs(uatAsMap, Tag.MAP, DumperOptions.FlowStyle.BLOCK)
+ }
+
+ fun toBare(): UatDefinition {
+ val newProcesses = processes.map { p ->
+ ProcessDefinition(p.name, p.request, null, p.responseNormalizerSpec)
+ }
+ return UatDefinition(newProcesses)
+ }
+
+ private fun pruneTree(node: Any?, excludedProperties: List<String>) {
+ when (node) {
+ is MutableMap<*, *> -> {
+ excludedProperties.forEach { key -> node.remove(key) }
+ node.forEach { (_, value) -> pruneTree(value, excludedProperties) }
+ }
+ is List<*> -> node.forEach { value -> pruneTree(value, excludedProperties) }
+ }
+ }
+
+ companion object {
+ fun load(mapper: ObjectMapper, spec: String): UatDefinition =
+ mapper.convertValue(Yaml().load(spec), UatDefinition::class.java)
+ }
+}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt
new file mode 100644
index 000000000..a904fa9b6
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt
@@ -0,0 +1,359 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
+
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.nhaarman.mockitokotlin2.any
+import com.nhaarman.mockitokotlin2.argThat
+import com.nhaarman.mockitokotlin2.atLeast
+import com.nhaarman.mockitokotlin2.atLeastOnce
+import com.nhaarman.mockitokotlin2.eq
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.verify
+import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
+import com.nhaarman.mockitokotlin2.whenever
+import org.apache.http.HttpHeaders
+import org.apache.http.HttpStatus
+import org.apache.http.client.HttpClient
+import org.apache.http.client.methods.HttpPost
+import org.apache.http.entity.ContentType
+import org.apache.http.entity.StringEntity
+import org.apache.http.entity.mime.HttpMultipartMode
+import org.apache.http.entity.mime.MultipartEntityBuilder
+import org.apache.http.impl.client.HttpClientBuilder
+import org.apache.http.message.BasicHeader
+import org.hamcrest.CoreMatchers.equalTo
+import org.hamcrest.CoreMatchers.notNullValue
+import org.hamcrest.MatcherAssert.assertThat
+import org.mockito.Answers
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService.WebClientResponse
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.COLOR_MOCKITO
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.markerOf
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.MockInvocationLogger
+import org.skyscreamer.jsonassert.JSONAssert
+import org.skyscreamer.jsonassert.JSONCompareMode
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.springframework.core.env.ConfigurableEnvironment
+import org.springframework.http.MediaType
+import org.springframework.stereotype.Component
+import org.springframework.util.Base64Utils
+import java.util.concurrent.ConcurrentHashMap
+
+/**
+ * Assumptions:
+ *
+ * - Application HTTP service is bound to loopback interface;
+ * - Password is either defined in plain (with "{noop}" prefix), or it's the same of username.
+ *
+ * @author Eliezio Oliveira
+ */
+@Component
+class UatExecutor(
+ private val environment: ConfigurableEnvironment,
+ private val restClientFactory: BluePrintRestLibPropertyService,
+ private val mapper: ObjectMapper
+) {
+
+ companion object {
+ private const val NOOP_PASSWORD_PREFIX = "{noop}"
+
+ private val log: Logger = LoggerFactory.getLogger(UatExecutor::class.java)
+ private val mockLoggingListener = MockInvocationLogger(markerOf(COLOR_MOCKITO))
+ }
+
+ // use lazy evaluation to postpone until localServerPort is injected by Spring
+ private val baseUrl: String by lazy {
+ "http://127.0.0.1:${localServerPort()}"
+ }
+
+ @Throws(AssertionError::class)
+ fun execute(uatSpec: String, cbaBytes: ByteArray) {
+ val uat = UatDefinition.load(mapper, uatSpec)
+ execute(uat, cbaBytes)
+ }
+
+ /**
+ *
+ * The UAT can range from minimum to completely defined.
+ *
+ * @return an updated UAT with all NB and SB messages.
+ */
+ @Throws(AssertionError::class)
+ fun execute(uat: UatDefinition, cbaBytes: ByteArray): UatDefinition {
+ val defaultHeaders = listOf(BasicHeader(HttpHeaders.AUTHORIZATION, clientAuthToken()))
+ val httpClient = HttpClientBuilder.create()
+ .setDefaultHeaders(defaultHeaders)
+ .build()
+ // Only if externalServices are defined
+ val mockInterceptor = MockPreInterceptor()
+ // Always defined and used, whatever the case
+ val spyInterceptor = SpyPostInterceptor(mapper)
+ restClientFactory.setInterceptors(mockInterceptor, spyInterceptor)
+ try {
+ // Configure mocked external services and save their expected requests for further validation
+ val requestsPerClient = uat.externalServices.associateBy(
+ { service ->
+ createRestClientMock(service.expectations).also { restClient ->
+ // side-effect: register restClient to override real instance
+ mockInterceptor.registerMock(service.selector, restClient)
+ }
+ },
+ { service -> service.expectations.map { it.request } }
+ )
+
+ val newProcesses = httpClient.use { client ->
+ uploadBlueprint(client, cbaBytes)
+
+ // Run processes
+ uat.processes.map { process ->
+ log.info("Executing process '${process.name}'")
+ val responseNormalizer = JsonNormalizer.getNormalizer(mapper, process.responseNormalizerSpec)
+ val actualResponse = processBlueprint(
+ client, process.request,
+ process.expectedResponse, responseNormalizer
+ )
+ ProcessDefinition(
+ process.name,
+ process.request,
+ actualResponse,
+ process.responseNormalizerSpec
+ )
+ }
+ }
+
+ // Validate requests to external services
+ for ((mockClient, requests) in requestsPerClient) {
+ requests.forEach { request ->
+ verify(mockClient, atLeastOnce()).exchangeResource(
+ eq(request.method),
+ eq(request.path),
+ argThat { assertJsonEquals(request.body, this) },
+ argThat(RequiredMapEntriesMatcher(request.headers))
+ )
+ }
+ // Don't mind the invocations to the overloaded exchangeResource(String, String, String)
+ verify(mockClient, atLeast(0)).exchangeResource(any(), any(), any())
+ verifyNoMoreInteractions(mockClient)
+ }
+
+ val newExternalServices = spyInterceptor.getSpies()
+ .map(SpyService::asServiceDefinition)
+
+ return UatDefinition(newProcesses, newExternalServices)
+ } finally {
+ restClientFactory.clearInterceptors()
+ }
+ }
+
+ private fun createRestClientMock(restExpectations: List<ExpectationDefinition>):
+ BlueprintWebClientService {
+ val restClient = mock<BlueprintWebClientService>(
+ defaultAnswer = Answers.RETURNS_SMART_NULLS,
+ // our custom verboseLogging handler
+ invocationListeners = arrayOf(mockLoggingListener)
+ )
+
+ // Delegates to overloaded exchangeResource(String, String, String, Map<String, String>)
+ whenever(restClient.exchangeResource(any(), any(), any()))
+ .thenAnswer { invocation ->
+ val method = invocation.arguments[0] as String
+ val path = invocation.arguments[1] as String
+ val request = invocation.arguments[2] as String
+ restClient.exchangeResource(method, path, request, emptyMap())
+ }
+ for (expectation in restExpectations) {
+ whenever(
+ restClient.exchangeResource(
+ eq(expectation.request.method),
+ eq(expectation.request.path),
+ any(),
+ any()
+ )
+ )
+ .thenReturn(WebClientResponse(expectation.response.status, expectation.response.body.toString()))
+ }
+ return restClient
+ }
+
+ @Throws(AssertionError::class)
+ private fun uploadBlueprint(client: HttpClient, cbaBytes: ByteArray) {
+ val multipartEntity = MultipartEntityBuilder.create()
+ .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
+ .addBinaryBody("file", cbaBytes, ContentType.DEFAULT_BINARY, "cba.zip")
+ .build()
+ val request = HttpPost("$baseUrl/api/v1/blueprint-model/publish").apply {
+ entity = multipartEntity
+ }
+ client.execute(request) { response ->
+ val statusLine = response.statusLine
+ assertThat(statusLine.statusCode, equalTo(HttpStatus.SC_OK))
+ }
+ }
+
+ @Throws(AssertionError::class)
+ private fun processBlueprint(
+ client: HttpClient,
+ requestBody: JsonNode,
+ expectedResponse: JsonNode?,
+ responseNormalizer: (String) -> String
+ ): JsonNode {
+ val stringEntity = StringEntity(mapper.writeValueAsString(requestBody), ContentType.APPLICATION_JSON)
+ val request = HttpPost("$baseUrl/api/v1/execution-service/process").apply {
+ entity = stringEntity
+ }
+ val response = client.execute(request) { response ->
+ val statusLine = response.statusLine
+ assertThat(statusLine.statusCode, equalTo(HttpStatus.SC_OK))
+ val entity = response.entity
+ assertThat("Response contains no content", entity, notNullValue())
+ entity.content.bufferedReader().use { it.readText() }
+ }
+ val actualResponse = responseNormalizer(response)
+ if (expectedResponse != null) {
+ assertJsonEquals(expectedResponse, actualResponse)
+ }
+ return mapper.readTree(actualResponse)!!
+ }
+
+ @Throws(AssertionError::class)
+ private fun assertJsonEquals(expected: JsonNode?, actual: String): Boolean {
+ // special case
+ if ((expected == null) && actual.isBlank()) {
+ return true
+ }
+ // general case
+ JSONAssert.assertEquals(expected?.toString(), actual, JSONCompareMode.LENIENT)
+ // assertEquals throws an exception whenever match fails
+ return true
+ }
+
+ private fun localServerPort(): Int =
+ (environment.getProperty("local.server.port")
+ ?: environment.getRequiredProperty("blueprint.httpPort")).toInt()
+
+ private fun clientAuthToken(): String {
+ val username = environment.getRequiredProperty("security.user.name")
+ val password = environment.getRequiredProperty("security.user.password")
+ val plainPassword = when {
+ password.startsWith(NOOP_PASSWORD_PREFIX) -> password.substring(
+ NOOP_PASSWORD_PREFIX.length)
+ else -> username
+ }
+ return "Basic " + Base64Utils.encodeToString("$username:$plainPassword".toByteArray())
+ }
+
+ private class MockPreInterceptor : BluePrintRestLibPropertyService.PreInterceptor {
+ private val mocks = ConcurrentHashMap<String, BlueprintWebClientService>()
+
+ override fun getInstance(jsonNode: JsonNode): BlueprintWebClientService? {
+ TODO("jsonNode-keyed services not yet supported")
+ }
+
+ override fun getInstance(selector: String): BlueprintWebClientService? =
+ mocks[selector]
+
+ fun registerMock(selector: String, client: BlueprintWebClientService) {
+ mocks[selector] = client
+ }
+ }
+
+ private class SpyPostInterceptor(private val mapper: ObjectMapper) : BluePrintRestLibPropertyService.PostInterceptor {
+
+ private val spies = ConcurrentHashMap<String, SpyService>()
+
+ override fun getInstance(jsonNode: JsonNode, service: BlueprintWebClientService): BlueprintWebClientService {
+ TODO("jsonNode-keyed services not yet supported")
+ }
+
+ override fun getInstance(selector: String, service: BlueprintWebClientService): BlueprintWebClientService {
+ val spiedService = SpyService(mapper, selector, service)
+ spies[selector] = spiedService
+ return spiedService
+ }
+
+ fun getSpies(): List<SpyService> =
+ spies.values.toList()
+ }
+
+ private class SpyService(
+ private val mapper: ObjectMapper,
+ val selector: String,
+ private val realService: BlueprintWebClientService
+ ) :
+ BlueprintWebClientService by realService {
+
+ private val expectations: MutableList<ExpectationDefinition> = mutableListOf()
+
+ override fun exchangeResource(methodType: String, path: String, request: String): WebClientResponse<String> =
+ exchangeResource(methodType, path, request,
+ DEFAULT_HEADERS
+ )
+
+ override fun exchangeResource(
+ methodType: String,
+ path: String,
+ request: String,
+ headers: Map<String, String>
+ ): WebClientResponse<String> {
+ val requestDefinition =
+ RequestDefinition(methodType, path, headers, toJson(request))
+ val realAnswer = realService.exchangeResource(methodType, path, request, headers)
+ val responseBody = when {
+ // TODO: confirm if we need to normalize the response here
+ realAnswer.status == HttpStatus.SC_OK -> toJson(realAnswer.body)
+ else -> null
+ }
+ val responseDefinition =
+ ResponseDefinition(realAnswer.status, responseBody)
+ expectations.add(
+ ExpectationDefinition(
+ requestDefinition,
+ responseDefinition
+ )
+ )
+ return realAnswer
+ }
+
+ override suspend fun <T> retry(times: Int, initialDelay: Long, delay: Long, block: suspend (Int) -> T): T {
+ return super.retry(times, initialDelay, delay, block)
+ }
+
+ fun asServiceDefinition() =
+ ServiceDefinition(selector, expectations)
+
+ private fun toJson(str: String): JsonNode? {
+ return when {
+ str.isNotBlank() -> mapper.readTree(str)
+ else -> null
+ }
+ }
+
+ companion object {
+ private val DEFAULT_HEADERS = mapOf(
+ HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
+ HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE
+ )
+ }
+ }
+}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt
new file mode 100644
index 000000000..f40b903de
--- /dev/null
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatServices.kt
@@ -0,0 +1,125 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import kotlinx.coroutines.runBlocking
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.COLOR_SERVICES
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.resetContextColor
+import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.setContextColor
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.UAT_SPECIFICATION_FILE
+import org.springframework.context.annotation.Profile
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.http.codec.multipart.FilePart
+import org.springframework.security.access.prepost.PreAuthorize
+import org.springframework.web.bind.annotation.PostMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RequestPart
+import org.springframework.web.bind.annotation.RestController
+import org.springframework.web.server.ResponseStatusException
+import java.io.File
+import java.util.zip.ZipFile
+
+/**
+ * Supporting services to help creating UAT specifications.
+ *
+ * @author Eliezio Oliveira
+ */
+@RestController
+@RequestMapping("/api/v1/uat")
+@Profile("uat")
+open class UatServices(private val uatExecutor: UatExecutor, private val mapper: ObjectMapper) {
+
+ @PostMapping("/verify", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
+ @PreAuthorize("hasRole('USER')")
+ @Suppress("BlockingMethodInNonBlockingContext")
+ open fun verify(@RequestPart("cba") cbaFile: FilePart) = runBlocking {
+ setContextColor(COLOR_SERVICES)
+ val tempFile = createTempFile()
+ try {
+ cbaFile.transferTo(tempFile)
+ val uatSpec = readZipEntryAsText(tempFile, UAT_SPECIFICATION_FILE)
+ val cbaBytes = tempFile.readBytes()
+ uatExecutor.execute(uatSpec, cbaBytes)
+ } catch (e: AssertionError) {
+ throw ResponseStatusException(HttpStatus.BAD_REQUEST, e.message)
+ } catch (t: Throwable) {
+ throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, t.message, t)
+ } finally {
+ tempFile.delete()
+ resetContextColor()
+ }
+ }
+
+ @PostMapping("/spy", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE], produces = ["text/vnd.yaml"])
+ @PreAuthorize("hasRole('USER')")
+ @Suppress("BlockingMethodInNonBlockingContext")
+ open fun spy(
+ @RequestPart("cba") cbaFile: FilePart,
+ @RequestPart("uat", required = false) uatFile: FilePart?
+ ): String = runBlocking {
+ val tempFile = createTempFile()
+ setContextColor(COLOR_SERVICES)
+ try {
+ cbaFile.transferTo(tempFile)
+ val uatSpec = when {
+ uatFile != null -> uatFile.readText()
+ else -> readZipEntryAsText(tempFile, UAT_SPECIFICATION_FILE)
+ }
+ val uat = UatDefinition.load(mapper, uatSpec)
+ val cbaBytes = tempFile.readBytes()
+ val updatedUat = uatExecutor.execute(uat, cbaBytes)
+ return@runBlocking updatedUat.dump(mapper,
+ FIELDS_TO_EXCLUDE
+ )
+ } catch (t: Throwable) {
+ throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, t.message, t)
+ } finally {
+ tempFile.delete()
+ resetContextColor()
+ }
+ }
+
+ private fun FilePart.readText(): String {
+ val tempFile = createTempFile()
+ try {
+ transferTo(tempFile).block()
+ return tempFile.readText()
+ } finally {
+ tempFile.delete()
+ }
+ }
+
+ @Suppress("SameParameterValue")
+ private fun readZipEntryAsText(file: File, entryName: String): String {
+ return ZipFile(file).use { zipFile -> zipFile.readEntryAsText(entryName) }
+ }
+
+ private fun ZipFile.readEntryAsText(entryName: String): String {
+ val zipEntry = getEntry(entryName)
+ return getInputStream(zipEntry).readBytes().toString(Charsets.UTF_8)
+ }
+
+ companion object {
+ // Fields that can be safely ignored from BPP response, and can be omitted on the UAT specification.
+ private val FIELDS_TO_EXCLUDE = listOf("timestamp")
+ }
+}
diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/WorkingFoldersInitializer.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/WorkingFoldersInitializer.kt
index 3c1757432..001dcbec4 100644
--- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/WorkingFoldersInitializer.kt
+++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/WorkingFoldersInitializer.kt
@@ -17,7 +17,7 @@
* SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
-package org.onap.ccsdk.cds.blueprintsprocessor.uat
+package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
import org.springframework.beans.factory.support.BeanDefinitionBuilder
import org.springframework.beans.factory.support.BeanDefinitionRegistry
@@ -32,7 +32,7 @@ class WorkingFoldersInitializer : ApplicationContextInitializer<ConfigurableAppl
override fun initialize(context: ConfigurableApplicationContext) {
val tempFolder = ExtendedTemporaryFolder()
val properties = listOf("Deploy", "Archive", "Working")
- .map { "blueprintsprocessor.blueprint${it}Path=${tempFolder.newFolder(it)}" }
+ .map { "blueprintsprocessor.blueprint${it}Path=${tempFolder.newFolder(it).absolutePath.replace("\\", "/")}" }
.toTypedArray()
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context, *properties)
// Expose tempFolder as a bean so it can be accessed via DI