/*******************************************************************************
* (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.bindings;
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.dependency.impl.services.utils.UnzipUtil;
import io.cloudslang.lang.entities.SystemProperty;
import io.cloudslang.lang.entities.bindings.Argument;
import io.cloudslang.lang.entities.bindings.values.Value;
import io.cloudslang.lang.entities.bindings.values.ValueFactory;
import io.cloudslang.lang.runtime.bindings.scripts.ScriptEvaluator;
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.PythonExecutionNotCachedEngine;
import io.cloudslang.runtime.impl.python.PythonRuntimeServiceImpl;
import io.cloudslang.score.events.EventBus;
import io.cloudslang.score.events.EventBusImpl;
import org.junit.Assert;
import org.junit.Ignore;
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.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.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.assertNull;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ArgumentsBindingTest.Config.class)
public class ArgumentsBindingTest {
private static boolean shouldRunMaven;
static {
ClassLoader classLoader = ArgumentsBindingTest.class.getClassLoader();
String settingsXmlPath = classLoader.getResource("settings.xml").getPath();
File rootHome = new File(settingsXmlPath).getParentFile();
File mavenHome = new File(rootHome, "maven");
File mavenRepo = new File(rootHome, "test-mvn-repo");
if (!mavenRepo.exists() && !mavenRepo.mkdirs()) {
System.out.println("Could not create maven repo " + mavenRepo.toString());
}
UnzipUtil.unzipToFolder(mavenHome.getAbsolutePath(), classLoader.getResourceAsStream("maven.zip"));
System.setProperty(MavenConfigImpl.MAVEN_HOME, mavenHome.getAbsolutePath());
System.setProperty(MavenConfigImpl.MAVEN_REPO_LOCAL, mavenRepo.getAbsolutePath());
System.setProperty("maven.home", classLoader.getResource("maven").getPath());
shouldRunMaven = System.getProperties().containsKey(MavenConfigImpl.MAVEN_REMOTE_URL) &&
System.getProperties().containsKey(MavenConfigImpl.MAVEN_PLUGINS_URL);
System.setProperty(MavenConfigImpl.MAVEN_SETTINGS_PATH, settingsXmlPath);
System.setProperty(MavenConfigImpl.MAVEN_M2_CONF_PATH, classLoader.getResource("m2.conf").getPath());
String provideralAlreadyConfigured = System.setProperty("python.executor.engine",
PythonExecutionNotCachedEngine.class.getSimpleName());
assertNull("python.executor.engine was configured before this test!!!!!!!", provideralAlreadyConfigured);
}
@SuppressWarnings("unchecked")
private static final Set<SystemProperty> EMPTY_SET = Collections.EMPTY_SET;
@Autowired
private ArgumentsBinding argumentsBinding;
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void testEmptyBindArguments() throws Exception {
List<Argument> arguments = Collections.emptyList();
Map<String, Value> result = bindArguments(arguments);
Assert.assertTrue(result.isEmpty());
}
@Test
public void testDefaultValueNoExpression() {
List<Argument> arguments = Collections.singletonList(new Argument("argument1", ValueFactory.create("value")));
Map<String, Value> result = bindArguments(arguments);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("value", result.get("argument1").get());
}
@Test
public void testDefaultValueExpression() {
List<Argument> arguments = Collections.singletonList(new Argument("argument1",
ValueFactory.create("${ 'value' }")));
Map<String, Value> result = bindArguments(arguments);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("value", result.get("argument1").get());
}
@Ignore("Remove when types are supported")
@Test
public void testDefaultValueInt() {
List<Argument> arguments = Collections.singletonList(new Argument("argument1", ValueFactory.create(2)));
Map<String, Value> result = bindArguments(arguments);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals(2, result.get("argument1").get());
}
@Ignore("Remove when types are supported")
@Test
public void testDefaultValueBoolean() {
List<Argument> arguments = Arrays.asList(
new Argument("argument1", ValueFactory.create(true)),
new Argument("argument2", ValueFactory.create(false)),
new Argument("argument3", ValueFactory.create("phrase containing true and false"))
);
Map<String, Value> result = bindArguments(arguments);
Assert.assertTrue((boolean) result.get("argument1").get());
Assert.assertFalse((boolean) result.get("argument2").get());
Assert.assertEquals("phrase containing true and false", result.get("argument3").get());
}
@Test
public void testTwoArguments() {
List<Argument> arguments = Arrays.asList(new Argument("argument2", ValueFactory.create("yyy")),
new Argument("argument1", ValueFactory.create("zzz")));
Map<String, Value> result = bindArguments(arguments);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("zzz", result.get("argument1").get());
Assert.assertTrue(result.containsKey("argument2"));
Assert.assertEquals("yyy", result.get("argument2").get());
}
@Test
public void testAssignNoExpression() {
Argument argument1 = new Argument("argument1", ValueFactory.create("${ argument1 }"));
Argument argument2 = new Argument("argument2", ValueFactory.create("${ argument1 }"));
List<Argument> arguments = Arrays.asList(argument1, argument2);
Map<String, Value> result = bindArguments(arguments);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals(null, result.get("argument1").get());
Assert.assertTrue(result.containsKey("argument2"));
Assert.assertEquals(null, result.get("argument2").get());
}
@Test
public void testArgumentRef() {
Map<String, Value> context = new HashMap<>();
context.put("argumentX", ValueFactory.create("xxx"));
List<Argument> arguments = Collections.singletonList(new Argument("argument1",
ValueFactory.create("${ str(argumentX) }")));
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("xxx", result.get("argument1").get());
Assert.assertEquals(1, context.size());
}
@Test
public void testArgumentScriptEval() {
Map<String, Value> context = new HashMap<>();
context.put("valX", ValueFactory.create("5"));
Argument scriptArgument = new Argument("argument1", ValueFactory.create("${ \"3\" + valX }"));
List<Argument> arguments = Collections.singletonList(scriptArgument);
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("35", result.get("argument1").get());
Assert.assertEquals(1, context.size());
}
@Test
public void testArgumentScriptEval2() {
Map<String, Value> context = new HashMap<>();
context.put("valB", ValueFactory.create("b"));
context.put("valC", ValueFactory.create("c"));
Argument scriptArgument = new Argument("argument1", ValueFactory.create("${ 'a' + valB + valC }"));
List<Argument> arguments = Collections.singletonList(scriptArgument);
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("abc", result.get("argument1").get());
}
@Test
public void testDefaultValueVsEmptyRef() {
Map<String, Value> context = new HashMap<>();
Argument refArgument = new Argument("argument1", ValueFactory.create("${ str('val') }"));
List<Argument> arguments = Collections.singletonList(refArgument);
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("val", result.get("argument1").get());
Assert.assertTrue(context.isEmpty());
}
@Test
public void testOverridableFalseBehaviour() {
Map<String, Value> context = new HashMap<>();
context.put("argument1", ValueFactory.create("3"));
Argument argument = new Argument("argument1", ValueFactory.create("${ \"5+7\" }"));
List<Argument> arguments = Collections.singletonList(argument);
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("5+7", result.get("argument1").get());
Assert.assertEquals(1, context.size());
Assert.assertEquals("3", context.get("argument1").get());
}
@Test
public void testComplexExpr() {
Map<String, Value> context = new HashMap<>();
context.put("argument1", ValueFactory.create("3"));
Argument argument = new Argument("argument2", ValueFactory.create("${ argument1 + \"3 * 2\" }"));
List<Argument> arguments = Collections.singletonList(argument);
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument2"));
Assert.assertEquals("33 * 2", result.get("argument2").get());
Assert.assertEquals(1, result.size());
}
@Test
public void testOverrideAssignFromVar() {
Map<String, Value> context = new HashMap<>();
context.put("argument2", ValueFactory.create("3"));
context.put("argument1", ValueFactory.create("5"));
Argument argument = new Argument("argument1", ValueFactory.create("${ argument2 }"));
List<Argument> arguments = Collections.singletonList(argument);
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("3", result.get("argument1").get());
Assert.assertEquals(1, result.size());
}
@Test(expected = RuntimeException.class)
public void testExpressionWithWrongRef() {
Map<String, Value> context = new HashMap<>();
Argument argument = new Argument("argument1", ValueFactory.create("${ argument2 }"));
List<Argument> arguments = Collections.singletonList(argument);
bindArguments(arguments, context);
}
@Test
public void testArgumentAssignFromAnotherArgument() {
Map<String, Value> context = new HashMap<>();
Argument argument1 = new Argument("argument1", ValueFactory.create("5"));
Argument argument2 = new Argument("argument2", ValueFactory.create("${ argument1 }"));
List<Argument> arguments = Arrays.asList(argument1, argument2);
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("5", result.get("argument1").get());
Assert.assertTrue(result.containsKey("argument2"));
Assert.assertEquals("5", result.get("argument2").get());
Assert.assertEquals(2, result.size());
Assert.assertTrue("orig context should not change", context.isEmpty());
}
@Test
public void testComplexExpressionArgument() {
Map<String, Value> context = new HashMap<>();
context.put("varX", ValueFactory.create("5"));
Argument argument1 = new Argument("argument1", ValueFactory.create("5"));
Argument argument2 = new Argument("argument2", ValueFactory.create("${ argument1 + \"5\" + varX }"));
List<Argument> arguments = Arrays.asList(argument1, argument2);
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("5", result.get("argument1").get());
Assert.assertTrue(result.containsKey("argument2"));
Assert.assertEquals("555", result.get("argument2").get());
Assert.assertEquals(2, result.size());
Assert.assertEquals("orig context should not change", 1, context.size());
}
@Test
public void testComplexExpression2Argument() {
Map<String, Value> context = new HashMap<>();
context.put("varX", ValueFactory.create("roles"));
Argument argument1 = new Argument("argument1", ValueFactory.create("${ 'mighty' + ' max ' + varX }"));
List<Argument> arguments = Collections.singletonList(argument1);
Map<String, Value> result = bindArguments(arguments, context);
Assert.assertFalse(result.isEmpty());
Assert.assertTrue(result.containsKey("argument1"));
Assert.assertEquals("mighty max roles", result.get("argument1").get());
Assert.assertEquals(1, result.size());
Assert.assertEquals("orig context should not change", 1, context.size());
}
private Map<String, Value> bindArguments(
List<Argument> arguments,
Map<String, ? extends Value> context) {
return argumentsBinding.bindArguments(arguments, context, EMPTY_SET);
}
private Map<String, Value> bindArguments(List<Argument> arguments) {
return bindArguments(arguments, new HashMap<String, Value>());
}
@Configuration
static class Config {
@Bean
public ArgumentsBinding argumentsBinding() {
return new ArgumentsBinding();
}
@Bean
public ScriptEvaluator scriptEvaluator() {
return new ScriptEvaluator();
}
@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 EventBus eventBus() {
return new EventBusImpl();
}
}
}