2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 Huawei Technologies Co., Ltd. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.ccsdk.cds.blueprintsprocessor.services.execution.scripts
23 import com.fasterxml.jackson.databind.JsonNode
24 import com.fasterxml.jackson.databind.ObjectMapper
25 import com.fasterxml.jackson.databind.node.ObjectNode
29 import io.mockk.verify
30 import kotlinx.coroutines.runBlocking
32 import org.junit.runner.RunWith
33 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ActionIdentifiers
34 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader
35 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
36 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData
37 import org.onap.ccsdk.cds.blueprintsprocessor.core.service.BluePrintClusterService
38 import org.onap.ccsdk.cds.blueprintsprocessor.core.service.CDS_LOCK_GROUP
39 import org.onap.ccsdk.cds.blueprintsprocessor.core.service.ClusterLock
40 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction
41 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService
42 import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.nodeTypeComponentScriptExecutor
43 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
44 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintError
45 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes
46 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
47 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
48 import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation
49 import org.onap.ccsdk.cds.controllerblueprints.core.data.LockAssignment
50 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
51 import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintScriptsServiceImpl
52 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
53 import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService
54 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
55 import org.springframework.beans.factory.annotation.Autowired
56 import org.springframework.test.context.ContextConfiguration
57 import org.springframework.test.context.junit4.SpringRunner
58 import kotlin.test.BeforeTest
59 import kotlin.test.assertEquals
60 import kotlin.test.assertNotNull
63 * Unit test cases for abstract component function.
65 @RunWith(SpringRunner::class)
66 @ContextConfiguration(
68 ComponentFunctionScriptingService::class,
69 BluePrintScriptsServiceImpl::class, DeprecatedBlueprintJythonService::class
72 class AbstractComponentFunctionTest {
74 lateinit var bluePrintRuntimeService: DefaultBluePrintRuntimeService
75 lateinit var blueprintContext: BluePrintContext
76 lateinit var blueprintClusterService: BluePrintClusterService
79 lateinit var compSvc: ComponentFunctionScriptingService
83 bluePrintRuntimeService = mockk()
84 blueprintContext = mockk()
85 blueprintClusterService = mockk()
86 every { bluePrintRuntimeService.bluePrintContext() } returns blueprintContext
88 every { blueprintContext.rootPath } returns normalizedPathName("target")
90 blueprintContext.nodeTemplateOperationImplementation(
93 } returns Implementation()
95 every { bluePrintRuntimeService.getBluePrintError() } returns BluePrintError()
99 fun testAbstractComponent() {
101 val samp = SampleComponent()
102 val comp = samp as AbstractComponentFunction
104 comp.bluePrintRuntimeService = bluePrintRuntimeService
105 comp.stepName = "sample-step"
106 assertNotNull(comp, "failed to get kotlin instance")
108 val input = getMockedInput(bluePrintRuntimeService)
110 val output = comp.applyNB(input)
112 assertEquals(output.actionIdentifiers.actionName, "activate")
113 assertEquals(output.commonHeader.requestId, "1234")
114 assertEquals(output.stepData!!.name, "activate-restconf")
115 assertEquals(output.status.message, "success")
120 fun testComponentFunctionPayload() {
121 val sampleComponent = SampleComponent()
122 sampleComponent.workflowName = "sample-action"
123 sampleComponent.executionServiceInput = JacksonUtils.readValueFromClassPathFile(
124 "payload/requests/sample-execution-request.json", ExecutionServiceInput::class.java
126 val payload = sampleComponent.requestPayload()
127 assertNotNull(payload, "failed to get payload")
128 val data = sampleComponent.requestPayloadActionProperty("data")?.first()
129 assertNotNull(data, "failed to get payload request action data")
133 fun testAbstractScriptComponent() {
135 val samp = SampleRestconfComponent(compSvc)
136 val comp = samp as AbstractComponentFunction
138 comp.bluePrintRuntimeService = bluePrintRuntimeService
139 comp.stepName = "sample-step"
140 assertNotNull(comp, "failed to get kotlin instance")
142 val input = getMockedInput(bluePrintRuntimeService)
144 val output = comp.applyNB(input)
146 assertEquals(output.actionIdentifiers.actionName, "activate")
147 assertEquals(output.commonHeader.requestId, "1234")
148 assertEquals(output.stepData!!.name, "activate-restconf")
149 assertEquals(output.status.message, "success")
154 fun testComponentScriptExecutorNodeType() {
155 val componentScriptExecutor = BluePrintTypes.nodeTypeComponentScriptExecutor()
156 assertNotNull(componentScriptExecutor.interfaces, "failed to get interface operations")
160 fun `prepareRequestNB should resolve lock properties`() {
161 val implementation = Implementation().apply {
162 this.lock = LockAssignment().apply {
163 this.key = """ {"get_input": "lock-key"} """.asJsonPrimitive()
167 blueprintContext.nodeTemplateOperationImplementation(any(), any(), any())
168 } returns implementation
171 bluePrintRuntimeService.resolvePropertyAssignments(any(), any(), any())
172 } returns mutableMapOf(
173 "key" to "abc-123-def-456".asJsonType(),
174 "acquireTimeout" to implementation.lock!!.acquireTimeout
177 val component: AbstractComponentFunction = SampleComponent()
178 component.bluePrintRuntimeService = bluePrintRuntimeService
179 component.bluePrintClusterService = blueprintClusterService
182 component.prepareRequestNB(getMockedInput(bluePrintRuntimeService))
185 val resolvedLock = component.implementation.lock!!
187 assertEquals("abc-123-def-456", resolvedLock.key.textValue())
189 assertEquals(180, resolvedLock.acquireTimeout.intValue())
192 @Test(expected = Exception::class)
193 fun `prepareRequestNB should throw exception if it fails to resolve lock key`() {
195 blueprintContext.nodeTemplateOperationImplementation(any(), any(), any())
196 } returns Implementation().apply { this.lock = LockAssignment() }
199 bluePrintRuntimeService.resolvePropertyAssignments(any(), any(), any())
200 } returns mutableMapOf(
201 "key" to "".asJsonType(),
202 "acquireTimeout" to Integer(360).asJsonType()
205 val component: AbstractComponentFunction = SampleComponent()
206 component.bluePrintRuntimeService = bluePrintRuntimeService
207 component.bluePrintClusterService = blueprintClusterService
210 component.prepareRequestNB(getMockedInput(bluePrintRuntimeService))
215 fun `applyNB should catch exceptions and call recoverNB`() {
216 val exception = RuntimeException("Intentional test exception")
218 bluePrintRuntimeService.resolvePropertyAssignments(any(), any(), any())
221 blueprintContext.nodeTemplateOperationImplementation(any(), any(), any())
222 } returns Implementation().apply {
223 this.lock = LockAssignment().apply { this.key = "testing-lock".asJsonType() }
226 val component: AbstractComponentFunction = spyk(SampleComponent())
227 component.bluePrintRuntimeService = bluePrintRuntimeService
228 component.bluePrintClusterService = blueprintClusterService
229 val input = getMockedInput(bluePrintRuntimeService)
231 runBlocking { component.applyNB(input) }
232 verify { runBlocking { component.recoverNB(exception, input) } }
236 fun `applyNB - when lock is present use ClusterLock`() {
238 val lockName = "testing-lock"
241 blueprintContext.nodeTemplateOperationImplementation(any(), any(), any())
242 } returns Implementation().apply {
243 this.lock = LockAssignment().apply { this.key = lockName.asJsonType() }
247 bluePrintRuntimeService.resolvePropertyAssignments(any(), any(), any())
248 } returns mutableMapOf(
249 "key" to lockName.asJsonType(),
250 "acquireTimeout" to Integer(180).asJsonType()
253 val clusterLock: ClusterLock = mockk()
255 every { clusterLock.name() } returns lockName
256 every { runBlocking { clusterLock.tryLock(any()) } } returns true
257 every { runBlocking { clusterLock.unLock() } } returns Unit
260 runBlocking { blueprintClusterService.clusterLock(any()) }
261 } returns clusterLock
263 val component: AbstractComponentFunction = SampleComponent()
264 component.bluePrintRuntimeService = bluePrintRuntimeService
265 component.bluePrintClusterService = blueprintClusterService
268 component.applyNB(getMockedInput(bluePrintRuntimeService))
272 runBlocking { blueprintClusterService.clusterLock("$lockName@$CDS_LOCK_GROUP") }
274 verify { runBlocking { clusterLock.unLock() } }
278 * Mocked input for abstract function test.
280 private fun getMockedInput(bluePrintRuntime: DefaultBluePrintRuntimeService):
281 ExecutionServiceInput {
283 val mapper = ObjectMapper()
284 val rootNode = mapper.createObjectNode()
285 rootNode.put("ip-address", "0.0.0.0")
286 rootNode.put("type", "rest")
288 val operationInputs = hashMapOf<String, JsonNode>()
289 operationInputs[BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE] =
290 "activate-restconf".asJsonPrimitive()
291 operationInputs[BluePrintConstants.PROPERTY_CURRENT_INTERFACE] =
292 "interfaceName".asJsonPrimitive()
293 operationInputs[BluePrintConstants.PROPERTY_CURRENT_OPERATION] =
294 "operationName".asJsonPrimitive()
295 operationInputs["dynamic-properties"] = rootNode
297 val stepInputData = StepData().apply {
298 name = "activate-restconf"
299 properties = operationInputs
301 val executionServiceInput = ExecutionServiceInput().apply {
302 commonHeader = CommonHeader().apply {
305 actionIdentifiers = ActionIdentifiers().apply {
306 actionName = "activate"
308 payload = JacksonUtils.jsonNode("{}") as ObjectNode
310 executionServiceInput.stepData = stepInputData
313 bluePrintRuntime.resolveNodeTemplateInterfaceOperationInputs(
314 "activate-restconf", "interfaceName", "operationName"
316 } returns operationInputs
318 val operationOutputs = hashMapOf<String, JsonNode>()
320 bluePrintRuntime.resolveNodeTemplateInterfaceOperationOutputs(
321 "activate-restconf", "interfaceName", "operationName"
323 } returns operationOutputs
324 every { bluePrintRuntime.bluePrintContext() } returns blueprintContext
326 return executionServiceInput