1 package org.onap.ccsdk.cds.blueprintsprocessor.uat.base
3 import com.fasterxml.jackson.databind.ObjectMapper
4 import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
5 import com.nhaarman.mockitokotlin2.any
6 import com.nhaarman.mockitokotlin2.eq
7 import com.nhaarman.mockitokotlin2.mock
8 import com.nhaarman.mockitokotlin2.whenever
12 import org.mockito.Answers
13 import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService
14 import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertyConfiguration
15 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
16 import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.PayloadUtils
17 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants
18 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService
19 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionServiceImpl
20 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService
21 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionRepository
22 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionRepository
23 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionService
24 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.CapabilityResourceResolutionProcessor
25 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.DefaultResourceResolutionProcessor
26 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.InputResourceResolutionProcessor
27 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.processor.RestResourceResolutionProcessor
28 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
29 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService
30 import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService
31 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService
32 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts.DeprecatedBlueprintJythonService
33 import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor
34 import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.MockInvocationLogger
35 import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.ExpectationDefinition
36 import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.UatDefinition
37 import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.UatExecutor.MockPreInterceptor
38 import org.onap.ccsdk.cds.blueprintsprocessor.uat.utils.UatExecutor.SpyPostInterceptor
39 import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
40 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService
41 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
42 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
43 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
44 import org.slf4j.Logger
45 import org.slf4j.LoggerFactory
46 import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext
47 import org.springframework.context.ApplicationContext
50 import java.nio.file.Path
51 import kotlin.test.BeforeTest
54 * This abstract base class supports tests of single workflow steps in an isolated manner, that are using
55 * {@see org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionComponent}.
56 * This means all the used external systems like e.g. sdnc or aai are mocked and must response with the correct
57 * BlueprintWebClientService.WebClientResponse to let the ressource resolution work properly.
59 * The component inside CDS, which is responsible for resolving resources is ResourceResolutionService.
60 * The ResourceResolutionService is using ResourceAssignmentProcessor's like e.g.
61 * InputResourceResolutionProcessor, DefaultResourceResolutionProcessor, RestResourceResolutionProcessor
62 * and CapabilityResourceResolutionProcessor
64 * These classes are only partially mocked by mockk spyk() function. This means, that the real classes are used
65 * and only some methods are rewritten via every {}.returns(...) functions
67 * For example the creation of ResourceAssignmentProcessor's are mocked in multiple
69 * every {applicationContext.getBean("${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}???")}
70 * .returns( ResourceResolutionProcessorXXX() ) functions.
72 * The test is also based on UAT concept of the CDS project.
73 * The test makes usage of following classes:
75 * SpyService: Decorator for overwriting the function for handling the rest based communication with external systems
76 * fun exchangeResource(methodType: String,path: String,request: String,headers: Map<String, String>):
77 * WebClientResponse<String>
78 * Uses ExpectationDefinition from the uat.yaml
80 * uat.MockPreInterceptor: Interceptor that hooks in the factory method of creation the different rest clients for
82 * BluePrintRestLibPropertyService.blueprintWebClientService(selector: String): BlueprintWebClientService
83 * It is used for exchanging the "real service" by a mock (here a mockito based one)
85 * uat.SpyPostInterceptor: Interceptor that hooks in the factory method of creation the different rest clients for
87 * BluePrintRestLibPropertyService.blueprintWebClientService(selector: String): BlueprintWebClientService
88 * It is used to inject the uat.SpyService decorator
90 * In a whole we do have the following decorator chain: uat.SpyService ( Mockito mock (real service) )
92 * {@see UatDefinition}: Model of behaviour of external systems. Used at runtime as a representation for
93 * request / response correlation of the external systems. It is loaded from the uat.yaml
97 * - in the cba Definition folder the enriched data_types.json and node_types.json needs to be in the actual version.
98 * inside the json workflow file (e.g. parameter-consistency.json) the includes to these json must be available.
99 * - uat.yaml for UatDefinition must be inside the cba/Test/ directory of the cba. This uat.yaml file must be adapted,
100 * if the logic inside the steps changes.
101 * See https://wiki.onap.org/pages/viewpage.action?pageId=59965554#ModelingConcepts-tests for details
103 abstract class BaseUatResourceResolutionTest {
104 private val resolutionKey = "resolutionKey"
105 private val resourceId = "1"
106 private val resourceType = "ServiceInstance"
107 private val occurrence = 0
109 // protected, bacause they maybe needed to be manipulated in inherited test classes
110 protected val props = hashMapOf<String, Any>()
111 protected var preInterceptor = MockPreInterceptor()
112 protected var postInterceptor = SpyPostInterceptor(ObjectMapper())
113 protected lateinit var resourceResolutionService: ResourceResolutionService
114 protected lateinit var applicationContext : ApplicationContext
117 private val log: Logger = LoggerFactory.getLogger(BaseUatResourceResolutionTest::class.java)
118 private val mockLoggingListener = MockInvocationLogger(LogColor.markerOf(LogColor.COLOR_MOCKITO))
123 props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_STORE_RESULT] = false
124 props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_KEY] = resolutionKey
125 props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_ID] = resourceId
126 props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE] = resourceType
127 props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE] = occurrence
128 props[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY] = false
130 applicationContext = spyk(ReactiveWebServerApplicationContext())
131 val templateResolutionRepository = mockk<TemplateResolutionRepository>()
132 val templateResolutionService = spyk(TemplateResolutionService(templateResolutionRepository))
133 val bluePrintLoadConfiguration = spyk(BluePrintLoadConfiguration())
134 val bluePrintTemplateService = spyk(BluePrintTemplateService(bluePrintLoadConfiguration))
135 val resourceResolutionRepository = mockk<ResourceResolutionRepository>()
136 val resourceResolutionDBService = spyk(ResourceResolutionDBService(resourceResolutionRepository))
138 // ResourceResolutionService
139 resourceResolutionService = spyk(
140 ResourceResolutionServiceImpl(
142 templateResolutionService,
143 bluePrintTemplateService,
144 resourceResolutionDBService)
147 // BluePrintRestLibPropertyService: setInterceptors "MockPreInterceptor" and "SpyPostInterceptor"
148 val bluePrintPropertyConfiguration = spyk(BluePrintPropertyConfiguration())
149 val bluePrintPropertiesService = spyk(BluePrintPropertiesService(bluePrintPropertyConfiguration))
150 val bluePrintRestLibPropertyService = BluePrintRestLibPropertyService(bluePrintPropertiesService)
151 bluePrintRestLibPropertyService.setInterceptors(preInterceptor, postInterceptor)
153 // ComponentFunctionScriptingService needed for CapabilityResourceResolutionProcessor
154 val blueprintJythonService = spyk(DeprecatedBlueprintJythonService())
155 val componentFunctionScriptingService = ComponentFunctionScriptingService(applicationContext, blueprintJythonService)
157 // Add ResourceResolutionProcessor's to the Spring ApplicationContext
158 // if more needed, add them in your own setUp method in derived test class
159 every { applicationContext.getBean("${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-input") }.returns(
160 InputResourceResolutionProcessor()
162 every { applicationContext.getBean("${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-default") }.returns(
163 DefaultResourceResolutionProcessor()
165 every { applicationContext.getBean("${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-rest") }.returns(
166 RestResourceResolutionProcessor(bluePrintRestLibPropertyService)
168 every { applicationContext.getBean("${ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR}source-capability") }.returns(
169 CapabilityResourceResolutionProcessor(componentFunctionScriptingService)
172 // create the Mockit mocks defined in the uat.yaml
173 createMockitoMocksByUatDefinition()
176 private fun createMockitoMocksByUatDefinition() {
178 val cwd: String = Path.of("").toAbsolutePath().toString()
179 log.info("current working directory : $cwd")
181 val uatSpec: String = File("$cwd/Tests/uat.yaml").readText(Charsets.UTF_8)
182 val uat = UatDefinition.load(jacksonObjectMapper(), uatSpec)
183 val expectationsPerClient = uat.externalServices.associateBy(
185 createRestClientMock(service.expectations).also { restClient ->
186 // side-effect: register restClient to override real instance
187 preInterceptor.registerMock(service.selector, restClient)
190 { service -> service.expectations }
194 private fun createRestClientMock(restExpectations: List<ExpectationDefinition>):
195 BlueprintWebClientService {
196 val restClient = mock<BlueprintWebClientService>(
197 defaultAnswer = Answers.RETURNS_SMART_NULLS,
198 // our custom verboseLogging handler
199 invocationListeners = arrayOf(mockLoggingListener)
202 // Delegates to overloaded exchangeResource(String, String, String, Map<String, String>)
203 whenever(restClient.exchangeResource(any(), any(), any()))
204 .thenAnswer { invocation ->
205 val method = invocation.arguments[0] as String
206 val path = invocation.arguments[1] as String
207 val request = invocation.arguments[2] as String
208 restClient.exchangeResource(method, path, request, emptyMap())
210 for (expectation in restExpectations) {
211 var stubbing = whenever(
212 restClient.exchangeResource(
213 eq(expectation.request.method),
214 eq(expectation.request.path),
219 for (response in expectation.responses) {
220 stubbing = stubbing.thenReturn(
221 BlueprintWebClientService.WebClientResponse(
223 response.body.toString()
231 protected suspend fun callResolveResources(
232 blueprintBasePath: String,
233 fileNameExecutionServiceInput: String,
234 workflowName: String,
235 nodeTemplateName: String,
236 artifactPrefixName: String
237 ): Pair<String, MutableList<ResourceAssignment>> {
238 val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(
243 val executionServiceInput =
244 JacksonUtils.readValueFromFile(
245 fileNameExecutionServiceInput,
246 ExecutionServiceInput::class.java
249 val resourceAssignmentRuntimeService =
250 ResourceAssignmentUtils.transformToRARuntimeService(
251 bluePrintRuntimeService,
252 "testResolveResource"
256 PayloadUtils.prepareInputsFromWorkflowPayload(
257 bluePrintRuntimeService,
258 executionServiceInput.payload,
262 return resourceResolutionService.resolveResources(
263 resourceAssignmentRuntimeService,