/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package org.apache.commons.exec;

import org.apache.commons.exec.environment.EnvironmentUtils;
import org.junit.*;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.*;

/**
 */
public class DefaultExecutorTest {

    /** Maximum time to wait (15s) */
    private static final int WAITFOR_TIMEOUT = 15000;

    private final Executor exec = new DefaultExecutor();
    private final File testDir = new File("src/test/scripts");
    private final File foreverOutputFile = new File("./target/forever.txt");
    private ByteArrayOutputStream baos;

    private final File testScript = TestUtil.resolveScriptForOS(testDir + "/test");
    private final File errorTestScript = TestUtil.resolveScriptForOS(testDir + "/error");
    private final File foreverTestScript = TestUtil.resolveScriptForOS(testDir + "/forever");
    private final File nonExistingTestScript = TestUtil.resolveScriptForOS(testDir + "/grmpffffff");
    private final File redirectScript = TestUtil.resolveScriptForOS(testDir + "/redirect");
    private final File printArgsScript = TestUtil.resolveScriptForOS(testDir + "/printargs");
//    private final File acroRd32Script = TestUtil.resolveScriptForOS(testDir + "/acrord32");
    private final File stdinSript = TestUtil.resolveScriptForOS(testDir + "/stdin");
    private final File environmentSript = TestUtil.resolveScriptForOS(testDir + "/environment");
//    private final File wrapperScript = TestUtil.resolveScriptForOS(testDir + "/wrapper");


    // Get suitable exit codes for the OS
    private static int SUCCESS_STATUS; // test script successful exit code
    private static int ERROR_STATUS;   // test script error exit code

    @BeforeClass
    public static void classSetUp() {

        final int statuses[] = TestUtil.getTestScriptCodesForOS();
        SUCCESS_STATUS=statuses[0];
        ERROR_STATUS=statuses[1];

        // turn on debug mode and throw an exception for each encountered problem
        System.setProperty("org.apache.commons.exec.lenient", "false");
        System.setProperty("org.apache.commons.exec.debug", "true");
    }

    @Before
    public void setUp() throws Exception {

        // delete the marker file
        this.foreverOutputFile.getParentFile().mkdirs();
        if (this.foreverOutputFile.exists()) {
            this.foreverOutputFile.delete();
        }

        // prepare a ready to Executor
        this.baos = new ByteArrayOutputStream();
        this.exec.setStreamHandler(new PumpStreamHandler(baos, baos));
    }

    @After
    public void tearDown() throws Exception {
        this.baos.close();
        foreverOutputFile.delete();
    }

    // ======================================================================
    // Start of regression tests
    // ======================================================================

    /**
     * The simplest possible test - start a script and
     * check that the output was pumped into our
     * {@code ByteArrayOutputStream}.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecute() throws Exception {
        final CommandLine cl = new CommandLine(testScript);
        final int exitValue = exec.execute(cl);
        assertEquals("FOO..", baos.toString().trim());
        assertFalse(exec.isFailure(exitValue));
        assertEquals(new File("."), exec.getWorkingDirectory());
    }

    @Test
    public void testExecuteWithWorkingDirectory() throws Exception {
        final File workingDir = new File("./target");
        final CommandLine cl = new CommandLine(testScript);
        exec.setWorkingDirectory(workingDir);
        final int exitValue = exec.execute(cl);
        assertEquals("FOO..", baos.toString().trim());
        assertFalse(exec.isFailure(exitValue));
        assertEquals(exec.getWorkingDirectory(), workingDir);
    }

    @Test(expected = IOException.class)
    public void testExecuteWithInvalidWorkingDirectory() throws Exception {
        final File workingDir = new File("/foo/bar");
        final CommandLine cl = new CommandLine(testScript);
        exec.setWorkingDirectory(workingDir);

        exec.execute(cl);
    }

    @Test
    public void testExecuteWithError() throws Exception {
        final CommandLine cl = new CommandLine(errorTestScript);

        try{
            exec.execute(cl);
            fail("Must throw ExecuteException");
        } catch (final ExecuteException e) {
            assertTrue(exec.isFailure(e.getExitValue()));
        }
    }

    @Test
    public void testExecuteWithArg() throws Exception {
        final CommandLine cl = new CommandLine(testScript);
        cl.addArgument("BAR");
        final int exitValue = exec.execute(cl);

        assertEquals("FOO..BAR", baos.toString().trim());
        assertFalse(exec.isFailure(exitValue));
    }

    /**
     * Execute the test script and pass a environment containing
     * 'TEST_ENV_VAR'.
     */
    @Test
    public void testExecuteWithSingleEnvironmentVariable() throws Exception {
        final Map<String, String> env = new HashMap<>();
        env.put("TEST_ENV_VAR", "XYZ");

        final CommandLine cl = new CommandLine(testScript);

        final int exitValue = exec.execute(cl, env);

        assertEquals("FOO.XYZ.", baos.toString().trim());
        assertFalse(exec.isFailure(exitValue));
    }

