/******************************************************************************* * (c) Copyright 2016 Hewlett-Packard Development Company, L.P. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 which accompany this distribution. * * The Apache License is available at * http://www.apache.org/licenses/LICENSE-2.0 * *******************************************************************************/ package io.cloudslang.lang.runtime.steps; import io.cloudslang.dependency.api.services.DependencyService; import io.cloudslang.dependency.api.services.MavenConfig; import io.cloudslang.dependency.impl.services.DependencyServiceImpl; import io.cloudslang.dependency.impl.services.MavenConfigImpl; import io.cloudslang.lang.entities.ExecutableType; import io.cloudslang.lang.entities.ScoreLangConstants; import io.cloudslang.lang.entities.bindings.Input; import io.cloudslang.lang.entities.bindings.Output; import io.cloudslang.lang.entities.bindings.Result; import io.cloudslang.lang.entities.bindings.values.SensitiveValue; import io.cloudslang.lang.entities.bindings.values.Value; import io.cloudslang.lang.entities.bindings.values.ValueFactory; import io.cloudslang.lang.entities.encryption.DummyEncryptor; import io.cloudslang.lang.runtime.bindings.InputsBinding; import io.cloudslang.lang.runtime.bindings.OutputsBinding; import io.cloudslang.lang.runtime.bindings.ResultsBinding; import io.cloudslang.lang.runtime.bindings.scripts.ScriptEvaluator; import io.cloudslang.lang.runtime.env.ParentFlowData; import io.cloudslang.lang.runtime.env.ReturnValues; import io.cloudslang.lang.runtime.env.RunEnvironment; import io.cloudslang.lang.runtime.events.LanguageEventData; import io.cloudslang.runtime.api.python.PythonRuntimeService; import io.cloudslang.runtime.impl.python.PythonExecutionCachedEngine; import io.cloudslang.runtime.impl.python.PythonExecutionEngine; import io.cloudslang.runtime.impl.python.PythonRuntimeServiceImpl; import io.cloudslang.score.events.EventBus; import io.cloudslang.score.events.EventBusImpl; import io.cloudslang.score.events.ScoreEvent; import io.cloudslang.score.lang.ExecutionRuntimeServices; import junit.framework.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import static java.util.Collections.singletonList; import static org.mockito.Matchers.anyMap; import static org.mockito.Matchers.anyMapOf; import static org.mockito.Matchers.anySet; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = ExecutableStepsTest.Config.class) public class ExecutableStepsTest { @Autowired private ExecutableExecutionData executableSteps; @Autowired private InputsBinding inputsBinding; @Autowired private ResultsBinding resultsBinding; @Autowired private OutputsBinding outputsBinding; @Test public void testStart() throws Exception { executableSteps.startExecutable(new ArrayList<Input>(), new RunEnvironment(), new HashMap<String, Value>(), new ExecutionRuntimeServices(), "", 2L, ExecutableType.FLOW); } @Test public void testStartWithInput() throws Exception { List<Input> inputs = singletonList(new Input.InputBuilder("input1", "input1").build()); RunEnvironment runEnv = new RunEnvironment(); Map<String, Value> resultMap = new HashMap<>(); resultMap.put("input1", ValueFactory.create(5)); when(inputsBinding.bindInputs(eq(inputs), anyMap(), anySet())).thenReturn(resultMap); executableSteps.startExecutable(inputs, runEnv, new HashMap<String, Value>(), new ExecutionRuntimeServices(), "", 2L, ExecutableType.FLOW); Map<String, Value> opVars = runEnv.getStack().popContext().getImmutableViewOfVariables(); Assert.assertTrue(opVars.containsKey("input1")); Assert.assertEquals(5, opVars.get("input1").get()); Map<String, Value> callArg = runEnv.removeCallArguments(); Assert.assertEquals(1, callArg.size()); Assert.assertTrue(callArg.containsKey("input1")); Assert.assertEquals(5, callArg.get("input1").get()); } @Test public void testBoundInputEvent() { List<Input> inputs = Arrays.asList( new Input.InputBuilder("input1", 5).build(), new Input.InputBuilder("input2", 3, true) .withRequired(true) .withPrivateInput(false) .build() ); final RunEnvironment runEnv = new RunEnvironment(); final ExecutionRuntimeServices runtimeServices = new ExecutionRuntimeServices(); Map<String, Value> resultMap = new HashMap<>(); resultMap.put("input1", ValueFactory.create(inputs.get(0).getValue())); resultMap.put("input2", ValueFactory.create(inputs.get(1).getValue())); when(inputsBinding.bindInputs(eq(inputs), anyMap(), anySet())).thenReturn(resultMap); executableSteps.startExecutable(inputs, runEnv, new HashMap<String, Value>(), runtimeServices, "dockerizeStep", 2L, ExecutableType.FLOW); Collection<ScoreEvent> events = runtimeServices.getEvents(); Assert.assertFalse(events.isEmpty()); ScoreEvent boundInputEvent = null; for (ScoreEvent event : events) { if (event.getEventType().equals(ScoreLangConstants.EVENT_INPUT_END)) { boundInputEvent = event; } } Assert.assertNotNull(boundInputEvent); LanguageEventData eventData = (LanguageEventData) boundInputEvent.getData(); Assert.assertTrue(eventData.containsKey(LanguageEventData.BOUND_INPUTS)); @SuppressWarnings("unchecked") Map<String, Serializable> inputsBounded = (Map<String, Serializable>) eventData.get(LanguageEventData.BOUND_INPUTS); Assert.assertNotNull(eventData.getStepName()); Assert.assertEquals(LanguageEventData.StepType.FLOW, eventData.getStepType()); Assert.assertEquals("dockerizeStep", eventData.getStepName()); // verify input names are in defined order and have the expected value Set<Map.Entry<String, Serializable>> inputEntries = inputsBounded.entrySet(); Iterator<Map.Entry<String, Serializable>> inputNamesIterator = inputEntries.iterator(); Map.Entry<String, Serializable> firstInput = inputNamesIterator.next(); org.junit.Assert .assertEquals("Inputs are not in defined order in end inputs binding event", "input1", firstInput.getKey()); org.junit.Assert .assertEquals(5, firstInput.getValue()); Map.Entry<String, Serializable> secondInput = inputNamesIterator.next(); org.junit.Assert .assertEquals("Inputs are not in defined order in end inputs binding event", "input2", secondInput.getKey()); org.junit.Assert .assertEquals(SensitiveValue.SENSITIVE_VALUE_MASK, secondInput.getValue()); } @Test public void testStartExecutableSetNextPosition() throws Exception { List<Input> inputs = Arrays.asList(); RunEnvironment runEnv = new RunEnvironment(); Long nextStepPosition = 2L; executableSteps.startExecutable(inputs, runEnv, new HashMap<String, Value>(), new ExecutionRuntimeServices(), "", nextStepPosition, ExecutableType.FLOW); Assert.assertEquals(nextStepPosition, runEnv.removeNextStepPosition()); } @Test public void testFinishExecutableWithResult() throws Exception { List<Result> results = singletonList(new Result(ScoreLangConstants.SUCCESS_RESULT, ValueFactory.create("true"))); RunEnvironment runEnv = new RunEnvironment(); runEnv.putReturnValues(new ReturnValues(new HashMap<String, Value>(), null)); runEnv.getExecutionPath().down(); when(resultsBinding.resolveResult( isNull(Map.class), anyMapOf(String.class, Value.class), eq(runEnv.getSystemProperties()), eq(results), isNull(String.class) )).thenReturn(ScoreLangConstants.SUCCESS_RESULT); executableSteps.finishExecutable(runEnv, new ArrayList<Output>(), results, new ExecutionRuntimeServices(), "", ExecutableType.FLOW); ReturnValues returnValues = runEnv.removeReturnValues(); Assert.assertTrue(returnValues.getResult().equals(ScoreLangConstants.SUCCESS_RESULT)); } @Test public void testFinishExecutableWithOutput() throws Exception { final List<Output> possibleOutputs = Arrays.asList(new Output("name", ValueFactory.create("name"))); RunEnvironment runEnv = new RunEnvironment(); runEnv.putReturnValues(new ReturnValues(new HashMap<String, Value>(), null)); runEnv.getExecutionPath().down(); Map<String, Value> boundOutputs = new HashMap<>(); boundOutputs.put("name", ValueFactory.create("John")); when(outputsBinding.bindOutputs( isNull(Map.class), anyMapOf(String.class, Value.class), eq(runEnv.getSystemProperties()), eq(possibleOutputs) )).thenReturn(boundOutputs); executableSteps.finishExecutable(runEnv, possibleOutputs, new ArrayList<Result>(), new ExecutionRuntimeServices(), "", ExecutableType.FLOW); ReturnValues returnValues = runEnv.removeReturnValues(); Map<String, Value> outputs = returnValues.getOutputs(); Assert.assertEquals(1, outputs.size()); Assert.assertEquals("John", outputs.get("name").get()); } @Test public void testFinishExecutableSetNextPositionToParentFlow() throws Exception { RunEnvironment runEnv = new RunEnvironment(); runEnv.putReturnValues(new ReturnValues(new HashMap<String, Value>(), null)); runEnv.getExecutionPath().down(); Long parentFirstStepPosition = 2L; runEnv.getParentFlowStack().pushParentFlowData(new ParentFlowData(111L, parentFirstStepPosition)); executableSteps.finishExecutable(runEnv, new ArrayList<Output>(), new ArrayList<Result>(), new ExecutionRuntimeServices(), "", ExecutableType.FLOW); Assert.assertEquals(parentFirstStepPosition, runEnv.removeNextStepPosition()); } @Test public void testFinishExecutableSetNextPositionNoParentFlow() throws Exception { RunEnvironment runEnv = new RunEnvironment(); runEnv.putReturnValues(new ReturnValues(new HashMap<String, Value>(), null)); runEnv.getExecutionPath().down(); executableSteps.finishExecutable(runEnv, new ArrayList<Output>(), new ArrayList<Result>(), new ExecutionRuntimeServices(), "", ExecutableType.FLOW); Assert.assertEquals(null, runEnv.removeNextStepPosition()); } @Test public void testFinishExecutableEvents() { final List<Output> possibleOutputs = singletonList(new Output("name", ValueFactory.create("name", false))); final List<Result> possibleResults = singletonList(new Result(ScoreLangConstants.SUCCESS_RESULT, ValueFactory.create("true"))); RunEnvironment runEnv = new RunEnvironment(); runEnv.putReturnValues(new ReturnValues(new HashMap<String, Value>(), null)); runEnv.getExecutionPath().down(); Map<String, Value> boundOutputs = new HashMap<>(); boundOutputs.put("name", ValueFactory.create("John")); String boundResult = ScoreLangConstants.SUCCESS_RESULT; when(outputsBinding.bindOutputs( isNull(Map.class), anyMapOf(String.class, Value.class), eq(runEnv.getSystemProperties()), eq(possibleOutputs) )).thenReturn(boundOutputs); when(resultsBinding.resolveResult( isNull(Map.class), anyMapOf(String.class, Value.class), eq(runEnv.getSystemProperties()), eq(possibleResults), isNull(String.class) )).thenReturn(boundResult); ExecutionRuntimeServices runtimeServices = new ExecutionRuntimeServices(); executableSteps.finishExecutable(runEnv, possibleOutputs, possibleResults, runtimeServices, "step1", ExecutableType.FLOW); Collection<ScoreEvent> events = runtimeServices.getEvents(); Assert.assertFalse(events.isEmpty()); ScoreEvent boundOutputEvent = null; ScoreEvent startOutputEvent = null; ScoreEvent executableFinishedEvent = null; for (ScoreEvent event : events) { if (event.getEventType().equals(ScoreLangConstants.EVENT_OUTPUT_END)) { boundOutputEvent = event; } else if (event.getEventType().equals(ScoreLangConstants.EVENT_OUTPUT_START)) { startOutputEvent = event; } else if (event.getEventType().equals(ScoreLangConstants.EVENT_EXECUTION_FINISHED)) { executableFinishedEvent = event; } } Assert.assertNotNull(startOutputEvent); LanguageEventData eventData = (LanguageEventData) startOutputEvent.getData(); Assert.assertTrue(eventData.containsKey(ScoreLangConstants.EXECUTABLE_OUTPUTS_KEY)); Assert.assertTrue(eventData.containsKey(ScoreLangConstants.EXECUTABLE_RESULTS_KEY)); List<Output> outputs = (List<Output>) eventData.get(ScoreLangConstants.EXECUTABLE_OUTPUTS_KEY); List<Result> results = (List<Result>) eventData.get(ScoreLangConstants.EXECUTABLE_RESULTS_KEY); Assert.assertEquals(possibleOutputs, outputs); Assert.assertEquals(possibleResults, results); Assert.assertNotNull(boundOutputEvent); eventData = (LanguageEventData) boundOutputEvent.getData(); Assert.assertTrue(eventData.containsKey(LanguageEventData.OUTPUTS)); Map<String, Serializable> returnOutputs = eventData.getOutputs(); String returnResult = (String) eventData.get(LanguageEventData.RESULT); Assert.assertEquals("step1", eventData.getStepName()); Assert.assertEquals(LanguageEventData.StepType.FLOW, eventData.getStepType()); Assert.assertEquals(1, returnOutputs.size()); Assert.assertEquals("John", returnOutputs.get("name")); Assert.assertTrue(returnResult.equals(ScoreLangConstants.SUCCESS_RESULT)); Assert.assertNotNull(executableFinishedEvent); eventData = (LanguageEventData) executableFinishedEvent.getData(); String result = (String) eventData.get(LanguageEventData.RESULT); Map<String, Serializable> eventOutputs = (Map<String, Serializable>) eventData.get(LanguageEventData.OUTPUTS); Assert.assertEquals(ScoreLangConstants.SUCCESS_RESULT, result); Assert.assertEquals(boundOutputs.size(), eventOutputs.size()); for (Map.Entry<String, Value> entry : boundOutputs.entrySet()) { Assert.assertEquals(entry.getValue().get(), eventOutputs.get(entry.getKey())); } } @Configuration static class Config { @Bean public InputsBinding inputsBinding() { return mock(InputsBinding.class); } @Bean public OutputsBinding outputsBinding() { return mock(OutputsBinding.class); } @Bean public ResultsBinding resultsBinding() { return mock(ResultsBinding.class); } @Bean public ScriptEvaluator scriptEvaluator() { return mock(ScriptEvaluator.class); } @Bean public DependencyService mavenRepositoryService() { return new DependencyServiceImpl(); } @Bean public MavenConfig mavenConfig() { return new MavenConfigImpl(); } @Bean public PythonRuntimeService pythonRuntimeService() { return new PythonRuntimeServiceImpl(); } @Bean public PythonExecutionEngine pythonExecutionEngine() { return new PythonExecutionCachedEngine(); } @Bean public ExecutableExecutionData operationSteps() { return new ExecutableExecutionData(); } @Bean public DummyEncryptor dummyEncryptor() { return new DummyEncryptor(); } @Bean public EventBus eventBus() { return new EventBusImpl(); } } }