/*******************************************************************************
* (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.caching.CacheResult;
import io.cloudslang.lang.compiler.caching.CacheValueState;
import io.cloudslang.lang.compiler.caching.CachedPrecompileService;
import io.cloudslang.lang.compiler.configuration.SlangCompilerSpringConfig;
import io.cloudslang.lang.compiler.modeller.model.Executable;
import io.cloudslang.lang.compiler.modeller.result.CompilationModellingResult;
import io.cloudslang.lang.entities.ScoreLangConstants;
import io.cloudslang.lang.entities.bindings.Input;
import io.cloudslang.score.api.ExecutionPlan;
import io.cloudslang.score.api.ExecutionStep;
import java.net.URL;
import java.util.List;
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;
/*
* Created by orius123 on 05/11/14.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SlangCompilerSpringConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class CompileOperationTest {
@Rule
public ExpectedException exception = ExpectedException.none();
@Autowired
private SlangCompiler compiler;
@Autowired
private CachedPrecompileService cachedPrecompileService;
@Test
public void testCompileOperationBasic() throws Exception {
URL resource = getClass().getResource("/test_op.sl");
ExecutionPlan executionPlan = compiler.compile(SlangSource.fromFile(resource.toURI()), null).getExecutionPlan();
assertNotNull("execution plan is null", executionPlan);
assertEquals("there is a different number of steps than expected", 3, executionPlan.getSteps().size());
}
@Test
public void testCompileOperationWithData() throws Exception {
URL resource = getClass().getResource("/operation_with_data.sl");
ExecutionPlan executionPlan = compiler.compile(SlangSource.fromFile(resource.toURI()), null).getExecutionPlan();
ExecutionStep startStep = executionPlan.getStep(1L);
@SuppressWarnings("unchecked")
List<Input> inputs = (List<Input>) startStep.getActionData().get(ScoreLangConstants.EXECUTABLE_INPUTS_KEY);
assertNotNull("inputs doesn't exist", inputs);
assertEquals("there is a different number of inputs than expected", 13, inputs.size());
ExecutionStep actionStep = executionPlan.getStep(2L);
String script = (String) actionStep.getActionData().get(ScoreLangConstants.PYTHON_ACTION_SCRIPT_KEY);
assertNotNull("script doesn't exist", script);
Assert.assertTrue("script is different than expected", script.startsWith("# this is python amigos!!"));
ExecutionStep endStep = executionPlan.getStep(3L);
Object outputs = endStep.getActionData().get(ScoreLangConstants.EXECUTABLE_OUTPUTS_KEY);
Object results = endStep.getActionData().get(ScoreLangConstants.EXECUTABLE_RESULTS_KEY);
assertNotNull("outputs don't exist", outputs);
assertNotNull("results don't exist", results);
}
@Test
public void testPreCompileOperationBasic() throws Exception {
URL resource = getClass().getResource("/check_Weather.sl");
Executable operation = compiler.preCompile(SlangSource.fromFile(resource.toURI()));
assertNotNull("preCompiledMetaData is null", operation);
assertEquals("Operation name is wrong", "check_Weather", operation.getName());
assertEquals("Operation namespace is wrong", "user.ops", operation.getNamespace());
assertEquals("There is a different number of operation inputs than expected", 1, operation.getInputs().size());
assertEquals("There is a different number of operation outputs than expected",
2, operation.getOutputs().size());
assertEquals("There is a different number of operation results than expected",
2, operation.getResults().size());
assertEquals("There is a different number of operation dependencies than expected",
0, operation.getExecutableDependencies().size());
}
@Test
public void testCompileOperationMissingClassName() throws Exception {
URL resource = getClass().getResource("/corrupted/operation_missing_class_name.sl");
exception.expect(RuntimeException.class);
exception.expectMessage("Action syntax is illegal.\n" +
"Following tags are missing: [" + SlangTextualKeys.JAVA_ACTION_CLASS_NAME_KEY);
compiler.compile(SlangSource.fromFile(resource.toURI()), null);
}
@Test
public void testCompileOperationMissingMethodName() throws Exception {
URL resource = getClass().getResource("/corrupted/operation_missing_method_name.sl");
exception.expect(RuntimeException.class);
exception.expectMessage("Action syntax is illegal.\n" +
"Following tags are missing: [" + SlangTextualKeys.JAVA_ACTION_METHOD_NAME_KEY);
compiler.compile(SlangSource.fromFile(resource.toURI()), null);
}
@Test
public void testCompileOperationInvalidActionProperty() throws Exception {
URL resource = getClass().getResource("/corrupted/operation_invalid_action_property.sl");
exception.expect(RuntimeException.class);
exception.expectMessage("Action syntax is illegal.\n" +
"Following tags are invalid: [IDontBelongHere]. " +
"Please take a look at the supported features per versions link");
compiler.compile(SlangSource.fromFile(resource.toURI()), null);
}
@Test
public void testCompileOperationMultipleActionTypes() throws Exception {
URL resource = getClass().getResource("/corrupted/operation_action_multiple_types.sl");
exception.expect(RuntimeException.class);
exception.expectMessage("Conflicting keys[java_action, python_action] at: operation_action_multiple_types");
compiler.compile(SlangSource.fromFile(resource.toURI()), null);
}
@Test
public void testCompileOperationMissingActionProperties() throws Exception {
URL resource = getClass().getResource("/corrupted/operation_missing_action_properties.sl");
exception.expect(RuntimeException.class);
exception.expectMessage("Error compiling operation_missing_action_properties.sl. " +
"Operation: operation_missing_action_properties has no action data");
compiler.compile(SlangSource.fromFile(resource.toURI()), null);
}
@Test
public void testCompileOperationMissingPythonScript() throws Exception {
URL resource = getClass().getResource("/corrupted/operation_missing_python_script.sl");
exception.expect(RuntimeException.class);
exception.expectMessage("Error compiling operation_missing_python_script.sl. " +
"Operation: operation_missing_python_script has no action data");
compiler.compile(SlangSource.fromFile(resource.toURI()), null);
}
@Test
public void testCompileOperationWithMissingNamespace() throws Exception {
URL resource = getClass().getResource("/corrupted/op_without_namespace.sl");
exception.expect(RuntimeException.class);
exception.expectMessage("For source[op_without_namespace.sl] namespace cannot be empty.");
compiler.compile(SlangSource.fromFile(resource.toURI()), null);
}
@Test
public void testPrecompileCacheCleanup() throws Exception {
URL resource = getClass().getResource("/corrupted/op_without_namespace.sl");
SlangSource slangSource = SlangSource.fromFile(resource.toURI());
CompilationModellingResult result = compiler.compileSource(slangSource, null);
assertEquals("The compilation result should have one error", 1, result.getErrors().size());
assertEquals("Wrong error message", "For source[op_without_namespace.sl] namespace cannot be empty.",
result.getErrors().get(0).getMessage());
assertNotNull("Cache should contain the ExecutableModellingResult before cache invalidateAllInPreCompileCache",
cachedPrecompileService.getValueFromCache(slangSource.getFilePath(), slangSource));
compiler.invalidateAllInPreCompileCache();
CacheResult cacheResult = cachedPrecompileService.getValueFromCache(slangSource.getFilePath(), slangSource);
assertEquals(
"Cache should not contain the ExecutableModellingResult after cache invalidateAllInPreCompileCache",
CacheValueState.MISSING,
cacheResult.getState()
);
}
@Test
public void testPrecompileCacheDisabledByDefault() throws Exception {
URL resource = getClass().getResource("/corrupted/op_without_namespace.sl");
SlangSource slangSource = SlangSource.fromFile(resource.toURI());
CompilationModellingResult result = compiler.compileSource(slangSource, null);
assertEquals("The compilation result should have one error", 1, result.getErrors().size());
assertEquals("Wrong error message", "For source[op_without_namespace.sl] namespace cannot be empty.",
result.getErrors().get(0).getMessage());
CacheResult cacheResult = cachedPrecompileService.getValueFromCache(slangSource.getFilePath(), slangSource);
assertEquals(
"Cache should not contain the ExecutableModellingResult after cache invalidateAllInPreCompileCache",
CacheValueState.MISSING,
cacheResult.getState()
);
}
}