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.*
23 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
24 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
25 import org.onap.ccsdk.cds.controllerblueprints.core.data.EdgeLabel
26 import org.onap.ccsdk.cds.controllerblueprints.core.data.Graph
27 import org.onap.ccsdk.cds.controllerblueprints.core.logger
28 import org.onap.ccsdk.cds.controllerblueprints.core.toGraph
29 import kotlin.test.assertNotNull
31 class BluePrintWorkflowServiceTest {
33 fun testSimpleFlow() {
35 val graph = "[START>A/SUCCESS, A>B/SUCCESS, B>C/SUCCESS, C>D/SUCCESS, D>E/SUCCESS, E>END/SUCCESS]"
37 val simpleWorkflow = TestBluePrintWorkFlowService()
38 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D", "E"), null)
40 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
41 assertNotNull(response, "failed to get response")
46 fun testMultipleFlows() {
49 val wfs = listOf("12345", "12346").map {
51 val graph = "[START>A/SUCCESS, A>B/SUCCESS, B>C/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
53 val simpleWorkflow = TestBluePrintWorkFlowService()
54 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D"), null)
55 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(it), it)
56 assertNotNull(response, "failed to get response")
65 fun testMissingEdgeForBFailureState() {
67 val graph = "[START>A/SUCCESS, A>B/SUCCESS, B>C/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
69 val simpleWorkflow = TestBluePrintWorkFlowService()
70 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "C", "D", "E"), arrayListOf("B"))
72 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
73 assertNotNull(response, "failed to get response")
78 fun testBExceptionFlow() {
80 val graph = "[START>A/SUCCESS, A>B/SUCCESS, B>C/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
82 val simpleWorkflow = TestBluePrintWorkFlowService()
83 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "C", "D", "E"), null)
85 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
86 assertNotNull(response, "failed to get response")
91 fun testTimeoutExceptionFlow() {
93 val graph = "[START>A/SUCCESS, A>TO/SUCCESS, TO>C/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
95 val simpleWorkflow = TestBluePrintWorkFlowService()
96 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "TO", "C", "D", "E"), null)
98 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
99 assertNotNull(response, "failed to get response")
104 fun testConditionalFlow() {
106 val graph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/FAILURE, B>D/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
108 val simpleWorkflow = TestBluePrintWorkFlowService()
109 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D", "E"), null)
111 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
112 assertNotNull(response, "failed to get response")
117 fun testBothConditionalFlow() {
120 val failurePatGraph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/FAILURE, B>D/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
122 val failurePathWorkflow = TestBluePrintWorkFlowService()
123 failurePathWorkflow.simulatedState = prepareSimulation(arrayListOf("B", "C", "D", "E"),
125 val failurePathWorkflowInput = "123456"
126 val failurePathResponse = failurePathWorkflow.executeWorkflow(failurePatGraph, mockBluePrintRuntimeService(), failurePathWorkflowInput)
127 assertNotNull(failurePathResponse, "failed to get response")
132 fun testMultipleSkipFlow() {
134 val graph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/FAILURE, C>D/SUCCESS, D>E/SUCCESS, B>E/SUCCESS, E>END/SUCCESS]"
136 val simpleWorkflow = TestBluePrintWorkFlowService()
137 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D", "E"), null)
139 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
140 assertNotNull(response, "failed to get response")
145 fun testParallelFlow() {
147 val graph = "[START>A/SUCCESS, A>B/SUCCESS, A>C/SUCCESS, B>D/SUCCESS, C>D/SUCCESS, D>END/SUCCESS]"
149 val simpleWorkflow = TestBluePrintWorkFlowService()
150 simpleWorkflow.simulatedState = prepareSimulation(arrayListOf("A", "B", "C", "D"), null)
152 val response = simpleWorkflow.executeWorkflow(graph, mockBluePrintRuntimeService(), input)
153 assertNotNull(response, "failed to get response")
157 private fun mockBluePrintRuntimeService(): BluePrintRuntimeService<*> {
158 return mockBluePrintRuntimeService("123456")
161 private fun mockBluePrintRuntimeService(id: String): BluePrintRuntimeService<*> {
162 val bluePrintRuntimeService = mockk<BluePrintRuntimeService<*>>()
163 every { bluePrintRuntimeService.id() } returns id
164 return bluePrintRuntimeService
167 private fun prepareSimulation(successes: List<String>?, failures: List<String>?): MutableMap<String, EdgeLabel> {
168 val simulatedState: MutableMap<String, EdgeLabel> = hashMapOf()
170 simulatedState[it] = EdgeLabel.SUCCESS
173 simulatedState[it] = EdgeLabel.FAILURE
175 return simulatedState
179 class TestBluePrintWorkFlowService
180 : AbstractBluePrintWorkFlowService<String, String>() {
181 val log = logger(TestBluePrintWorkFlowService::class)
183 lateinit var simulatedState: MutableMap<String, EdgeLabel>
185 override suspend fun initializeWorkflow(input: String): EdgeLabel {
186 return EdgeLabel.SUCCESS
189 override suspend fun executeWorkflow(graph: Graph, bluePrintRuntimeService: BluePrintRuntimeService<*>, input: String): String {
190 log.info("Executing Graph : $graph")
192 this.workflowId = bluePrintRuntimeService.id()
193 val output = CompletableDeferred<String>()
194 val startMessage = WorkflowExecuteMessage(input, output)
195 val workflowActor = workflowActor()
196 if (!workflowActor.isClosedForSend) {
197 workflowActor().send(startMessage)
199 throw BluePrintProcessorException("workflow actor is closed for send $workflowActor")
201 return startMessage.output.await()
204 override suspend fun prepareNodeExecutionMessage(node: Graph.Node)
205 : NodeExecuteMessage<String, String> {
206 return NodeExecuteMessage(node, "$node Input", "")
209 override suspend fun executeNode(node: Graph.Node, nodeInput: String,
210 nodeOutput: String): EdgeLabel {
211 // val random = (1..10).random() * 100
212 // log.info("workflow($workflowId) node(${node.id}) will reply in $random ms")
213 // kotlinx.coroutines.delay(random.toLong())
214 // //Simulation for timeout
215 if (node.id == "TO") {
217 kotlinx.coroutines.delay(2)
220 return simulatedState[node.id] ?: throw BluePrintException("failed to get status for the node($node)")
223 override suspend fun prepareNodeSkipMessage(node: Graph.Node): NodeSkipMessage<String, String> {
225 return NodeSkipMessage(node, "$node Skip Input", nodeOutput)
228 override suspend fun skipNode(node: Graph.Node, nodeInput: String,
229 nodeOutput: String): EdgeLabel {
230 return simulatedState[node.id] ?: throw BluePrintException("failed to get status for the node($node)")
233 override suspend fun cancelNode(node: Graph.Node, nodeInput: String,
234 nodeOutput: String): EdgeLabel {
235 TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
238 override suspend fun restartNode(node: Graph.Node, nodeInput: String,
239 nodeOutput: String): EdgeLabel {
240 TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
243 override suspend fun prepareWorkflowOutput(): String {
244 if (exceptions.isNotEmpty()) {
246 log.error("workflow($workflowId) exceptions :", it)
249 return "Final Response"