/*******************************************************************************
* (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.compiler;
import io.cloudslang.lang.compiler.configuration.SlangCompilerSpringConfig;
import io.cloudslang.lang.compiler.modeller.model.Executable;
import io.cloudslang.lang.compiler.modeller.model.Flow;
import io.cloudslang.lang.compiler.modeller.model.Step;
import io.cloudslang.lang.entities.CompilationArtifact;
import io.cloudslang.lang.entities.ListLoopStatement;
import io.cloudslang.lang.entities.ResultNavigation;
import io.cloudslang.lang.entities.ScoreLangConstants;
import io.cloudslang.lang.entities.bindings.Output;
import io.cloudslang.lang.entities.bindings.values.ValueFactory;
import io.cloudslang.score.api.ExecutionPlan;
import io.cloudslang.score.api.ExecutionStep;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Date: 3/25/2015
*
* @author Bonczidai Levente
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SlangCompilerSpringConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class CompileParallelLoopFlowTest {
@Autowired
private SlangCompiler compiler;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testPreCompileParallelLoopFlow() throws Exception {
Step step = getStepsAfterPrecompileFlow("/loops/parallel_loop/simple_parallel_loop.sl").getFirst();
verifyParallelLoopStatement(step);
List<Output> publishValues = getPublishOutputs(step);
assertEquals("publish list is not empty", 0, publishValues.size());
List<Map<String, String>> expectedNavigationStrings = new ArrayList<>();
Map<String, String> successMap = new HashMap<>();
successMap.put(ScoreLangConstants.SUCCESS_RESULT, "SUCCESS");
Map<String, String> failureMap = new HashMap<>();
failureMap.put(ScoreLangConstants.FAILURE_RESULT, "FAILURE");
expectedNavigationStrings.add(successMap);
expectedNavigationStrings.add(failureMap);
verifyNavigationStrings(expectedNavigationStrings, step);
assertTrue(step.isParallelLoop());
}
@Test
public void testPreCompileParallelLoopFlowPublish() throws Exception {
Step step = getStepsAfterPrecompileFlow("/loops/parallel_loop/parallel_loop_publish.sl").getFirst();
verifyParallelLoopStatement(step);
List<Output> publishValues = getPublishOutputs(step);
assertEquals(2, publishValues.size());
assertEquals("${ map(lambda x:str(x['name']), branches_context) }", publishValues.get(0).getValue().get());
List<Map<String, String>> expectedNavigationStrings = new ArrayList<>();
Map<String, String> successMap = new HashMap<>();
successMap.put(ScoreLangConstants.SUCCESS_RESULT, "SUCCESS");
Map<String, String> failureMap = new HashMap<>();
failureMap.put(ScoreLangConstants.FAILURE_RESULT, "FAILURE");
expectedNavigationStrings.add(successMap);
expectedNavigationStrings.add(failureMap);
verifyNavigationStrings(expectedNavigationStrings, step);
assertTrue(step.isParallelLoop());
}
@Test
public void testPreCompileParallelLoopFlowNavigate() throws Exception {
Deque<Step> steps = getStepsAfterPrecompileFlow("/loops/parallel_loop/parallel_loop_navigate.sl");
assertEquals(2, steps.size());
Step parallelStep = steps.getFirst();
verifyParallelLoopStatement(parallelStep);
List<Output> publishValues = getPublishOutputs(parallelStep);
assertEquals(0, publishValues.size());
List<Map<String, String>> expectedNavigationStrings = new ArrayList<>();
Map<String, String> successMap = new HashMap<>();
successMap.put(ScoreLangConstants.SUCCESS_RESULT, "print_list");
Map<String, String> failureMap = new HashMap<>();
failureMap.put(ScoreLangConstants.FAILURE_RESULT, "FAILURE");
expectedNavigationStrings.add(successMap);
expectedNavigationStrings.add(failureMap);
verifyNavigationStrings(expectedNavigationStrings, parallelStep);
assertTrue(parallelStep.isParallelLoop());
}
@Test
public void testPreCompileParallelLoopFlowPublishNavigate() throws Exception {
Deque<Step> steps = getStepsAfterPrecompileFlow("/loops/parallel_loop/parallel_loop_publish_navigate.sl");
assertEquals(2, steps.size());
Step parallelStep = steps.getFirst();
verifyParallelLoopStatement(parallelStep);
List<Output> publishValues = getPublishOutputs(parallelStep);
assertEquals(2, publishValues.size());
assertEquals("${ map(lambda x:str(x['name']), branches_context) }", publishValues.get(0).getValue().get());
List<Map<String, String>> expectedNavigationStrings = new ArrayList<>();
Map<String, String> successMap = new HashMap<>();
successMap.put(ScoreLangConstants.SUCCESS_RESULT, "print_list");
Map<String, String> failureMap = new HashMap<>();
failureMap.put(ScoreLangConstants.FAILURE_RESULT, "FAILURE");
expectedNavigationStrings.add(successMap);
expectedNavigationStrings.add(failureMap);
verifyNavigationStrings(expectedNavigationStrings, parallelStep);
assertTrue(parallelStep.isParallelLoop());
}
@Test
public void testCompileParallelLoopFlow() throws Exception {
final URI flow = getClass().getResource("/loops/parallel_loop/simple_parallel_loop.sl").toURI();
final URI operation = getClass().getResource("/loops/parallel_loop/print_branch.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation));
CompilationArtifact artifact = compiler.compile(SlangSource.fromFile(flow), path);
assertNotNull("artifact is null", artifact);
ExecutionPlan executionPlan = artifact.getExecutionPlan();
assertNotNull("executionPlan is null", executionPlan);
ExecutionStep addBranchesStep = executionPlan.getStep(2L);
assertTrue("add branches step is not marked as split step", addBranchesStep.isSplitStep());
Map<String, ?> addBranchesActionData = addBranchesStep.getActionData();
verifyParallelLoopStatement(addBranchesActionData);
assertNotNull("branch begin step method not found", executionPlan.getStep(3L));
assertNotNull("branch end step method not found", executionPlan.getStep(4L));
assertNotNull("join branches method not found", executionPlan.getStep(5L));
}
@Test
public void testCompileParallelLoopFlowPublish() throws Exception {
final URI flow = getClass().getResource("/loops/parallel_loop/parallel_loop_publish.sl").toURI();
final URI operation = getClass().getResource("/loops/parallel_loop/print_branch.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation));
CompilationArtifact artifact = compiler.compile(SlangSource.fromFile(flow), path);
assertNotNull("artifact is null", artifact);
ExecutionPlan executionPlan = artifact.getExecutionPlan();
assertNotNull("executionPlan is null", executionPlan);
ExecutionStep addBranchesStep = executionPlan.getStep(2L);
assertTrue("add branches step is not marked as split step", addBranchesStep.isSplitStep());
Map<String, ?> addBranchesActionData = addBranchesStep.getActionData();
verifyParallelLoopStatement(addBranchesActionData);
ExecutionStep joinBranchesStep = executionPlan.getStep(5L);
Map<String, ?> joinBranchesActionData = joinBranchesStep.getActionData();
verifyPublishValues(joinBranchesActionData);
assertNotNull("branch begin step method not found", executionPlan.getStep(3L));
ExecutionStep branchEndStepExecutionStep = executionPlan.getStep(4L);
assertNotNull("branch end step method not found", branchEndStepExecutionStep);
verifyBranchPublishValuesIsEmpty(branchEndStepExecutionStep.getActionData());
}
@Test
public void testCompileParallelLoopFlowNavigate() throws Exception {
final URI flow = getClass().getResource("/loops/parallel_loop/parallel_loop_navigate.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
CompilationArtifact artifact = compiler.compile(SlangSource.fromFile(flow), path);
assertNotNull("artifact is null", artifact);
ExecutionPlan executionPlan = artifact.getExecutionPlan();
assertNotNull("executionPlan is null", executionPlan);
ExecutionStep addBranchesStep = executionPlan.getStep(2L);
assertTrue("add branches step is not marked as split step", addBranchesStep.isSplitStep());
Map<String, ?> addBranchesActionData = addBranchesStep.getActionData();
verifyParallelLoopStatement(addBranchesActionData);
ExecutionStep joinBranchesStep = executionPlan.getStep(5L);
Map<String, ?> joinBranchesActionData = joinBranchesStep.getActionData();
verifyNavigationValuesSuccessFailure(joinBranchesActionData);
assertNotNull("branch begin step method not found", executionPlan.getStep(3L));
assertNotNull("branch end step method not found", executionPlan.getStep(4L));
}
@Test
public void testCompileParallelLoopFlowNavigateDefault() throws Exception {
final URI flow = getClass().getResource("/loops/parallel_loop/parallel_loop_navigate_default.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
CompilationArtifact artifact = compiler.compile(SlangSource.fromFile(flow), path);
assertNotNull("artifact is null", artifact);
ExecutionPlan executionPlan = artifact.getExecutionPlan();
assertNotNull("executionPlan is null", executionPlan);
ExecutionStep addBranchesStep = executionPlan.getStep(2L);
assertTrue("add branches step is not marked as split step", addBranchesStep.isSplitStep());
Map<String, ?> addBranchesActionData = addBranchesStep.getActionData();
verifyParallelLoopStatement(addBranchesActionData);
ExecutionStep joinBranchesStep = executionPlan.getStep(5L);
Map<String, ?> joinBranchesActionData = joinBranchesStep.getActionData();
verifyNavigationValuesSuccessFailure(joinBranchesActionData);
assertNotNull("branch begin step method not found", executionPlan.getStep(3L));
assertNotNull("branch end step method not found", executionPlan.getStep(4L));
}
@Test
public void testCompileParallelLoopFlowNavigateDefaultCustom() throws Exception {
final URI flow = getClass()
.getResource("/loops/parallel_loop/parallel_loop_navigate_default_custom.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch_custom_only.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
expectedException.expect(RuntimeException.class);
expectedException.expectMessage(
"Cannot compile flow 'parallel_loop_navigate_default_custom' since for step 'print_values' " +
"the navigation keys [FAILURE] have no matching results. The parallel loop depending on " +
"'loops.parallel_loop.print_branch_custom_only' can have the following results: [SUCCESS]."
);
compiler.compile(SlangSource.fromFile(flow), path);
}
@Test
public void testCompileParallelLoopFlowNavigateCustom() throws Exception {
final URI flow = getClass().getResource("/loops/parallel_loop/parallel_loop_navigate_custom.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch_custom_only.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
CompilationArtifact artifact = compiler.compile(SlangSource.fromFile(flow), path);
assertNotNull("artifact is null", artifact);
ExecutionPlan executionPlan = artifact.getExecutionPlan();
assertNotNull("executionPlan is null", executionPlan);
ExecutionStep addBranchesStep = executionPlan.getStep(2L);
assertTrue("add branches step is not marked as split step", addBranchesStep.isSplitStep());
Map<String, ?> addBranchesActionData = addBranchesStep.getActionData();
verifyParallelLoopStatement(addBranchesActionData);
ExecutionStep joinBranchesStep = executionPlan.getStep(5L);
Map<String, ?> joinBranchesActionData = joinBranchesStep.getActionData();
verifyNavigationValuesSuccess(joinBranchesActionData);
assertNotNull("branch begin step method not found", executionPlan.getStep(3L));
assertNotNull("branch end step method not found", executionPlan.getStep(4L));
}
@Test
public void testCompileParallelLoopFlowNavigateDefaultSuccessOnly() throws Exception {
final URI flow = getClass()
.getResource("/loops/parallel_loop/parallel_loop_navigate_default_success_only.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch_success_only.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
expectedException.expect(RuntimeException.class);
expectedException.expectMessage(
"Cannot compile flow 'parallel_loop_navigate_default_success_only' since for step 'print_values' " +
"the navigation keys [FAILURE] have no matching results. The parallel loop depending on " +
"'loops.parallel_loop.print_branch_success_only' can have the following results: [SUCCESS]."
);
compiler.compile(SlangSource.fromFile(flow), path);
}
@Test
public void testCompileParallelLoopFlowNavigateSuccessOnly() throws Exception {
final URI flow = getClass().getResource("/loops/parallel_loop/parallel_loop_navigate_success_only.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch_success_only.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
CompilationArtifact artifact = compiler.compile(SlangSource.fromFile(flow), path);
assertNotNull("artifact is null", artifact);
ExecutionPlan executionPlan = artifact.getExecutionPlan();
assertNotNull("executionPlan is null", executionPlan);
ExecutionStep addBranchesStep = executionPlan.getStep(2L);
assertTrue("add branches step is not marked as split step", addBranchesStep.isSplitStep());
Map<String, ?> addBranchesActionData = addBranchesStep.getActionData();
verifyParallelLoopStatement(addBranchesActionData);
ExecutionStep joinBranchesStep = executionPlan.getStep(5L);
Map<String, ?> joinBranchesActionData = joinBranchesStep.getActionData();
verifyNavigationValuesSuccess(joinBranchesActionData);
assertNotNull("branch begin step method not found", executionPlan.getStep(3L));
assertNotNull("branch end step method not found", executionPlan.getStep(4L));
}
@Test
public void testCompileParallelLoopFlowNavigateNotWired() throws Exception {
final URI flow = getClass().getResource("/loops/parallel_loop/parallel_loop_navigate_not_wired.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
expectedException.expect(RuntimeException.class);
expectedException.expectMessage(
"Cannot compile flow 'parallel_loop_navigate_not_wired' since for step " +
"'print_values' the parallel loop results [FAILURE] have no matching navigation."
);
compiler.compile(SlangSource.fromFile(flow), path);
}
@Test
public void testCompileParallelLoopFlowPublishNavigate() throws Exception {
final URI flow = getClass().getResource("/loops/parallel_loop/parallel_loop_publish_navigate.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
CompilationArtifact artifact = compiler.compile(SlangSource.fromFile(flow), path);
assertNotNull("artifact is null", artifact);
ExecutionPlan executionPlan = artifact.getExecutionPlan();
assertNotNull("executionPlan is null", executionPlan);
ExecutionStep addBranchesStep = executionPlan.getStep(2L);
assertTrue("add branches step is not marked as split step", addBranchesStep.isSplitStep());
Map<String, ?> addBranchesActionData = addBranchesStep.getActionData();
verifyParallelLoopStatement(addBranchesActionData);
ExecutionStep joinBranchesStep = executionPlan.getStep(5L);
Map<String, ?> joinBranchesActionData = joinBranchesStep.getActionData();
verifyPublishValues(joinBranchesActionData);
verifyNavigationValuesSuccessFailure(joinBranchesActionData);
assertNotNull("branch begin step method not found", executionPlan.getStep(3L));
ExecutionStep branchEndStepExecutionStep = executionPlan.getStep(4L);
assertNotNull("branch end step method not found", branchEndStepExecutionStep);
verifyBranchPublishValuesIsEmpty(branchEndStepExecutionStep.getActionData());
}
@Test
public void testPublishOnBranchThrowsException() throws Exception {
final URI flow = getClass()
.getResource("/corrupted/loops/parallel_loop/parallel_loop_publish_on_branch.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
expectedException.expect(RuntimeException.class);
expectedException
.expectMessage("Artifact {print_values} has unrecognized tag {publish} under 'parallel_loop'. " +
"Please take a look at the supported features per versions link");
compiler.compile(SlangSource.fromFile(flow), path);
}
@Test
public void testAggregateKeyThrowsException() throws Exception {
final URI flow = getClass()
.getResource("/corrupted/loops/parallel_loop/parallel_loop_aggregate_key.sl").toURI();
final URI operation1 = getClass().getResource("/loops/parallel_loop/print_branch.sl").toURI();
final URI operation2 = getClass().getResource("/loops/parallel_loop/print_list.sl").toURI();
Set<SlangSource> path = new HashSet<>();
path.add(SlangSource.fromFile(operation1));
path.add(SlangSource.fromFile(operation2));
expectedException.expect(RuntimeException.class);
expectedException.expectMessage("Artifact {print_values} has unrecognized tag {aggregate}. " +
"Please take a look at the supported features per versions link");
compiler.compile(SlangSource.fromFile(flow), path);
}
private void verifyPublishValues(Map<String, ?> joinBranchesActionData) {
assertTrue(joinBranchesActionData.containsKey(ScoreLangConstants.STEP_PUBLISH_KEY));
@SuppressWarnings("unchecked") List<Output> actualPublishOutputs =
(List<Output>) joinBranchesActionData.get(ScoreLangConstants.STEP_PUBLISH_KEY);
List<Output> expectedPublishOutputs = new ArrayList<>();
expectedPublishOutputs
.add(new Output("name_list",
ValueFactory.create("${ map(lambda x:str(x['name']), branches_context) }")));
expectedPublishOutputs
.add(new Output("number_from_last_branch",
ValueFactory.create("${ branches_context[-1]['number'] }")));
assertEquals("publish values not as expected", expectedPublishOutputs, actualPublishOutputs);
}
private void verifyBranchPublishValuesIsEmpty(Map<String, ?> actionData) {
@SuppressWarnings("unchecked") List<Output> publishValues =
(List<Output>) actionData.get(ScoreLangConstants.STEP_PUBLISH_KEY);
assertTrue(CollectionUtils.isEmpty(publishValues));
}
private void verifyNavigationValuesSuccessFailure(Map<String, ?> joinBranchesActionData) {
assertTrue(joinBranchesActionData.containsKey(ScoreLangConstants.STEP_NAVIGATION_KEY));
@SuppressWarnings("unchecked") Map<String, ResultNavigation> actualNavigateValues =
(Map<String, ResultNavigation>) joinBranchesActionData.get(ScoreLangConstants.STEP_NAVIGATION_KEY);
Map<String, ResultNavigation> expectedNavigationValues = new HashMap<>();
expectedNavigationValues.put("SUCCESS", new ResultNavigation(6L, null));
expectedNavigationValues.put("FAILURE", new ResultNavigation(0L, "FAILURE"));
assertEquals("navigation values not as expected", expectedNavigationValues, actualNavigateValues);
}
private void verifyNavigationValuesSuccess(Map<String, ?> joinBranchesActionData) {
assertTrue(joinBranchesActionData.containsKey(ScoreLangConstants.STEP_NAVIGATION_KEY));
@SuppressWarnings("unchecked") Map<String, ResultNavigation> actualNavigateValues =
(Map<String, ResultNavigation>) joinBranchesActionData.get(ScoreLangConstants.STEP_NAVIGATION_KEY);
Map<String, ResultNavigation> expectedNavigationValues = new HashMap<>();
expectedNavigationValues.put("SUCCESS", new ResultNavigation(6L, null));
assertEquals("navigation values not as expected", expectedNavigationValues, actualNavigateValues);
}
private void verifyParallelLoopStatement(Map<String, ?> addBranchesActionData) {
assertTrue(addBranchesActionData.containsKey(ScoreLangConstants.PARALLEL_LOOP_STATEMENT_KEY));
ListLoopStatement parallelLoopStatement =
(ListLoopStatement) addBranchesActionData.get(ScoreLangConstants.PARALLEL_LOOP_STATEMENT_KEY);
assertEquals("parallel loop statement value not as expected",
"value", parallelLoopStatement.getVarName());
assertEquals("parallel loop statement expression not as expected",
"values", parallelLoopStatement.getExpression());
}
private void verifyParallelLoopStatement(Step step) {
assertTrue(step.getPreStepActionData().containsKey(SlangTextualKeys.PARALLEL_LOOP_KEY));
ListLoopStatement parallelLoopStatement = (ListLoopStatement) step.getPreStepActionData()
.get(SlangTextualKeys.PARALLEL_LOOP_KEY);
assertEquals("values", parallelLoopStatement.getExpression());
assertEquals("value", parallelLoopStatement.getVarName());
}
private Deque<Step> getStepsAfterPrecompileFlow(String flowPath) throws URISyntaxException {
URI flow = getClass().getResource(flowPath).toURI();
Executable executable = compiler.preCompile(SlangSource.fromFile(flow));
assertNotNull("executable is null", executable);
return ((Flow) executable).getWorkflow().getSteps();
}
private List<Output> getPublishOutputs(Step step) {
assertTrue(step.getPostStepActionData().containsKey(SlangTextualKeys.PUBLISH_KEY));
@SuppressWarnings("unchecked") List<Output> publishValues =
(List<Output>) step.getPostStepActionData().get(SlangTextualKeys.PUBLISH_KEY);
assertNotNull("publish list is null", publishValues);
return publishValues;
}
private void verifyNavigationStrings(List<Map<String, String>> expectedNavigationStrings, Step step) {
List<Map<String, String>> actualNavigationStrings = step.getNavigationStrings();
assertEquals(expectedNavigationStrings, actualNavigationStrings);
}
}