/******************************************************************************* * (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.ExecutableBuilder; import io.cloudslang.lang.compiler.modeller.result.ExecutableModellingResult; import io.cloudslang.lang.entities.CompilationArtifact; import io.cloudslang.lang.entities.ResultNavigation; import io.cloudslang.lang.entities.ScoreLangConstants; import io.cloudslang.score.api.ExecutionPlan; import io.cloudslang.score.api.ExecutionStep; import java.net.URI; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.junit.Assert; 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; /* * Created by orius123 on 05/11/14. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SlangCompilerSpringConfig.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) public class CompileFlowWithOnFailureTest { @Autowired private SlangCompiler compiler; @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void testCompileOnFailureBasic() throws Exception { URI flow = getClass().getResource("/flow_with_on_failure.sl").toURI(); URI operation = getClass().getResource("/test_op.sl").toURI(); Set<SlangSource> path = new HashSet<>(); path.add(SlangSource.fromFile(operation)); CompilationArtifact compilationArtifact = compiler.compile(SlangSource.fromFile(flow), path); ExecutionPlan executionPlan = compilationArtifact.getExecutionPlan(); assertNotNull("execution plan is null", executionPlan); assertEquals("there is a different number of steps than expected", 8, executionPlan.getSteps().size()); assertEquals("execution plan name is different than expected", "flow_with_on_failure", executionPlan.getName()); assertEquals("the dependencies size is not as expected", 1, compilationArtifact.getDependencies().size()); assertEquals("the inputs size is not as expected", 1, compilationArtifact.getInputs().size()); long firstOnFailureStep = 6L; long endFlowStep = 0L; ExecutionStep firstStep = executionPlan.getStep(3L); assertEquals("first step didn't navigate to on failure", firstOnFailureStep, getFailureNavigationStepId(firstStep)); ExecutionStep secondStep = executionPlan.getStep(5L); assertEquals(endFlowStep, getFailureNavigationStepId(secondStep)); ExecutionStep firstOnFailStep = executionPlan.getStep(7L); assertEquals(endFlowStep, getFailureNavigationStepId(firstOnFailStep)); } @Test public void testCompileMultipleOnFailure() throws Exception { URI operation = getClass().getResource("/test_op.sl").toURI(); Set<SlangSource> path = new HashSet<>(); path.add(SlangSource.fromFile(operation)); expectedException.expectMessage("Multiple 'on_failure' steps found"); expectedException.expect(RuntimeException.class); URI flow = getClass().getResource("/corrupted/multiple_on_failure.sl").toURI(); compiler.compile(SlangSource.fromFile(flow), path); } @Test public void testCompileSameNameInFlowAndOnFailure() throws Exception { URI operation = getClass().getResource("/fail_on_input_op.sl").toURI(); Set<SlangSource> path = new HashSet<>(); path.add(SlangSource.fromFile(operation)); expectedException.expectMessage(ExecutableBuilder.UNIQUE_STEP_NAME_MESSAGE_SUFFIX); expectedException.expectMessage("step_same_name"); expectedException.expect(RuntimeException.class); URI flow = getClass().getResource("/corrupted/same_step_name_in_flow_and_on_failure.sl").toURI(); compiler.compile(SlangSource.fromFile(flow), path); } @Test public void testCompileOnFailureSecondStep() throws Exception { URI operation = getClass().getResource("/test_op.sl").toURI(); Set<SlangSource> path = new HashSet<>(); path.add(SlangSource.fromFile(operation)); expectedException.expect(RuntimeException.class); expectedException.expectMessage("'on_failure' should be last step in the workflow"); URI flow = getClass().getResource("/corrupted/flow_with_on_failure_second_step.sl").toURI(); compiler.compile(SlangSource.fromFile(flow), path); } @Test public void testDefaultNavigationMissingResultOnFailure() throws Exception { URI operation = getClass().getResource("/test_op.sl").toURI(); Set<SlangSource> path = new HashSet<>(); path.add(SlangSource.fromFile(operation)); expectedException.expect(RuntimeException.class); expectedException.expectMessage( "Failed to compile step: jedi_training_3." + " The step/result name: FAILURE of navigation: SUCCESS -> FAILURE is missing" ); URI flow = getClass().getResource("/corrupted/default_navigation_missing_result_on_failure.sl").toURI(); compiler.compile(SlangSource.fromFile(flow), path); } @Test public void testFlowOnFailureStepFailureResultIsReachable() throws Exception { URI resource = getClass().getResource("/on_failure_reachable_result.sl").toURI(); ExecutableModellingResult result = compiler.preCompileSource(SlangSource.fromFile(resource)); assertTrue(result.getErrors().size() == 0); } private long getFailureNavigationStepId(ExecutionStep firstStep) { Map<String, ResultNavigation> navigationData = getNavigationMap(firstStep); return navigationData.get(ScoreLangConstants.FAILURE_RESULT).getNextStepId(); } private Map<String, ResultNavigation> getNavigationMap(ExecutionStep firstStep) { @SuppressWarnings("unchecked") Map<String, ResultNavigation> stringResultNavigationMap = (Map<String, ResultNavigation>) firstStep.getActionData().get(ScoreLangConstants.STEP_NAVIGATION_KEY); return stringResultNavigationMap; } }