2 * Copyright © 2019 IBM.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.ccsdk.cds.controllerblueprints.core.service
21 import kotlinx.coroutines.CompletableDeferred
22 import kotlinx.coroutines.async
23 import kotlinx.coroutines.awaitAll
24 import kotlinx.coroutines.coroutineScope
25 import kotlinx.coroutines.runBlocking
26 import kotlinx.coroutines.withTimeout
28 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
29 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
30 import org.onap.ccsdk.cds.controllerblueprints.core.data.EdgeLabel
31 import org.onap.ccsdk.cds.controllerblueprints.core.data.Graph
32 import org.onap.ccsdk.cds.controllerblueprints.core.logger
33 import org.onap.ccsdk.cds.controllerblueprints.core.toGraph
34 import kotlin.test.assertNotNull
36 class BluePrintWorkflowServiceTest {
38 fun testSimpleFlow() {
40 val graph = "[START>A/SUCCESS, A>B/SUCCESS, B>C/SUCCESS, C>D/SUCCESS, D>E/SUCCESS, E>END/SUCCESS]"
42 val simpleWorkflow = TestBluePrintWorkFlowService()
43 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D", "E"), null)
45 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
46 assertNotNull(response, "failed to get response")
51 fun testMultipleFlows() {
54 val wfs = listOf("12345", "12346").map {
56 val graph = "[START>A/SUCCESS, A>B/SUCCESS, B>C/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
58 val simpleWorkflow = TestBluePrintWorkFlowService()
59 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D"), null)
60 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(it), it)
61 assertNotNull(response, "failed to get response")
70 fun testMissingEdgeForBFailureState() {
72 val graph = "[START>A/SUCCESS, A>B/SUCCESS, B>C/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
74 val simpleWorkflow = TestBluePrintWorkFlowService()
75 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "C", "D", "E"), arrayListOf("B"))
77 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
78 assertNotNull(response, "failed to get response")
83 fun testBExceptionFlow() {
85 val graph = "[START>A/SUCCESS, A>B/SUCCESS, B>C/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
87 val simpleWorkflow = TestBluePrintWorkFlowService()
88 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "C", "D", "E"), null)
90 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
91 assertNotNull(response, "failed to get response")
96 fun testTimeoutExceptionFlow() {
98 val graph = "[START>A/SUCCESS, A>TO/SUCCESS, TO>C/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
100 val simpleWorkflow = TestBluePrintWorkFlowService()
101 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "TO", "C", "D", "E"), null)
103 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
104 assertNotNull(response, "failed to get response")
109 fun testConditionalFlow() {
111 val graph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/FAILURE, B>D/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
113 val simpleWorkflow = TestBluePrintWorkFlowService()
114 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D", "E"), null)
116 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
117 assertNotNull(response, "failed to get response")
122 fun testBothConditionalFlow() {
125 val failurePatGraph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/FAILURE, B>D/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
127 val failurePathWorkflow = TestBluePrintWorkFlowService()
128 failurePathWorkflow.simulatedState = prepareSimulation(
129 arrayListOf("B", "C", "D", "E"),
132 val failurePathWorkflowInput = "123456"
133 val failurePathResponse = failurePathWorkflow.executeWorkflow(failurePatGraph, mockBluePrintRuntimeService(), failurePathWorkflowInput)
134 assertNotNull(failurePathResponse, "failed to get response")
139 fun testMultipleSkipFlow() {
141 val graph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/FAILURE, C>D/SUCCESS, D>E/SUCCESS, B>E/SUCCESS, E>END/SUCCESS]"
143 val simpleWorkflow = TestBluePrintWorkFlowService()
144 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D", "E"), null)
146 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
147 assertNotNull(response, "failed to get response")
152 fun testParallelFlow() {
154 val graph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/SUCCESS, B>D/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
156 val simpleWorkflow = TestBluePrintWorkFlowService()
157 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D"), null)
159 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
160 assertNotNull(response, "failed to get response")
164 private fun mockBluePrintRuntimeService(): BluePrintRuntimeService<*> {
165 return mockBluePrintRuntimeService("123456")
168 private fun mockBluePrintRuntimeService(id: String): BluePrintRuntimeService<*> {
169 val bluePrintRuntimeService = mockk<BluePrintRuntimeService<*>>()
170 every { bluePrintRuntimeService.id() } returns id
171 return bluePrintRuntimeService
174 private fun prepareSimulation(successes: List<String>?, failures: List<String>?): MutableMap<String, EdgeLabel> {
175 val simulatedState: MutableMap<String, EdgeLabel> = hashMapOf()
177 simulatedState[it] = EdgeLabel.SUCCESS
180 simulatedState[it] = EdgeLabel.FAILURE
182 return simulatedState
186 class TestBluePrintWorkFlowService :
187 AbstractBluePrintWorkFlowService<String, String>() {
189 val log = logger(TestBluePrintWorkFlowService::class)
191 lateinit var simulatedState: MutableMap<String, EdgeLabel>
193 override suspend fun initializeWorkflow(input: String): EdgeLabel {
194 return EdgeLabel.SUCCESS
197 override suspend fun executeWorkflow(graph: Graph, bluePrintRuntimeService: BluePrintRuntimeService<*>, input: String): String {
198 log.info("Executing Graph : $graph")
200 this.workflowId = bluePrintRuntimeService.id()
201 val output = CompletableDeferred<String>()
202 val startMessage = WorkflowExecuteMessage(input, output)
203 val workflowActor = workflowActor()
204 if (!workflowActor.isClosedForSend) {
205 workflowActor().send(startMessage)
207 throw BluePrintProcessorException("workflow actor is closed for send $workflowActor")
209 return startMessage.output.await()
212 override suspend fun prepareNodeExecutionMessage(node: Graph.Node):
213 NodeExecuteMessage<String, String> {
214 return NodeExecuteMessage(node, "$node Input", "")
217 override suspend fun executeNode(
222 // val random = (1..10).random() * 100
223 // log.info("workflow($workflowId) node(${node.id}) will reply in $random ms")
224 // kotlinx.coroutines.delay(random.toLong())
225 // //Simulation for timeout
226 if (node.id == "TO") {
228 kotlinx.coroutines.delay(2)
231 return simulatedState[node.id] ?: throw BluePrintException("failed to get status for the node($node)")
234 override suspend fun prepareNodeSkipMessage(node: Graph.Node): NodeSkipMessage<String, String> {
236 return NodeSkipMessage(node, "$node Skip Input", nodeOutput)
239 override suspend fun skipNode(
244 return simulatedState[node.id] ?: throw BluePrintException("failed to get status for the node($node)")
247 override suspend fun cancelNode(
252 TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
255 override suspend fun restartNode(
260 TODO("not implemented") // To change body of created functions use File | Settings | File Templates.
263 override suspend fun prepareWorkflowOutput(): String {
264 if (exceptions.isNotEmpty()) {
266 log.error("workflow($workflowId) exceptions :", it)
269 return "Final Response"