/*- * ============LICENSE_START======================================================= * Copyright (C) 2019 Nordix Foundation. * Modifications Copyright (c) 2019 IBM, Bell Canada. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.node.TextNode import io.mockk.every import io.mockk.spyk import org.junit.Before import org.junit.Test import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType import org.onap.ccsdk.cds.controllerblueprints.core.data.EntrySchema import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment import kotlin.test.assertEquals data class IpAddress(val port: String, val ip: String) data class Host(val name: String, val ipAddress: IpAddress) data class ExpectedResponseIp(val ip: String) data class ExpectedResponseIpAddress(val ipAddress: IpAddress) class ResourceAssignmentUtilsTest { private lateinit var resourceAssignmentRuntimeService: ResourceAssignmentRuntimeService private lateinit var inputMapToTestPrimitiveTypeWithValue: JsonNode private lateinit var inputMapToTestPrimitiveTypeWithKeyValue: JsonNode private lateinit var inputMapToTestCollectionOfPrimitiveType: JsonNode private lateinit var inputMapToTestCollectionOfComplexTypeWithOneOutputKeyMapping: JsonNode private lateinit var inputMapToTestCollectionOfComplexTypeWithAllOutputKeyMapping: JsonNode private lateinit var inputMapToTestComplexTypeWithOneOutputKeyMapping: JsonNode private lateinit var inputMapToTestComplexTypeWithAllOutputKeyMapping: JsonNode private lateinit var expectedValueToTestPrimitiveType: JsonNode private lateinit var expectedValueToTesCollectionOfPrimitiveType: JsonNode private lateinit var expectedValueToTestCollectionOfComplexTypeWithOneOutputKeyMapping: JsonNode private lateinit var expectedValueToTestComplexTypeWithOneOutputKeyMapping: JsonNode private lateinit var expectedValueToTestComplexTypeWithAllOutputKeyMapping: JsonNode private lateinit var expectedValueToTestCollectionOfComplexTypeWithAllOutputKeyMapping: JsonNode @Before fun setup() { val bluePrintContext = BluePrintMetadataUtils.getBluePrintContext( "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration") resourceAssignmentRuntimeService = spyk(ResourceAssignmentRuntimeService("1234", bluePrintContext)) //Init input map and expected values for tests initInputMapAndExpectedValuesForPrimitiveType() initInputMapAndExpectedValuesForCollection() initInputMapAndExpectedValuesForComplexType() val propertiesDefinition1 = PropertyDefinition().apply { type = "string" id = "port" } val propertiesDefinition2 = PropertyDefinition().apply { type = "string" id = "ip" } val propertiesDefinition3 = PropertyDefinition().apply { type = "string" id = "name" } val propertiesDefinition4 = PropertyDefinition().apply { type = "ip-address" id = "ipAddress" } var mapOfPropertiesIpAddress = mutableMapOf() mapOfPropertiesIpAddress["port"] = propertiesDefinition1 mapOfPropertiesIpAddress["ip"] = propertiesDefinition2 var mapOfPropertiesHost = mutableMapOf() mapOfPropertiesHost["name"] = propertiesDefinition3 mapOfPropertiesHost["ipAddress"] = propertiesDefinition4 val myDataTypeIpaddress = DataType().apply { id = "ip-address" properties = mapOfPropertiesIpAddress } val myDataTypeHost = DataType().apply { id = "host" properties = mapOfPropertiesHost } every { resourceAssignmentRuntimeService.bluePrintContext().dataTypeByName("ip-address") } returns myDataTypeIpaddress every { resourceAssignmentRuntimeService.bluePrintContext().dataTypeByName("host") } returns myDataTypeHost every { resourceAssignmentRuntimeService.setNodeTemplateAttributeValue(any(), any(), any()) } returns Unit } @Test fun `generateResourceDataForAssignments - positive test`() { //given a valid resource assignment val validResourceAssignment = createResourceAssignmentForTest("valid_value") //and a list containing that resource assignment val resourceAssignmentList = listOf(validResourceAssignment) //when the values of the resources are evaluated val outcome = ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignmentList) //then the assignment should produce a valid result val expected = "{\n" + " \"pnf-id\" : \"valid_value\"\n" + "}" assertEquals(expected, outcome.replace("\r\n","\n"), "unexpected outcome generated") } @Test fun `generateResourceDataForAssignments - resource without value is not resolved as null`() { //given a valid resource assignment val resourceAssignmentWithNullValue = createResourceAssignmentForTest(null) //and a list containing that resource assignment val resourceAssignmentList = listOf(resourceAssignmentWithNullValue) //when the values of the resources are evaluated val outcome = ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignmentList) //then the assignment should produce a valid result val expected = "{\n" + " \"pnf-id\" : \"\${pnf-id}\"\n" + "}" assertEquals(expected, outcome.replace("\r\n","\n"), "unexpected outcome generated") } private fun createResourceAssignmentForTest(resourceValue: String?): ResourceAssignment { val valueForTest = if (resourceValue == null) null else TextNode(resourceValue) val resourceAssignmentForTest = ResourceAssignment().apply { name = "pnf-id" dictionaryName = "pnf-id" dictionarySource = "input" property = PropertyDefinition().apply { type = "string" value = valueForTest } } return resourceAssignmentForTest } @Test fun parseResponseNodeTestForPrimitivesTypes(){ var outcome = prepareResponseNodeForTest("sample-value", "string", "", inputMapToTestPrimitiveTypeWithValue) assertEquals(expectedValueToTestPrimitiveType, outcome, "Unexpected outcome returned for primitive type of simple String") outcome = prepareResponseNodeForTest("sample-key-value", "string", "", inputMapToTestPrimitiveTypeWithKeyValue) assertEquals(expectedValueToTestPrimitiveType, outcome, "Unexpected outcome returned for primitive type of key-value String") } @Test fun parseResponseNodeTestForCollectionsOfString(){ var outcome = prepareResponseNodeForTest("listOfString", "list", "string", inputMapToTestCollectionOfPrimitiveType) assertEquals(expectedValueToTesCollectionOfPrimitiveType, outcome, "unexpected outcome returned for list of String") outcome = prepareResponseNodeForTest("mapOfString", "map", "string", inputMapToTestCollectionOfPrimitiveType) assertEquals(expectedValueToTesCollectionOfPrimitiveType, outcome, "unexpected outcome returned for map of String") } @Test fun parseResponseNodeTestForCollectionsOfComplexType(){ var outcome = prepareResponseNodeForTest("listOfMyDataTypeWithOneOutputKeyMapping", "list", "ip-address", inputMapToTestCollectionOfComplexTypeWithOneOutputKeyMapping) assertEquals(expectedValueToTestCollectionOfComplexTypeWithOneOutputKeyMapping, outcome, "unexpected outcome returned for list of String") outcome = prepareResponseNodeForTest("listOfMyDataTypeWithAllOutputKeyMapping", "list", "ip-address", inputMapToTestCollectionOfComplexTypeWithAllOutputKeyMapping) assertEquals(expectedValueToTestCollectionOfComplexTypeWithAllOutputKeyMapping, outcome, "unexpected outcome returned for list of String") } @Test fun `parseResponseNodeTestForComplexType find one output key mapping`(){ val outcome = prepareResponseNodeForTest("complexTypeOneKeys", "host", "", inputMapToTestComplexTypeWithOneOutputKeyMapping) assertEquals(expectedValueToTestComplexTypeWithOneOutputKeyMapping, outcome, "Unexpected outcome returned for complex type") } @Test fun `parseResponseNodeTestForComplexType find all output key mapping`(){ val outcome = prepareResponseNodeForTest("complexTypeAllKeys", "host", "", inputMapToTestComplexTypeWithAllOutputKeyMapping) assertEquals(expectedValueToTestComplexTypeWithAllOutputKeyMapping, outcome, "Unexpected outcome returned for complex type") } private fun initInputMapAndExpectedValuesForPrimitiveType() { inputMapToTestPrimitiveTypeWithValue = "1.2.3.1".asJsonType() val keyValue = mutableMapOf() keyValue["value"]= "1.2.3.1" inputMapToTestPrimitiveTypeWithKeyValue = keyValue.asJsonType() expectedValueToTestPrimitiveType = TextNode("1.2.3.1") } private fun initInputMapAndExpectedValuesForCollection(){ val listOfIps = arrayListOf("1.2.3.1", "1.2.3.2", "1.2.3.3") val arrayNodeForList1 = JacksonUtils.objectMapper.createArrayNode() listOfIps.forEach { val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() arrayChildNode.set("value", it.asJsonPrimitive()) arrayNodeForList1.add(arrayChildNode) } inputMapToTestCollectionOfPrimitiveType = arrayNodeForList1 expectedValueToTesCollectionOfPrimitiveType = arrayListOf(ExpectedResponseIp("1.2.3.1"), ExpectedResponseIp( "1.2.3.2"), ExpectedResponseIp("1.2.3.3")).asJsonType() val listOfIpAddresses = arrayListOf(IpAddress("1111", "1.2.3.1").asJsonType(), IpAddress("2222", "1.2.3.2").asJsonType(), IpAddress("3333", "1.2.3.3").asJsonType()) val arrayNodeForList2 = JacksonUtils.objectMapper.createArrayNode() listOfIpAddresses.forEach { val arrayChildNode = JacksonUtils.objectMapper.createObjectNode() arrayChildNode.set("value", it.asJsonType()) arrayNodeForList2.add(arrayChildNode) } inputMapToTestCollectionOfComplexTypeWithOneOutputKeyMapping = arrayNodeForList2 val arrayNodeForList3 = JacksonUtils.objectMapper.createArrayNode() var childNode = JacksonUtils.objectMapper.createObjectNode() childNode.set("port", "1111".asJsonPrimitive()) childNode.set("ip", "1.2.3.1".asJsonPrimitive()) arrayNodeForList3.add(childNode) childNode = JacksonUtils.objectMapper.createObjectNode() childNode.set("port", "2222".asJsonPrimitive()) childNode.set("ip", "1.2.3.2".asJsonPrimitive()) arrayNodeForList3.add(childNode) childNode = JacksonUtils.objectMapper.createObjectNode() childNode.set("port", "3333".asJsonPrimitive()) childNode.set("ip", "1.2.3.3".asJsonPrimitive()) arrayNodeForList3.add(childNode) inputMapToTestCollectionOfComplexTypeWithAllOutputKeyMapping = arrayNodeForList3 expectedValueToTestCollectionOfComplexTypeWithOneOutputKeyMapping = arrayListOf(ExpectedResponseIpAddress(IpAddress("1111", "1.2.3.1")), ExpectedResponseIpAddress(IpAddress("2222", "1.2.3.2")), ExpectedResponseIpAddress( IpAddress("3333", "1.2.3.3"))).asJsonType() expectedValueToTestCollectionOfComplexTypeWithAllOutputKeyMapping = arrayListOf(IpAddress("1111", "1.2.3.1"), IpAddress("2222", "1.2.3.2"), IpAddress("3333", "1.2.3.3")).asJsonType() } private fun initInputMapAndExpectedValuesForComplexType(){ val mapOfComplexType = mutableMapOf() mapOfComplexType["value"] = Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType() mapOfComplexType["port"] = "8888".asJsonType() mapOfComplexType["something"] = "1.2.3.2".asJsonType() inputMapToTestComplexTypeWithOneOutputKeyMapping = mapOfComplexType.asJsonType() val objectNode = JacksonUtils.objectMapper.createObjectNode() expectedValueToTestComplexTypeWithOneOutputKeyMapping = objectNode.set("host", Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType()) val childNode1 = JacksonUtils.objectMapper.createObjectNode() childNode1.set("name", "my-ipAddress".asJsonPrimitive()) childNode1.set("ipAddress", IpAddress("1111", "1.2.3.1").asJsonType()) childNode1.set("port", "8888".asJsonType()) childNode1.set("something", IpAddress("2222", "1.2.3.1").asJsonType()) inputMapToTestComplexTypeWithAllOutputKeyMapping = childNode1 val childNode2 = JacksonUtils.objectMapper.createObjectNode() childNode2.set("name", "my-ipAddress".asJsonPrimitive()) childNode2.set("ipAddress", IpAddress("1111", "1.2.3.1").asJsonType()) expectedValueToTestComplexTypeWithAllOutputKeyMapping = childNode2 } private fun prepareResponseNodeForTest(dictionary_source: String, sourceType: String, entrySchema: String, response: Any): JsonNode { val resourceAssignment = when (sourceType) { "list", "map" -> { prepareRADataDictionaryCollection(dictionary_source, sourceType, entrySchema) } "string" -> { prepareRADataDictionaryOfPrimaryType(dictionary_source) } else -> { prepareRADataDictionaryComplexType(dictionary_source, sourceType, entrySchema) } } val responseNode = checkNotNull(JacksonUtils.getJsonNode(response)) { "Failed to get database query result into Json node." } val outputKeyMapping = prepareOutputKeyMapping(dictionary_source) return ResourceAssignmentUtils.parseResponseNode(responseNode, resourceAssignment, resourceAssignmentRuntimeService, outputKeyMapping) } private fun prepareRADataDictionaryOfPrimaryType(dictionary_source: String): ResourceAssignment { return ResourceAssignment().apply { name = "ipAddress" dictionaryName = "sample-ip" dictionarySource = "$dictionary_source" property = PropertyDefinition().apply { type = "string" } } } private fun prepareRADataDictionaryCollection(dictionary_source: String, sourceType: String, schema: String): ResourceAssignment { return ResourceAssignment().apply { name = "ipAddress-list" dictionaryName = "sample-licenses" dictionarySource = "$dictionary_source" property = PropertyDefinition().apply { type = "$sourceType" entrySchema = EntrySchema().apply { type = "$schema" } } } } private fun prepareRADataDictionaryComplexType(dictionary_source: String, sourceType: String, schema: String): ResourceAssignment { return ResourceAssignment().apply { name = "ipAddress-complexType" dictionaryName = "sample-licenses" dictionarySource = "$dictionary_source" property = PropertyDefinition().apply { type = "$sourceType" } } } private fun prepareOutputKeyMapping(dictionary_source: String): MutableMap { val outputMapping = mutableMapOf() when (dictionary_source) { "sample-key-value", "sample-value" -> { //Primary Type if (dictionary_source=="sample-key-value") outputMapping["sample-ip"] = "value" } "listOfString", "mapOfString" -> { //List of string outputMapping["ip"] = "value" } "listOfMyDataTypeWithOneOutputKeyMapping", "listOfMyDataTypeWithAllOutputKeyMapping" -> { //List or map of complex Type if (dictionary_source == "listOfMyDataTypeWithOneOutputKeyMapping") outputMapping["ipAddress"] = "value" else { outputMapping["port"] = "port" outputMapping["ip"] = "ip" } } else -> { //Complex Type if (dictionary_source == "complexTypeOneKeys") outputMapping["host"] = "value" else { outputMapping["name"] = "name" outputMapping["ipAddress"] = "ipAddress" } } } return outputMapping } }