diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ShellAction.java b/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ShellAction.java index e408fc8..a875919 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ShellAction.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/core/actions/ShellAction.java @@ -19,8 +19,11 @@ package ch.psi.fda.core.actions; +import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; +import java.util.logging.Level; import java.util.logging.Logger; import ch.psi.fda.core.Action; @@ -37,6 +40,8 @@ public class ShellAction implements Action{ private volatile Process process; private volatile boolean abort = false; + private boolean checkExitValue = true; + private int exitValue = 0; /** * Name (full path if it is not in the system path) of the script to execute when @@ -51,7 +56,8 @@ public class ShellAction implements Action{ * @throws IllegalArgumentException Specified script does not exist */ public ShellAction(String script){ - File s = new File(script); + String[] scri = script.split("[ ,\t]"); + File s = new File(scri[0]); if(!s.exists()){ throw new IllegalArgumentException("Script "+script+" does not exist."); } @@ -73,15 +79,37 @@ public class ShellAction implements Action{ abort = false; logger.fine("Execute script "+script); process = Runtime.getRuntime().exec(script); - int exitValue = process.waitFor(); - logger.fine("Script ["+script+"] return value: "+exitValue); + int exitVal = process.waitFor(); + + // Log output of the shell script if loglevel is finest + if(logger.isLoggable(Level.FINEST)){ + logger.finest("STDOUT [BEGIN]"); + // TODO The readout of the stream should be in parallel to the processing of the script! I.e. the output appears in the log as it is generated by the script! + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line = null; + while((line=reader.readLine()) != null){ + logger.finest(line); + } + logger.finest("STDOUT [END]"); + + logger.finest("STDERR [BEGIN]"); + // TODO The readout of the stream should be in parallel to the processing of the script! I.e. the output appears in the log as it is generated by the script! + reader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + line = null; + while((line=reader.readLine()) != null){ + logger.finest(line); + } + logger.finest("STDERR [END]"); + } + + logger.fine("Script ["+script+"] return value: "+exitVal); if(abort){ throw new RuntimeException("Script ["+script+"] was aborted"); } else{ // Check script exit value to 0 if != 0 then throw an runtime exception - if(exitValue != 0){ + if(checkExitValue && exitVal != exitValue){ throw new RuntimeException("Script ["+script+"] returned with an exit value not equal to 0"); } } @@ -106,6 +134,8 @@ public class ShellAction implements Action{ } } + + /* (non-Javadoc) * @see ch.psi.fda.core.Action#destroy() */ @@ -114,4 +144,31 @@ public class ShellAction implements Action{ // Nothing to be done } + /** + * @return the checkExitValue + */ + public boolean isCheckExitValue() { + return checkExitValue; + } + + /** + * @param checkExitValue the checkExitValue to set + */ + public void setCheckExitValue(boolean checkExitValue) { + this.checkExitValue = checkExitValue; + } + + /** + * @return the exitValue + */ + public int getExitValue() { + return exitValue; + } + + /** + * @param exitValue the exitValue to set + */ + public void setExitValue(int exitValue) { + this.exitValue = exitValue; + } } diff --git a/ch.psi.fda/src/main/java/ch/psi/fda/core/actors/JythonFunction.java b/ch.psi.fda/src/main/java/ch/psi/fda/core/actors/JythonFunction.java index 85d5024..1779ccd 100644 --- a/ch.psi.fda/src/main/java/ch/psi/fda/core/actors/JythonFunction.java +++ b/ch.psi.fda/src/main/java/ch/psi/fda/core/actors/JythonFunction.java @@ -82,7 +82,7 @@ public class JythonFunction implements Function { } additionalParameter = b.toString(); - // Set variables in jython engine + // Set variables in Jython engine for(String k: map.keySet()){ engine.put(k, map.get(k)); } @@ -103,6 +103,7 @@ public class JythonFunction implements Function { logger.fine("Function called"); try { + logger.info("calculate( "+parameter+""+additionalParameter+" )"); return ((Double) engine.eval("calculate( "+parameter+""+additionalParameter+" )")); } catch (ScriptException e) { throw new RuntimeException("Calculating actuator step failed while executing the Jython script",e); diff --git a/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ShellActionTest.java b/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ShellActionTest.java index e6c79a2..87ccd5f 100644 --- a/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ShellActionTest.java +++ b/ch.psi.fda/src/test/java/ch/psi/fda/core/actions/ShellActionTest.java @@ -38,7 +38,7 @@ public class ShellActionTest { /** * Test Shell Script that returns with an exit code of 0 */ - private String testscript; + private String[] testscripts; /** * Test Shell Script that returns with an exit code of 1 */ @@ -48,17 +48,19 @@ public class ShellActionTest { */ private String testscriptNotExist; - /** * @throws java.lang.Exception */ @Before public void setUp() throws Exception { URL url = this.getClass().getClassLoader().getResource("testscripts"); - String file = new File(new URI(url.toString())).getAbsolutePath(); - testscript = file+"/testscript1.sh"; - testscriptError = file+"testfiles/testscript2-error.sh"; - testscriptNotExist = file+"testfiles/testscriptNotExist.sh"; + String file = new File(new URI(url.toString())).getAbsolutePath()+"/../../../src/test/resources/testscripts"; + // need to perform this hack as the copied scripts in the target directory do not have the execute permissions + + // test scripts also need to be able to accept options !!!! + testscripts = new String[]{file+"/testscript1.sh", file+"/testscript1.sh -option opt a b "}; + testscriptError = file+"/testscript2-error.sh"; + testscriptNotExist = file+"/testscriptNotExist.sh"; } /** @@ -74,7 +76,9 @@ public class ShellActionTest { */ @Test public void testScriptAction() { - new ShellAction(testscript); + for(String testscript: testscripts){ + new ShellAction(testscript); + } } /** @@ -92,10 +96,12 @@ public class ShellActionTest { */ @Test public void testExecute() throws InterruptedException { - File f = new File(testscript); - f.setExecutable(true); // Make file executable - ShellAction action = new ShellAction(testscript); - action.execute(); + for(String testscript: testscripts){ + File f = new File(testscript); + f.setExecutable(true); // Make file executable + ShellAction action = new ShellAction(testscript); + action.execute(); + } } /** @@ -107,6 +113,17 @@ public class ShellActionTest { ShellAction action = new ShellAction(testscriptError); action.execute(); } + + /** + * Test method for {@link ch.psi.fda.core.actions.ShellAction#execute()}. + * @throws InterruptedException + */ + @Test + public void testExecuteErrorDisabledCheck() throws InterruptedException { + ShellAction action = new ShellAction(testscriptError); + action.setCheckExitValue(false); + action.execute(); + } /** * Test method for {@link ch.psi.fda.core.actions.ShellAction#abort()}. diff --git a/ch.psi.fda/src/test/java/ch/psi/fda/core/actors/JythonFunctionTest.java b/ch.psi.fda/src/test/java/ch/psi/fda/core/actors/JythonFunctionTest.java index 2764580..94c141c 100644 --- a/ch.psi.fda/src/test/java/ch/psi/fda/core/actors/JythonFunctionTest.java +++ b/ch.psi.fda/src/test/java/ch/psi/fda/core/actors/JythonFunctionTest.java @@ -93,5 +93,28 @@ public class JythonFunctionTest { double rval = f.calculate(4); logger.info("Return value: "+rval); } + + /** + * Test whether there is a mapping of global variable that is not declared in the entry function as parameter + */ + @Test + public void testVariableMappingMissingParameterDeclaration() { + // Add two global variables a and b. + Map map = new HashMap(); + JythonGlobalVariable v = new JythonGlobalVariable(); + v.setName("a"); + v.setValue(1.5); + map.put(v.getName(), v); + v = new JythonGlobalVariable(); + v.setName("b"); + v.setValue(3.5); + map.put(v.getName(), v); + + String script = "import math\ndef "+JythonFunction.ENTRY_FUNCTION_NAME+"(parameter, b):\n return b.getValue()"; + JythonFunction f = new JythonFunction(script, map); + + double rval = f.calculate(4); + logger.info("Return value: "+rval); + } } diff --git a/ch.psi.fda/src/test/resources/testscripts/testscript1.sh b/ch.psi.fda/src/test/resources/testscripts/testscript1.sh index e2435ec..658ada0 100755 --- a/ch.psi.fda/src/test/resources/testscripts/testscript1.sh +++ b/ch.psi.fda/src/test/resources/testscripts/testscript1.sh @@ -1,4 +1,10 @@ #!/bin/bash echo "Test Script" -sleep 4 +for i in $@ +do + echo $i +done +sleep 1 + + exit 0 \ No newline at end of file