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.BlueprintTypes
45 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
46 import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
47 import org.onap.ccsdk.cds.controllerblueprints.core.data.Implementation
48 import org.onap.ccsdk.cds.controllerblueprints.core.data.LockAssignment
49 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
50 import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BlueprintScriptsServiceImpl
51 import org.onap.ccsdk.cds.controllerblueprints.core.service.BlueprintContext
52 import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBlueprintRuntimeService
53 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
54 import org.springframework.beans.factory.annotation.Autowired
55 import org.springframework.test.context.ContextConfiguration
56 import org.springframework.test.context.junit4.SpringRunner
57 import kotlin.test.BeforeTest
58 import kotlin.test.assertEquals
59 import kotlin.test.assertNotNull
62 * Unit test cases for abstract component function.
64 @RunWith(SpringRunner::class)
65 @ContextConfiguration(
67 ComponentFunctionScriptingService::class,
68 BlueprintScriptsServiceImpl::class, DeprecatedBlueprintJythonService::class
71 class AbstractComponentFunctionTest {
73 lateinit var bluePrintRuntimeService: DefaultBlueprintRuntimeService
74 lateinit var blueprintContext: BlueprintContext
75 lateinit var blueprintClusterService: BlueprintClusterService
78 lateinit var compSvc: ComponentFunctionScriptingService
82 bluePrintRuntimeService = mockk()
83 blueprintContext = mockk()
84 blueprintClusterService = mockk()
85 every { bluePrintRuntimeService.bluePrintContext() } returns blueprintContext
87 every { blueprintContext.rootPath } returns normalizedPathName("target")
89 blueprintContext.nodeTemplateOperationImplementation(
92 } returns Implementation()
96 fun testAbstractComponent() {
98 val samp = SampleComponent()
99 val comp = samp as AbstractComponentFunction
101 comp.bluePrintRuntimeService = bluePrintRuntimeService
102 comp.stepName = "sample-step"
103 assertNotNull(comp, "failed to get kotlin instance")
105 val input = getMockedInput(bluePrintRuntimeService)
107 val output = comp.applyNB(input)
109 assertEquals(output.actionIdentifiers.actionName, "activate")
110 assertEquals(output.commonHeader.requestId, "1234")
111 assertEquals(output.stepData!!.name, "activate-restconf")
112 assertEquals(output.status.message, "success")
117 fun testComponentFunctionPayload() {
118 val sampleComponent = SampleComponent()
119 sampleComponent.workflowName = "sample-action"
120 sampleComponent.executionServiceInput = JacksonUtils.readValueFromClassPathFile(
121 "payload/requests/sample-execution-request.json", ExecutionServiceInput::class.java
123 val payload = sampleComponent.requestPayload()
124 assertNotNull(payload, "failed to get payload")
125 val data = sampleComponent.requestPayloadActionProperty("data")?.first()
126 assertNotNull(data, "failed to get payload request action data")
130 fun testAbstractScriptComponent() {
132 val samp = SampleRestconfComponent(compSvc)
133 val comp = samp as AbstractComponentFunction
135 comp.bluePrintRuntimeService = bluePrintRuntimeService
136 comp.stepName = "sample-step"
137 assertNotNull(comp, "failed to get kotlin instance")
139 val input = getMockedInput(bluePrintRuntimeService)
141 val output = comp.applyNB(input)
143 assertEquals(output.actionIdentifiers.actionName, "activate")
144 assertEquals(output.commonHeader.requestId, "1234")
145 assertEquals(output.stepData!!.name, "activate-restconf")
146 assertEquals(output.status.message, "success")
151 fun testComponentScriptExecutorNodeType() {
152 val componentScriptExecutor = BlueprintTypes.nodeTypeComponentScriptExecutor()
153 assertNotNull(componentScriptExecutor.interfaces, "failed to get interface operations")
157 fun `prepareRequestNB should resolve lock properties`() {
158 val implementation = Implementation().apply {
159 this.lock = LockAssignment().apply {
160 this.key = """ {"get_input": "lock-key"} """.asJsonPrimitive()
164 blueprintContext.nodeTemplateOperationImplementation(any(), any(), any())
165 } returns implementation
168 bluePrintRuntimeService.resolvePropertyAssignments(any(), any(), any())
169 } returns mutableMapOf(
170 "key" to "abc-123-def-456".asJsonType(),
171 "acquireTimeout" to implementation.lock!!.acquireTimeout
174 val component: AbstractComponentFunction = SampleComponent()
175 component.bluePrintRuntimeService = bluePrintRuntimeService
176 component.bluePrintClusterService = blueprintClusterService
179 component.prepareRequestNB(getMockedInput(bluePrintRuntimeService))
182 val resolvedLock = component.implementation.lock!!
184 assertEquals("abc-123-def-456", resolvedLock.key.textValue())
186 assertEquals(180, resolvedLock.acquireTimeout.intValue())
189 @Test(expected = Exception::class)
190 fun `prepareRequestNB should throw exception if it fails to resolve lock key`() {
192 blueprintContext.nodeTemplateOperationImplementation(any(), any(), any())
193 } returns Implementation().apply { this.lock = LockAssignment() }
196 bluePrintRuntimeService.resolvePropertyAssignments(any(), any(), any())
197 } returns mutableMapOf(
198 "key" to "".asJsonType(),
199 "acquireTimeout" to Integer(360).asJsonType()
202 val component: AbstractComponentFunction = SampleComponent()
203 component.bluePrintRuntimeService = bluePrintRuntimeService
204 component.bluePrintClusterService = blueprintClusterService
207 component.prepareRequestNB(getMockedInput(bluePrintRuntimeService))
212 fun `applyNB should catch exceptions and call recoverNB`() {
213 val exception = RuntimeException("Intentional test exception")
215 bluePrintRuntimeService.resolvePropertyAssignments(any(), any(), any())
218 blueprintContext.nodeTemplateOperationImplementation(any(), any(), any())
219 } returns Implementation().apply {
220 this.lock = LockAssignment().apply { this.key = "testing-lock".asJsonType() }
223 val component: AbstractComponentFunction = spyk(SampleComponent())
224 component.bluePrintRuntimeService = bluePrintRuntimeService
225 component.bluePrintClusterService = blueprintClusterService
226 val input = getMockedInput(bluePrintRuntimeService)
228 runBlocking { component.applyNB(input) }
229 verify { runBlocking { component.recoverNB(exception, input) } }
233 fun `applyNB - when lock is present use ClusterLock`() {
235 val lockName = "testing-lock"
238 blueprintContext.nodeTemplateOperationImplementation(any(), any(), any())
239 } returns Implementation().apply {
240 this.lock = LockAssignment().apply { this.key = lockName.asJsonType() }
244 bluePrintRuntimeService.resolvePropertyAssignments(any(), any(), any())
245 } returns mutableMapOf(
246 "key" to lockName.asJsonType(),
247 "acquireTimeout" to Integer(180).asJsonType()
250 val clusterLock: ClusterLock = mockk()
252 every { clusterLock.name() } returns lockName
253 every { runBlocking { clusterLock.tryLock(any()) } } returns true
254 every { runBlocking { clusterLock.unLock() } } returns Unit
257 runBlocking { blueprintClusterService.clusterLock(any()) }
258 } returns clusterLock
260 val component: AbstractComponentFunction = SampleComponent()
261 component.bluePrintRuntimeService = bluePrintRuntimeService
262 component.bluePrintClusterService = blueprintClusterService
265 component.applyNB(getMockedInput(bluePrintRuntimeService))
269 runBlocking { blueprintClusterService.clusterLock("$lockName@$CDS_LOCK_GROUP") }
271 verify { runBlocking { clusterLock.unLock() } }
275 * Mocked input for abstract function test.
277 private fun getMockedInput(bluePrintRuntime: DefaultBlueprintRuntimeService):
278 ExecutionServiceInput {
280 val mapper = ObjectMapper()
281 val rootNode = mapper.createObjectNode()
282 rootNode.put("ip-address", "0.0.0.0")
283 rootNode.put("type", "rest")
285 val operationInputs = hashMapOf<String, JsonNode>()
286 operationInputs[BlueprintConstants.PROPERTY_CURRENT_NODE_TEMPLATE] =
287 "activate-restconf".asJsonPrimitive()
288 operationInputs[BlueprintConstants.PROPERTY_CURRENT_INTERFACE] =
289 "interfaceName".asJsonPrimitive()
290 operationInputs[BlueprintConstants.PROPERTY_CURRENT_OPERATION] =
291 "operationName".asJsonPrimitive()
292 operationInputs["dynamic-properties"] = rootNode
294 val stepInputData = StepData().apply {
295 name = "activate-restconf"
296 properties = operationInputs
298 val executionServiceInput = ExecutionServiceInput().apply {
299 commonHeader = CommonHeader().apply {
302 actionIdentifiers = ActionIdentifiers().apply {
303 actionName = "activate"
305 payload = JacksonUtils.jsonNode("{}") as ObjectNode
307 executionServiceInput.stepData = stepInputData
310 bluePrintRuntime.resolveNodeTemplateInterfaceOperationInputs(
311 "activate-restconf", "interfaceName", "operationName"
313 } returns operationInputs
315 val operationOutputs = hashMapOf<String, JsonNode>()
317 bluePrintRuntime.resolveNodeTemplateInterfaceOperationOutputs(
318 "activate-restconf", "interfaceName", "operationName"
320 } returns operationOutputs
321 every { bluePrintRuntime.bluePrintContext() } returns blueprintContext
323 return executionServiceInput