/*******************************************************************************
* (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.scripts;
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.bindings.values.Value;
import io.cloudslang.lang.entities.bindings.values.ValueFactory;
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.PythonExecutor;
import io.cloudslang.runtime.impl.python.PythonRuntimeServiceImpl;
import io.cloudslang.score.events.EventBus;
import io.cloudslang.score.events.EventBusImpl;
import junit.framework.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.python.core.PyObject;
import org.python.core.PyStringMap;
import org.python.util.PythonInterpreter;
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.HashMap;
import java.util.Map;
import java.util.Set;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ScriptExecutorTest.Config.class)
public class ScriptExecutorTest {
private static PythonInterpreter execInterpreter = mock(PythonInterpreter.class);
@Rule
public ExpectedException exception = ExpectedException.none();
@Autowired
private ScriptExecutor scriptExecutor;
@Test
public void testExecuteScript() throws Exception {
reset(execInterpreter);
final String script = "pass";
Map<String, Value> scriptInputValues = new HashMap<>();
Value value1 = ValueFactory.create("value1");
Value value2 = ValueFactory.create("value2");
scriptInputValues.put("input1", value1);
scriptInputValues.put("input2", value2);
Map<Object, PyObject> scriptOutputValues = new HashMap<>();
PyObject pyObjectValue1 = (PyObject) ValueFactory.createPyObjectValue("value1", false);
PyObject pyObjectValue2 = (PyObject) ValueFactory.createPyObjectValue("value2", false);
scriptOutputValues.put("output1", pyObjectValue1);
scriptOutputValues.put("output2", pyObjectValue2);
when(execInterpreter.getLocals()).thenReturn(new PyStringMap(scriptOutputValues));
when(execInterpreter.get(eq("output1"))).thenReturn(pyObjectValue1);
when(execInterpreter.get(eq("output2"))).thenReturn(pyObjectValue2);
Map<String, Serializable> expectedScriptOutputs = new HashMap<>();
expectedScriptOutputs.put("output1", value1);
expectedScriptOutputs.put("output2", value2);
final Map<String, Value> outputs = scriptExecutor.executeScript(script, scriptInputValues);
verify(execInterpreter).set(eq("input1"), eq((Value) pyObjectValue1));
verify(execInterpreter).set(eq("input2"), eq((Value) pyObjectValue2));
verify(execInterpreter).exec(script);
Assert.assertEquals(expectedScriptOutputs, outputs);
}
@Test
public void testExecuteScriptError() throws Exception {
reset(execInterpreter);
String script = "pass";
doThrow(new RuntimeException("error from interpreter")).when(execInterpreter).exec(eq(script));
exception.expect(RuntimeException.class);
exception.expectMessage("error from interpreter");
exception.expectMessage("Error executing python script");
scriptExecutor.executeScript(script, new HashMap<String, Value>());
}
@Configuration
static class Config {
@Bean
public ScriptExecutor scriptExecutor() {
return new ScriptExecutor();
}
@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() {
protected PythonExecutor createNewExecutor(Set<String> filePaths) {
return new PythonExecutor(filePaths) {
protected PythonInterpreter initInterpreter(Set<String> dependencies) {
return execInterpreter;
}
};
}
};
}
@Bean
public EventBus eventBus() {
return new EventBusImpl();
}
}
}