package nl.hsac.fitnesse.fixture.slim;

import nl.hsac.fitnesse.fixture.util.ProgramResponse;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Fixture to run a program.
 */
public class ExecuteProgramTest extends SlimFixtureWithMap {
    private int timeout = 60 * 1000;
    private String workingDirectory;
    private List<String> arguments = new ArrayList<>();
    private ProgramResponse response = new ProgramResponse();

    public void setTimeoutOfSeconds(int timeoutSeconds) {
        timeout = timeoutSeconds * 1000;
    }

    public void setTimeoutOfMilliseconds(int timeout) {
        this.timeout = timeout;
    }

    public int timeout() {
        return timeout;
    }

    public void setWorkingDirectory(String workingDirectory) {
        this.workingDirectory = workingDirectory;
    }

    public void setAsArguments(List<String> arguments) {
        if (arguments == null) {
            this.arguments = new ArrayList<>();
        } else {
            this.arguments = arguments;
        }
    }

    public void setAsArgument(String argument, int index) {
        while (arguments.size() <= index) {
            arguments.add("");
        }
        arguments.set(index, argument);
    }

    public List<String> getArguments() {
        return arguments;
    }

    public boolean execute(String command) {
        response = new ProgramResponse();
        if (!getCurrentValues().isEmpty()) {
            Map<String, String> env = new LinkedHashMap<>();
            for (Map.Entry<String, Object> entry : getCurrentValues().entrySet()) {
                String value = String.valueOf(entry.getValue());
                env.put(entry.getKey(), value);
            }
            response.setEnvironment(env);
        }
        response.setDirectory(workingDirectory);
        response.setCommand(command);
        response.setArguments(arguments);
        getEnvironment().invokeProgram(timeout, response);
        return true;
    }

    public Integer exitCode() {
        return response.getExitCode();
    }

    public String standardOut() {
        return formatOutput(rawStandardOut());
    }

    public String standardError() {
        return rawStandardError();
    }

    public String rawStandardOut() {
        return response.getStdOut();
    }

    public String rawStandardError() {
        return response.getStdErr();
    }

    protected String formatOutput(String output) {
        String result;
        if (StringUtils.isEmpty(output)) {
            result = output;
        } else {
            result = getEnvironment().getHtml(output);
        }
        return result;
    }
}

@@ -530,16 +530,120 @@
 nse();%0A%0A
+    /**%0A     * @param timeout max time for test to wait for program to finish, in milliseconds.%0A     */%0A
     publ
@@ -662,17 +662,22 @@
 imeoutOf
-S
+Millis
 econds(i
@@ -686,23 +686,16 @@
  timeout
-Seconds
 ) %7B%0A    
@@ -698,16 +698,21 @@
         
+this.
 timeout 
@@ -724,30 +724,122 @@
 eout
-Seconds * 1000;%0A    %7D%0A
+;%0A    %7D%0A%0A    /**%0A     * @param timeoutSeconds max time for test to wait for program to finish, in seconds.%0A     */
 %0A   
@@ -855,38 +855,33 @@
 oid setTimeoutOf
-Millis
+S
 econds(int timeo
@@ -874,32 +874,39 @@
 onds(int timeout
+Seconds
 ) %7B%0A        this
@@ -905,96 +905,306 @@
     
-this.timeout = timeout;%0A    %7D%0A%0A    public int timeout() %7B%0A        return timeout;%0A    %7D%0A
+setTimeoutOfMilliseconds(timeoutSeconds * 1000);%0A    %7D%0A%0A    /**%0A     * @return max time for test to wait for program to finish, in milliseconds.%0A     */%0A    public int timeout() %7B%0A        return timeout;%0A    %7D%0A%0A    /**%0A     * @param workingDirectory working directory when starting program.%0A     */
 %0A   
@@ -1312,32 +1312,95 @@
 rectory;%0A    %7D%0A%0A
+    /**%0A     * @param arguments arguments for program.%0A     */%0A
     public void 
@@ -1587,32 +1587,146 @@
        %7D%0A    %7D%0A%0A
+    /**%0A     * @param argument argument for program.%0A     * @param index index (zero-based) for argument.%0A     */%0A
     public void 
@@ -1909,77 +1909,185 @@
     
-public List%3CString%3E getArguments() %7B%0A        return arguments;
+/**%0A     * Executes command.%0A     * @param command executable to start.%0A     * @return true.%0A     * @throws RuntimeException when unable to start program, or on timeout.
 %0A    
-%7D%0A
+ */
 %0A   
@@ -2747,32 +2747,85 @@
 rn true;%0A    %7D%0A%0A
+    /**%0A     * @return exit code of program.%0A     */%0A
     public Integ
@@ -2878,32 +2878,101 @@
 tCode();%0A    %7D%0A%0A
+    /**%0A     * @return formatted standard output of program.%0A     */%0A
     public Strin
@@ -3035,32 +3035,100 @@
 dOut());%0A    %7D%0A%0A
+    /**%0A     * @return formatted standard error of program.%0A     */%0A
     public Strin
@@ -3181,32 +3181,104 @@
 Error();%0A    %7D%0A%0A
+    /**%0A     * @return un-formatted standard output of program.%0A     */%0A
     public Strin
@@ -3338,24 +3338,95 @@
 t();%0A    %7D%0A%0A
+    /**%0A     * @return un-formatted standard error of program.%0A     */%0A
     public S
@@ -3492,24 +3492,167 @@
 r();%0A    %7D%0A%0A
+    /**%0A     * Formats output of program for display in wiki.%0A     * @param output output of program.%0A     * @return formatted output.%0A     */%0A
     protecte

Add JavaDoc to execute program test