    /**
     * Start a asynchronous process which returns an success
     * exit value.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteAsync() throws Exception {
        final CommandLine cl = new CommandLine(testScript);
        final DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
        exec.execute(cl, resultHandler);
        resultHandler.waitFor(2000);
        assertTrue(resultHandler.hasResult());
        assertNull(resultHandler.getException());
        assertFalse(exec.isFailure(resultHandler.getExitValue()));
        assertEquals("FOO..", baos.toString().trim());
    }

    /**
     * Start a asynchronous process which returns an error
     * exit value.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteAsyncWithError() throws Exception {
        final CommandLine cl = new CommandLine(errorTestScript);
        final DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
        exec.execute(cl, resultHandler);
        resultHandler.waitFor(2000);
        assertTrue(resultHandler.hasResult());
        assertTrue(exec.isFailure(resultHandler.getExitValue()));
        assertNotNull(resultHandler.getException());
        assertEquals("FOO..", baos.toString().trim());
    }

    /**
     * Start a asynchronous process and terminate it manually before the
     * watchdog timeout occurs.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteAsyncWithTimelyUserTermination() throws Exception {
        final CommandLine cl = new CommandLine(foreverTestScript);
        final ExecuteWatchdog watchdog = new ExecuteWatchdog(Integer.MAX_VALUE);
        exec.setWatchdog(watchdog);
        final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
        exec.execute(cl, handler);
        // wait for script to run
        Thread.sleep(2000);
        assertTrue("Watchdog should watch the process", watchdog.isWatching());
        // terminate it manually using the watchdog
        watchdog.destroyProcess();
        // wait until the result of the process execution is propagated
        handler.waitFor(WAITFOR_TIMEOUT);
        assertTrue("Watchdog should have killed the process", watchdog.killedProcess());
        assertFalse("Watchdog is no longer watching the process", watchdog.isWatching());
        assertTrue("ResultHandler received a result", handler.hasResult());
        assertNotNull("ResultHandler received an exception as result", handler.getException());
    }

    /**
     * Start a asynchronous process and try to terminate it manually but
     * the process was already terminated by the watchdog. This is
     * basically a race condition between infrastructure and user
     * code.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteAsyncWithTooLateUserTermination() throws Exception {
        final CommandLine cl = new CommandLine(foreverTestScript);
        final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
        final ExecuteWatchdog watchdog = new ExecuteWatchdog(3000);
        exec.setWatchdog(watchdog);
        exec.execute(cl, handler);
        // wait for script to be terminated by the watchdog
        Thread.sleep(6000);
        // try to terminate the already terminated process
        watchdog.destroyProcess();
        // wait until the result of the process execution is propagated
        handler.waitFor(WAITFOR_TIMEOUT);
        assertTrue("Watchdog should have killed the process already", watchdog.killedProcess());
        assertFalse("Watchdog is no longer watching the process", watchdog.isWatching());
        assertTrue("ResultHandler received a result", handler.hasResult());
        assertNotNull("ResultHandler received an exception as result", handler.getException());
    }

    /**
     * Start a script looping forever (synchronously) and check if the ExecuteWatchdog
     * kicks in killing the run away process. To make killing a process
     * more testable the "forever" scripts write each second a '.'
     * into "./target/forever.txt" (a marker file). After a test run
     * we should have a few dots in there.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteWatchdogSync() throws Exception {

        if (OS.isFamilyOpenVms()) {
            System.out.println("The test 'testExecuteWatchdogSync' currently hangs on the following OS : "
                    + System.getProperty("os.name"));
            return;
        }

        final long timeout = 10000;

        final CommandLine cl = new CommandLine(foreverTestScript);
        final DefaultExecutor executor = new DefaultExecutor();
        executor.setWorkingDirectory(new File("."));
        final ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout);
        executor.setWatchdog(watchdog);

        try {
            executor.execute(cl);
        }
        catch (final ExecuteException e) {
            Thread.sleep(timeout);
            final int nrOfInvocations = getOccurrences(readFile(this.foreverOutputFile), '.');
            assertTrue(executor.getWatchdog().killedProcess());
            assertTrue("killing the subprocess did not work : " + nrOfInvocations, nrOfInvocations > 5
                    && nrOfInvocations <= 11);
            return;
        }
        catch (final Throwable t) {
            fail(t.getMessage());
        }

        assertTrue("Killed process should be true", executor.getWatchdog().killedProcess() );
        fail("Process did not create ExecuteException when killed");
    }

    /**
     * Start a script looping forever (asynchronously) and check if the
     * ExecuteWatchdog kicks in killing the run away process. To make killing
     * a process more testable the "forever" scripts write each second a '.'
     * into "./target/forever.txt" (a marker file). After a test run
     * we should have a few dots in there.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteWatchdogAsync() throws Exception {

        final long timeout = 10000;

        final CommandLine cl = new CommandLine(foreverTestScript);
        final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
        final DefaultExecutor executor = new DefaultExecutor();
        executor.setWorkingDirectory(new File("."));
        executor.setWatchdog(new ExecuteWatchdog(timeout));

        executor.execute(cl, handler);
        handler.waitFor(WAITFOR_TIMEOUT);

        assertTrue("Killed process should be true", executor.getWatchdog().killedProcess() );
        assertTrue("ResultHandler received a result", handler.hasResult());
        assertNotNull("ResultHandler received an exception as result", handler.getException());

        final int nrOfInvocations = getOccurrences(readFile(this.foreverOutputFile), '.');
        assertTrue("Killing the process did not work : " + nrOfInvocations, nrOfInvocations > 5 && nrOfInvocations <= 11);
    }

    /**
     * [EXEC-68] Synchronously starts a short script with a Watchdog attached with an extremely large timeout. Checks
     * to see if the script terminated naturally or if it was killed by the Watchdog. Fail if killed by Watchdog.
     *
     * @throws Exception
     *             the test failed
     */
    @Test
    public void testExecuteWatchdogVeryLongTimeout() throws Exception {
        final long timeout = Long.MAX_VALUE;

        final CommandLine cl = new CommandLine(testScript);
        final DefaultExecutor executor = new DefaultExecutor();
        executor.setWorkingDirectory(new File("."));
        final ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout);
        executor.setWatchdog(watchdog);

        try {
            executor.execute(cl);
        } catch (final ExecuteException e) {
            assertFalse("Process should exit normally, not be killed by watchdog", watchdog.killedProcess());
            // If the Watchdog did not kill it, something else went wrong.
            throw e;
        }
    }

    /**
     * Try to start an non-existing application which should result
     * in an exception.
     */
    @Test(expected = IOException.class)
    public void testExecuteNonExistingApplication() throws Exception {
        final CommandLine cl = new CommandLine(nonExistingTestScript);
        final DefaultExecutor executor = new DefaultExecutor();

        executor.execute(cl);
    }

    /**
     * Try to start an non-existing application which should result
     * in an exception.
     */
    @Test(expected = IOException.class)
    public void testExecuteNonExistingApplicationWithWatchDog() throws Exception {
        final CommandLine cl = new CommandLine(nonExistingTestScript);
        final DefaultExecutor executor = new DefaultExecutor();
        executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT));

        executor.execute(cl);
    }

    /**
     * Try to start an non-existing application where the exception is caught/processed
     * by the result handler.
     */
    @Test
    public void testExecuteAsyncNonExistingApplication() throws Exception {
        final CommandLine cl = new CommandLine(nonExistingTestScript);
        final DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
        final DefaultExecutor executor = new DefaultExecutor();

        executor.execute(cl, resultHandler);
        resultHandler.waitFor();

        assertTrue(executor.isFailure(resultHandler.getExitValue()));
        assertNotNull(resultHandler.getException());
    }

    /**
     * Try to start an non-existing application where the exception is caught/processed
     * by the result handler. The watchdog in notified to avoid waiting for the
     * process infinitely.
     *
     * @see <a href="https://issues.apache.org/jira/browse/EXEC-71">EXEC-71</a>
     */
    @Test
    public void testExecuteAsyncNonExistingApplicationWithWatchdog() throws Exception {
        final CommandLine cl = new CommandLine(nonExistingTestScript);
        final DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler() {
            @Override
            public void onProcessFailed(final ExecuteException e) {
                System.out.println("Process did not stop gracefully, had exception '" + e.getMessage() + "' while executing process");
                super.onProcessFailed(e);
            }
        };
        final DefaultExecutor executor = new DefaultExecutor();
        executor.setWatchdog(new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT));

        executor.execute(cl, resultHandler);
        resultHandler.waitFor();

        assertTrue(executor.isFailure(resultHandler.getExitValue()));
        assertNotNull(resultHandler.getException());
        assertFalse(executor.getWatchdog().isWatching());
        assertFalse(executor.getWatchdog().killedProcess());
        executor.getWatchdog().destroyProcess();
    }

    /**
     * Invoke the error script but define that the ERROR_STATUS is a good
     * exit value and therefore no exception should be thrown.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteWithCustomExitValue1() throws Exception {
        exec.setExitValue(ERROR_STATUS);
        final CommandLine cl = new CommandLine(errorTestScript);
        exec.execute(cl);
    }

    /**
     * Invoke the error script but define that SUCCESS_STATUS is a bad
     * exit value and therefore an exception should be thrown.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteWithCustomExitValue2() throws Exception {
        final CommandLine cl = new CommandLine(errorTestScript);
        exec.setExitValue(SUCCESS_STATUS);
        try{
            exec.execute(cl);
            fail("Must throw ExecuteException");
        } catch (final ExecuteException e) {
            assertTrue(exec.isFailure(e.getExitValue()));
        }
    }

    /**
     * Test the proper handling of ProcessDestroyer for an synchronous process.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteWithProcessDestroyer() throws Exception {

      final CommandLine cl = new CommandLine(testScript);
      final ShutdownHookProcessDestroyer processDestroyer = new ShutdownHookProcessDestroyer();
      exec.setProcessDestroyer(processDestroyer);

      assertTrue(processDestroyer.isEmpty());
      assertTrue(processDestroyer.isAddedAsShutdownHook() == false);

      final int exitValue = exec.execute(cl);

      assertEquals("FOO..", baos.toString().trim());
      assertFalse(exec.isFailure(exitValue));
      assertTrue(processDestroyer.isEmpty());
      assertTrue(processDestroyer.isAddedAsShutdownHook() == false);
    }

    /**
     * Test the proper handling of ProcessDestroyer for an asynchronous process.
     * Since we do not terminate the process it will be terminated in the
     * ShutdownHookProcessDestroyer implementation.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteAsyncWithProcessDestroyer() throws Exception {

      final CommandLine cl = new CommandLine(foreverTestScript);
      final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
      final ShutdownHookProcessDestroyer processDestroyer = new ShutdownHookProcessDestroyer();
      final ExecuteWatchdog watchdog = new ExecuteWatchdog(Integer.MAX_VALUE);

      assertTrue(exec.getProcessDestroyer() == null);
      assertTrue(processDestroyer.isEmpty());
      assertTrue(processDestroyer.isAddedAsShutdownHook() == false);

      exec.setWatchdog(watchdog);
      exec.setProcessDestroyer(processDestroyer);
      exec.execute(cl, handler);

      // wait for script to start
      Thread.sleep(2000);

      // our process destroyer should be initialized now
      assertNotNull("Process destroyer should exist", exec.getProcessDestroyer());
      assertEquals("Process destroyer size should be 1", 1, processDestroyer.size());
      assertTrue("Process destroyer should exist as shutdown hook", processDestroyer.isAddedAsShutdownHook());

      // terminate it and the process destroyer is detached
      watchdog.destroyProcess();
      assertTrue(watchdog.killedProcess());
      handler.waitFor(WAITFOR_TIMEOUT);
      assertTrue("ResultHandler received a result", handler.hasResult());
      assertNotNull(handler.getException());
      assertEquals("Processor Destroyer size should be 0", 0, processDestroyer.size());
      assertFalse("Process destroyer should not exist as shutdown hook", processDestroyer.isAddedAsShutdownHook());
    }

    /**
     * Invoke the test using some fancy arguments.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteWithFancyArg() throws Exception {
        final CommandLine cl = new CommandLine(testScript);
        cl.addArgument("test $;`(0)[1]{2}");
        final int exitValue = exec.execute(cl);
        assertTrue(baos.toString().trim().indexOf("test $;`(0)[1]{2}") > 0);
        assertFalse(exec.isFailure(exitValue));
    }

    /**
     * Start a process with redirected streams - stdin of the newly
     * created process is connected to a FileInputStream whereas
     * the "redirect" script reads all lines from stdin and prints
     * them on stdout. Furthermore the script prints a status
     * message on stderr.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteWithRedirectedStreams() throws Exception {
        if (OS.isFamilyUnix()) {
            final FileInputStream fis = new FileInputStream("./NOTICE.txt");
            final CommandLine cl = new CommandLine(redirectScript);
            final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(baos, baos, fis);
            final DefaultExecutor executor = new DefaultExecutor();
            executor.setWorkingDirectory(new File("."));
            executor.setStreamHandler(pumpStreamHandler);
            final int exitValue = executor.execute(cl);
            fis.close();
            final String result = baos.toString().trim();
            assertTrue(result, result.indexOf("Finished reading from stdin") > 0);
            assertFalse("exitValue=" + exitValue, exec.isFailure(exitValue));
        } else if (OS.isFamilyWindows()) {
            System.err
                    .println("The code samples to do that in windows look like a joke ... :-( .., no way I'm doing that");
            System.err.println("The test 'testExecuteWithRedirectedStreams' does not support the following OS : "
                    + System.getProperty("os.name"));
        } else {
            System.err.println("The test 'testExecuteWithRedirectedStreams' does not support the following OS : "
                    + System.getProperty("os.name"));
        }
    }

     /**
      * Start a process and connect stdout and stderr.
      *
      * @throws Exception the test failed
      */
     @Test
    public void testExecuteWithStdOutErr() throws Exception {
        final CommandLine cl = new CommandLine(testScript);
        final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(System.out, System.err);
        final DefaultExecutor executor = new DefaultExecutor();
        executor.setStreamHandler(pumpStreamHandler);
        final int exitValue = executor.execute(cl);
        assertFalse(exec.isFailure(exitValue));
    }

    /**
     * Start a process and connect it to no stream.
     *
     * @throws Exception
     *             the test failed
     */
    @Test
    public void testExecuteWithNullOutErr() throws Exception {
        final CommandLine cl = new CommandLine(testScript);
        final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(null, null);
        final DefaultExecutor executor = new DefaultExecutor();
        executor.setStreamHandler(pumpStreamHandler);
        final int exitValue = executor.execute(cl);
        assertFalse(exec.isFailure(exitValue));
    }

     /**
      * Start a process and connect out and err to a file.
      *
      * @throws Exception the test failed
      */
     @Test
    public void testExecuteWithRedirectOutErr() throws Exception {
        final File outfile = File.createTempFile("EXEC", ".test");
        outfile.deleteOnExit();
        final CommandLine cl = new CommandLine(testScript);
        try (FileOutputStream outAndErr = new FileOutputStream(outfile)) {
            final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(outAndErr);
            final DefaultExecutor executor = new DefaultExecutor();
            executor.setStreamHandler(pumpStreamHandler);
            final int exitValue = executor.execute(cl);
            assertFalse(exec.isFailure(exitValue));
            assertTrue(outfile.exists());
        }
    }

    /**
     * A generic test case to print the command line arguments to 'printargs' script to solve
     * even more command line puzzles.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testExecuteWithComplexArguments() throws Exception {
        final CommandLine cl = new CommandLine(printArgsScript);
        cl.addArgument("gdal_translate");
        cl.addArgument("HDF5:\"/home/kk/grass/data/4404.he5\"://HDFEOS/GRIDS/OMI_Column_Amount_O3/Data_Fields/ColumnAmountO3/home/kk/4.tif", false);
        final DefaultExecutor executor = new DefaultExecutor();
        final int exitValue = executor.execute(cl);
        assertFalse(exec.isFailure(exitValue));
     }


    /**
     * The test script reads an argument from {@code stdin} and prints
     * the result to stdout. To make things slightly more interesting
     * we are using an asynchronous process.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testStdInHandling() throws Exception {
        // newline not needed; causes problems for VMS
        final ByteArrayInputStream bais = new ByteArrayInputStream("Foo".getBytes());
        final CommandLine cl = new CommandLine(this.stdinSript);
        final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(this.baos, System.err, bais);
        final DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
        final Executor executor = new DefaultExecutor();
        executor.setStreamHandler(pumpStreamHandler);
        executor.execute(cl, resultHandler);

        resultHandler.waitFor(WAITFOR_TIMEOUT);
        assertTrue("ResultHandler received a result", resultHandler.hasResult());

        assertFalse(exec.isFailure(resultHandler.getExitValue()));
        final String result = baos.toString();
        assertTrue("Result '" + result + "' should contain 'Hello Foo!'", result.indexOf("Hello Foo!") >= 0);
    }

    /**
     * Call a script to dump the environment variables of the subprocess.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testEnvironmentVariables() throws Exception {
        exec.execute(new CommandLine(environmentSript));
        final String environment = baos.toString().trim();
        assertFalse("Found no environment variables", environment.isEmpty());
        assertFalse(environment.indexOf("NEW_VAR") >= 0);
    }

    /**
     * Call a script to dump the environment variables of the subprocess
     * after adding a custom environment variable.
     *
     * @throws Exception the test failed
     */
    @Test
    public void testAddEnvironmentVariables() throws Exception {
        final Map<String, String> myEnvVars = new HashMap<>(EnvironmentUtils.getProcEnvironment());
        myEnvVars.put("NEW_VAR","NEW_VAL");
        exec.execute(new CommandLine(environmentSript), myEnvVars);
        final String environment = baos.toString().trim();
        assertTrue("Expecting NEW_VAR in "+environment,environment.indexOf("NEW_VAR") >= 0);
        assertTrue("Expecting NEW_VAL in "+environment,environment.indexOf("NEW_VAL") >= 0);
    }

    @Test
    public void testAddEnvironmentVariableEmbeddedQuote() throws Exception {
        final Map<String, String> myEnvVars = new HashMap<>(EnvironmentUtils.getProcEnvironment());
        final String name = "NEW_VAR";
        final String value = "NEW_\"_VAL";
        myEnvVars.put(name,value);
        exec.execute(new CommandLine(environmentSript), myEnvVars);
        final String environment = baos.toString().trim();
        assertTrue("Expecting "+name+" in "+environment,environment.indexOf(name) >= 0);
        assertTrue("Expecting "+value+" in "+environment,environment.indexOf(value) >= 0);
    }

    // ======================================================================
    // === Long running tests
    // ======================================================================

    /**
     * Start any processes in a loop to make sure that we do
     * not leave any handles/resources open.
     *
     * @throws Exception the test failed
     */
    @Test
    @Ignore
    public void _testExecuteStability() throws Exception {

        // make a plain-vanilla test
        for (int i=0; i<100; i++) {
            final Map<String, String> env = new HashMap<>();
            env.put("TEST_ENV_VAR", Integer.toString(i));
            final CommandLine cl = new CommandLine(testScript);
            final int exitValue = exec.execute(cl,env);
            assertFalse(exec.isFailure(exitValue));
            assertEquals("FOO." + i + ".", baos.toString().trim());
            baos.reset();
        }

        // now be nasty and use the watchdog to kill out sub-processes
        for (int i=0; i<100; i++) {
            final Map<String, String> env = new HashMap<>();
            env.put("TEST_ENV_VAR", Integer.toString(i));
            final DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
            final CommandLine cl = new CommandLine(foreverTestScript);
            final ExecuteWatchdog watchdog = new ExecuteWatchdog(500);
            exec.setWatchdog(watchdog);
            exec.execute(cl, env, resultHandler);
            resultHandler.waitFor(WAITFOR_TIMEOUT);
            assertTrue("ResultHandler received a result", resultHandler.hasResult());
            assertNotNull(resultHandler.getException());
            baos.reset();
        }
    }


    // ======================================================================
    // === Helper methods
    // ======================================================================

    private String readFile(final File file) throws Exception {

        String text;
        final StringBuilder contents = new StringBuilder();
        final BufferedReader reader = new BufferedReader(new FileReader(file));

        while ((text = reader.readLine()) != null)
        {
            contents.append(text)
                .append(System.getProperty(
                    "line.separator"));
        }
        reader.close();
        return contents.toString();
    }

    private int getOccurrences(final String data, final char c) {

        int result = 0;

        for (int i=0; i<data.length(); i++) {
            if (data.charAt(i) == c) {
                result++;
            }
        }

        return result;
    }
}
