commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sgoes...@apache.org
Subject svn commit: r985157 - in /commons/proper/exec/trunk: ./ src/changes/ src/main/java/org/apache/commons/exec/ src/site/apt/ src/test/java/org/apache/commons/exec/ src/test/scripts/
Date Fri, 13 Aug 2010 11:08:39 GMT
Author: sgoeschl
Date: Fri Aug 13 11:08:38 2010
New Revision: 985157

URL: http://svn.apache.org/viewvc?rev=985157&view=rev
Log:
Cleaning up code and tests to tackle next release

Added:
    commons/proper/exec/trunk/src/site/apt/technical.apt
      - copied, changed from r984890, commons/proper/exec/trunk/src/site/apt/tutorial.apt
    commons/proper/exec/trunk/src/test/scripts/environment.bat
    commons/proper/exec/trunk/src/test/scripts/environment.sh   (with props)
    commons/proper/exec/trunk/src/test/scripts/ping.bat   (contents, props changed)
      - copied, changed from r984732, commons/proper/exec/trunk/src/test/scripts/exec41.bat
    commons/proper/exec/trunk/src/test/scripts/ping.sh   (contents, props changed)
      - copied, changed from r984732, commons/proper/exec/trunk/src/test/scripts/exec41.sh
    commons/proper/exec/trunk/src/test/scripts/stdin.bat   (with props)
Removed:
    commons/proper/exec/trunk/src/test/scripts/exec41.bat
    commons/proper/exec/trunk/src/test/scripts/exec41.sh
Modified:
    commons/proper/exec/trunk/build.xml
    commons/proper/exec/trunk/src/changes/changes.xml
    commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java
    commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/ExecuteWatchdog.java
    commons/proper/exec/trunk/src/site/apt/index.apt
    commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java
    commons/proper/exec/trunk/src/test/scripts/forever.bat
    commons/proper/exec/trunk/src/test/scripts/forever.sh
    commons/proper/exec/trunk/src/test/scripts/stdin.sh

Modified: commons/proper/exec/trunk/build.xml
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/build.xml?rev=985157&r1=985156&r2=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/build.xml (original)
+++ commons/proper/exec/trunk/build.xml Fri Aug 13 11:08:38 2010
@@ -23,7 +23,7 @@
   <property file="user.properties" />
   
   <property file="build.properties" />
-  <property name="maven.build.version" value="1.0.1"/>
+  <property name="maven.build.version" value="1.1.0"/>
   <property name="maven.build.output" value="target/classes"/>
   <property name="maven.build.directory" value="target"/>
   <property name="maven.build.final.name" value="commons-exec-${maven.build.version}"/>

Modified: commons/proper/exec/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/changes/changes.xml?rev=985157&r1=985156&r2=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/src/changes/changes.xml (original)
+++ commons/proper/exec/trunk/src/changes/changes.xml Fri Aug 13 11:08:38 2010
@@ -24,6 +24,30 @@
     </properties>
     <body>
         <release version="1.1-SNAPSHOT" date="as in SVN" description="Maintenance Release">
+            <action dev="sgoeschl" type="fix" date="2010-08-16" >
+                The 'forever.bat' accidentally overwrite the 'forever.txt' instead of
+                appending.
+            </action>
+            <action dev="sgoeschl" type="update" date="2010-08-16" >
+                DefaultExecutor() now sets the working directory with the current working
+                directory.
+            </action>
+            <action dev="sgoeschl" type="update" date="2010-08-15">
+                Added 'DefaultExecutorTest#testStdInHandling' to show how
+                commons-exec can feed the 'stdin' of a child process.
+            </action>
+            <action dev="sgoeschl" type="update" date="2010-08-15" issue="EXEC-42" due-to="Konrad
Windzus">
+                Improved the documentation.
+            </action>
+            <action dev="sgoeschl" type="update" date="2010-08-15" issue="EXEC-41" due-to="Ernest
Mishkin">
+                Added a PumpStreamHandler.setAlwaysWaitForStreamThreads() which allows to
skip
+                joining with the pumper threads. Having said that - using that flag is for
the
+                desperate because it could leave up to three worker threads behind but there
+                might be situations where this is the only escape.
+            </action>
+            <action dev="sgoeschl" type="fix" date="2010-08-15" issue="EXEC-46" due-to="Zimmermann
Nir">
+                Process.waitFor should clear interrupt status when throwing InterruptedException
+            </action>
             <action dev="sgoeschl" type="update" date="2010-06-01" issue="EXEC-42" due-to="Pablo
Hoertner">
                 Added a new section to the tutorial to show working with asynchronous
                 processes. Thanks to Pablo for providing this documentation update.

Modified: commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java?rev=985157&r1=985156&r2=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java (original)
+++ commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/DefaultExecutor.java Fri
Aug 13 11:08:38 2010
@@ -64,17 +64,20 @@ public class DefaultExecutor implements 
     private ProcessDestroyer processDestroyer;
 
     /**
-     * Default constructor creating a default <code>PumpStreamHandler</code>.
+     * Default constructor creating a default <code>PumpStreamHandler</code>
+     * and sets the working directory of the subprocess to the current
+     * working directory.
+     *
      * The <code>PumpStreamHandler</code> pumps the output of the subprocess
      * into our <code>System.out</code> and <code>System.err</code>
to avoid
      * into our <code>System.out</code> and <code>System.err</code>
to avoid
-     * a blocked or deadlocked subprocess (see
-     * {@link java.lang.Process Process}).
+     * a blocked or deadlocked subprocess (see{@link java.lang.Process Process}).
      */
     public DefaultExecutor() {
         this.streamHandler = new PumpStreamHandler();
         this.launcher = CommandLauncherFactory.createVMLauncher();
         this.exitValues = new int[0];
+        this.workingDirectory = new File(".");
     }
 
     /**
@@ -318,16 +321,19 @@ public class DefaultExecutor implements 
         streams.start();
 
         try {
+
             // add the process to the list of those to destroy if the VM exits
             if(this.getProcessDestroyer() != null) {
               this.getProcessDestroyer().add(process);
             }
 
+            // associate the watchdog with the newly created process
             if (watchdog != null) {
                 watchdog.start(process);
             }
 
             int exitValue = Executor.INVALID_EXITVALUE;
+
             try {
                 exitValue = process.waitFor();
             } catch (InterruptedException e) {

Modified: commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/ExecuteWatchdog.java
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/ExecuteWatchdog.java?rev=985157&r1=985156&r2=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/ExecuteWatchdog.java (original)
+++ commons/proper/exec/trunk/src/main/java/org/apache/commons/exec/ExecuteWatchdog.java Fri
Aug 13 11:08:38 2010
@@ -18,6 +18,8 @@
 
 package org.apache.commons.exec;
 
+import org.apache.commons.exec.util.DebugUtils;
+
 /**
  * Destroys a process running for too long. For example:
  *
@@ -148,6 +150,7 @@ public class ExecuteWatchdog implements 
             }
         } catch (Exception e) {
             caught = e;
+            DebugUtils.handleException("Getting the exit value of the process failed", e);
         } finally {
             cleanUp();
         }

Modified: commons/proper/exec/trunk/src/site/apt/index.apt
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/site/apt/index.apt?rev=985157&r1=985156&r2=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/src/site/apt/index.apt (original)
+++ commons/proper/exec/trunk/src/site/apt/index.apt Fri Aug 13 11:08:38 2010
@@ -17,7 +17,7 @@
 ~~
 
  --------
-Jakarta Commons Exec
+Apache Commons Exec
  --------
  --------
 12 November 2008

Copied: commons/proper/exec/trunk/src/site/apt/technical.apt (from r984890, commons/proper/exec/trunk/src/site/apt/tutorial.apt)
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/site/apt/technical.apt?p2=commons/proper/exec/trunk/src/site/apt/technical.apt&p1=commons/proper/exec/trunk/src/site/apt/tutorial.apt&r1=984890&r2=985157&rev=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/src/site/apt/tutorial.apt (original)
+++ commons/proper/exec/trunk/src/site/apt/technical.apt Fri Aug 13 11:08:38 2010
@@ -17,177 +17,20 @@
 ~~
 
  --------
-Apache Commons Exec Tutorial
+Apache Commons Exec Technical Details
  --------
  --------
-12 November 2008
+16 August 2010
  --------
 
 Apache Commons Exec
 
-* The First Encounter
+* An Implementation Overview
 
-  At this point we can safely assume that you would like to start some subprocesses from
within your
-  Java application and you spent some time here to do it properly. You look at Commons Exec
and think
-  "Wow - calling Runtime.exec() is easy and the Apache folks are wasting their and my time
-  with tons of code".
-  
-  Well, we learned it the hard way (in my case more than once) that using plain Runtime.exec()
can be 
-  a painful experience. Therefore you are invited to delve into commons-exec and have a look
at the
-  hard lessons the easy way ...
-  
-* Taming Your First Process
-
-  Let's look at a real example - we would like to print PDF documents from within your Java
-  application. After googling a while it turns out to be a minor headache and using Adobe
Acrobat
-  seems to be a good option.
-
-  The command line under Windows should look like "AcroRd32.exe /p /h file" assuming that
the
-  Acrobat Reader is found in the path.
-
-+----------------------------------------------------------------------------
-String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();
-CommandLine commandLine = CommandLine.parse(line);
-DefaultExecutor executor = new DefaultExecutor();
-int exitValue = executor.execute(commandLine);
-+----------------------------------------------------------------------------
-
-  You successfully printed your first PDF document but at the end an exception is thrown
- what
-  happend? Oops, Acrobat Reader returned an exit value of '1' on success which is usually
-  considered as an execution failure. So we have to tweak our code to fix this odd behaviour
-
-  we define the exit value of "1" to be considered as successful execution.
-
-+----------------------------------------------------------------------------
-String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();
-CommandLine commandLine = CommandLine.parse(line);
-DefaultExecutor executor = new DefaultExecutor();
-executor.setExitValue(1);
-int exitValue = executor.execute(commandLine);
-+----------------------------------------------------------------------------
-
-* To Watchdog Or Not To Watchdog
-
-  You happily printed for a while but now your application blocks - your printing subprocess
-  hangs for some obvious or not so obvious reason. Starting is easy but what to do with a
run-away
-  Acrobat Reader telling you that printing failed due to a lack of paper?! Luckily commons-exec
-  provides a watchdog which does the work for you. Here is the improved code which kills
a
-  run-away process after sixty seconds.
-
-+----------------------------------------------------------------------------
-String line = "AcroRd32.exe /p /h " + file.getAbsolutePath();
-CommandLine commandLine = CommandLine.parse(line);
-DefaultExecutor executor = new DefaultExecutor();
-executor.setExitValue(1);
-ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);
-executor.setWatchdog(watchdog);
-int exitValue = executor.execute(commandLine);
-+----------------------------------------------------------------------------
-
-* Quoting Is Your Friend
-
-  Well, the code worked for quite a while until a new customer complained that
-  no documents are printed. It took half a day to find out that the following file
-  'C:\\Document And Settings\\documents\\432432.pdf' could not be printed. Due to the
-  spaces and without further quoting the command line fell literally apart into
-  the following snippet
-
-+----------------------------------------------------------------------------
-> AcroRd32.exe /p /h C:\Document And Settings\documents\432432.pdf
-+----------------------------------------------------------------------------
-
-  As a quick fix we added double quotes which tells commons-exec to handle
-  the file as a single command line argument instead of splitting it into
-  parts.
-  
-+----------------------------------------------------------------------------
-String line = "AcroRd32.exe /p /h \"" + file.getAbsolutePath() + "\"";
-CommandLine commandLine = CommandLine.parse(line);
-DefaultExecutor executor = new DefaultExecutor();
-executor.setExitValue(1);
-ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);
-executor.setWatchdog(watchdog);
-int exitValue = executor.execute(commandLine);
-+----------------------------------------------------------------------------
-
-* Build the Command Line Incrementally
-
-  The previous problem stems from the fact that commons-exec tried to split
-  a single command line string into a string array considering single and
-  double quotes. At the end of the day this is error-prone so we recommend
-  building the command line incrementally - according to the same reasoning
-  the Ant documentation does not recommend passing a single command line to
-  the <exec> target (see deprecated command attribute for 
-  {{{http://ant.apache.org/manual/CoreTasks/exec.html}exec}} task)
-  
-+----------------------------------------------------------------------------
-CommandLine commandLine = CommandLine.parse("AcroRd32.exe");
-commandLine.addArgument("/p");
-commandLine.addArgument("/h");
-commandLine.addArgument(file.getAbsolutePath());
-DefaultExecutor executor = new DefaultExecutor();
-executor.setExitValue(1);
-ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);
-executor.setWatchdog(watchdog);
-int exitValue = executor.execute(commandLine);
-+----------------------------------------------------------------------------
-
-* Using Command Line Expansion
-
-  In the previous example we basically hardcoded the command line to be
-  executed. Using a different application to print PDF documents or just
-  tinkering with command line options would require a new release - uncool.
-  To write better code you can look at the following code snippet.
-
-+----------------------------------------------------------------------------
-Map map = new HashMap();
-map.put("file", "C:\Document And Settings\documents\432432.pdf");
-
-CommandLine commandLine = CommandLine.parse("AcroRd32.exe");
-commandLine.addArgument("/p");
-commandLine.addArgument("/h");
-commandLine.addArgument("${file}");
-commandLine.setSubstitutionMap(map);
-
-DefaultExecutor executor = new DefaultExecutor();
-executor.setExitValue(1);
-ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);
-executor.setWatchdog(watchdog);
-int exitValue = executor.execute(commandLine);
-+----------------------------------------------------------------------------
-
-* Unblock Your Execution
-
-  Up to now we have a working example but it would not be good enough for
-  production - because it is blocking.
-
-  Your own worker thread will block until the print process has finshed.
-  Therefore   executing the print job asynchronously will do the trick.
-  In this example we create an instance of 'ExecuteResultHandler' and pass it
-  to the 'Executor' instance in order to execute the process asynchronously.
-  The 'resultHandler' picks up any offending exception or the process exit
-  code.
-
-+----------------------------------------------------------------------------
-CommandLine commandLine = CommandLine.parse(this.acroRd32Script.getAbsolutePath());
-commandLine.addArgument("/p");
-commandLine.addArgument("/h");
-commandLine.addArgument("${file}");
-HashMap map = new HashMap();
-map.put("file", "./pom.xml");
-commandLine.setSubstitutionMap(map);
-
-DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
-
-ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);
-Executor executor = new DefaultExecutor();
-executor.setExitValue(1);
-executor.setStreamHandler(new PumpStreamHandler());
-executor.setWatchdog(watchdog);
-executor.execute(commandLine, resultHandler);
-
-// some time later the result handler callback was invoked so we
-// can safely request the exit value
-int exitValue = resultHandler.waitFor();
+  Looking at commons-exec can be a bit daunting the first time therefore an
+  overview of the implementation helps.
+
+** DefaultExecutor
+  The main class is <<DefaultExecutor>> where you defined the command line
+  of the sub-process to be executed.
 
-+----------------------------------------------------------------------------
-  

Modified: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java?rev=985157&r1=985156&r2=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java
(original)
+++ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java
Fri Aug 13 11:08:38 2010
@@ -18,9 +18,11 @@
 
 package org.apache.commons.exec;
 
+import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileReader;
 import java.io.IOException;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -33,49 +35,73 @@ public class DefaultExecutorTest extends
 
     private Executor exec = new DefaultExecutor();
     private File testDir = new File("src/test/scripts");
+    private File foreverOutputFile = new File("./target/forever.txt");
     private ByteArrayOutputStream baos;
+
     private File testScript = TestUtil.resolveScriptForOS(testDir + "/test");
     private File errorTestScript = TestUtil.resolveScriptForOS(testDir + "/error");
     private File foreverTestScript = TestUtil.resolveScriptForOS(testDir + "/forever");
     private File nonExistingTestScript = TestUtil.resolveScriptForOS(testDir + "/grmpffffff");
     private File redirectScript = TestUtil.resolveScriptForOS(testDir + "/redirect");
-    private File exec41Script = TestUtil.resolveScriptForOS(testDir + "/exec41");
+    private File pingScript = TestUtil.resolveScriptForOS(testDir + "/ping");
     private File printArgsScript = TestUtil.resolveScriptForOS(testDir + "/printargs");
     private File acroRd32Script = TestUtil.resolveScriptForOS(testDir + "/acrord32");
     private File stdinSript = TestUtil.resolveScriptForOS(testDir + "/stdin");
-
+    private File environmentSript = TestUtil.resolveScriptForOS(testDir + "/environment");
 
     // Get suitable exit codes for the OS
     private static final int SUCCESS_STATUS; // test script successful exit code
     private static final int ERROR_STATUS;   // test script error exit code
+
     static{
-       int statuses[] = TestUtil.getTestScriptCodesForOS();
-       SUCCESS_STATUS=statuses[0];
-       ERROR_STATUS=statuses[1];
+
+        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");                
     }
     
     protected void setUp() throws Exception {
+
         System.out.println(">>> Executing " + getName() + " ...");
-        baos = new ByteArrayOutputStream();
-        exec.setStreamHandler(new PumpStreamHandler(baos, baos));
+
+        // 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));
     }
 
     protected void tearDown() throws Exception {
-        baos.close();
+        this.baos.close();
     }
 
+    /**
+     * The simplest possible test - start a script and
+     * check that the output was pumped into our
+     * <code>ByteArrayOutputStream</code>.
+     *
+     * @throws Exception the test failed
+     */
     public void testExecute() throws Exception {
         CommandLine cl = new CommandLine(testScript);
-
         int exitValue = exec.execute(cl);
         assertEquals("FOO..", baos.toString().trim());
         assertFalse(exec.isFailure(exitValue));
+        assertEquals(new File("."), exec.getWorkingDirectory());        
     }
 
     public void testExecuteWithWorkingDirectory() throws Exception {
-        File workingDir = new File(".");
+        File workingDir = new File("./target");
         CommandLine cl = new CommandLine(testScript);
-        exec.setWorkingDirectory(new File("."));
+        exec.setWorkingDirectory(workingDir);
         int exitValue = exec.execute(cl);
         assertEquals("FOO..", baos.toString().trim());
         assertFalse(exec.isFailure(exitValue));
@@ -153,7 +179,7 @@ public class DefaultExecutorTest extends
     }
 
     /**
-     * Start a async process and terminate it manually before the
+     * Start a asynchronous process and terminate it manually before the
      * watchdog timeout occurs.
      *
      * @throws Exception the test failed 
@@ -167,15 +193,17 @@ public class DefaultExecutorTest extends
         // wait for script to run
         Thread.sleep(2000);
         assertTrue("Watchdog should watch the process", watchdog.isWatching());
-        // terminate it
+        // terminate it using the watchdog
         watchdog.destroyProcess();
-        assertTrue("Watchdog should have killed the process",watchdog.killedProcess());
+        assertTrue("Watchdog should have killed the process", watchdog.killedProcess());
         assertFalse(watchdog.isWatching());
     }
 
     /**
      * Start a async process and try to terminate it manually but
-     * the process was already terminated by the watchdog.
+     * the process was already terminated by the watchdog. This is
+     * basically a race condition between infrastructure and user
+     * code.
      *
      * @throws Exception the test failed
      */
@@ -195,21 +223,30 @@ public class DefaultExecutorTest extends
 
     /**
      * Start a script looping forever and check if the ExecuteWatchdog
-     * kicks in killing the run away process.
+     * 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
      */
     public void testExecuteWatchdog() throws Exception {
+
         long timeout = 10000;
+
         CommandLine cl = new CommandLine(foreverTestScript);
         DefaultExecutor executor = new DefaultExecutor();
         executor.setWorkingDirectory(new File("."));
         ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout);
         executor.setWatchdog(watchdog);
+
         try {
             executor.execute(cl);
         }
         catch(ExecuteException e) {
+            Thread.sleep(timeout);
+            int nrOfInvocations = getOccurrences(readFile(this.foreverOutputFile), '.');
+            assertTrue("killing the subprocess did not work : " + nrOfInvocations, nrOfInvocations
> 5 && nrOfInvocations <= 11);
             assertTrue( executor.getWatchdog().killedProcess() );
             return;
         }
@@ -218,7 +255,7 @@ public class DefaultExecutorTest extends
         }
 
         assertTrue("Killed process should be true", executor.getWatchdog().killedProcess()
);
-        fail("Process did not create Execute Exception when killed");
+        fail("Process did not create ExecuteException when killed");
     }
 
     /**
@@ -262,6 +299,8 @@ public class DefaultExecutorTest extends
      * @throws Exception the test failed
      */
     public void testExecuteStability() throws Exception {
+
+        // make a plain-vanilla test
         for(int i=0; i<1000; i++) {
             Map env = new HashMap();
             env.put("TEST_ENV_VAR", new Integer(i));
@@ -271,6 +310,24 @@ public class DefaultExecutorTest extends
             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++) {
+            Map env = new HashMap();
+            env.put("TEST_ENV_VAR", new Integer(i));
+            DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
+            CommandLine cl = new CommandLine(foreverTestScript);
+            ExecuteWatchdog watchdog = new ExecuteWatchdog(500);
+            exec.setWatchdog(watchdog);
+            exec.execute(cl, env, resultHandler);
+            try {
+                resultHandler.waitFor();
+            }
+            catch(ExecuteException e) {
+                // nothing to do
+            }
+            baos.reset();
+        }
     }
 
     /**
@@ -347,18 +404,28 @@ public class DefaultExecutorTest extends
       exec.setProcessDestroyer(processDestroyer);
       exec.execute(cl, handler);
 
-      // wait for script to run
+      // wait for script to start
       Thread.sleep(2000);
-      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());
+
+      // 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());
-      Thread.sleep(100);
-      assertEquals("Processor Destroyer size should be 0",0,processDestroyer.size());
-      assertFalse("Process destroyer should not exist as shutdown hook",processDestroyer.isAddedAsShutdownHook());
+
+      try {
+          handler.waitFor();
+          fail("Expecting an ExecutionException");
+      }
+      catch(ExecuteException e) {
+          // nothing to do
+      }
+
+      assertEquals("Processor Destroyer size should be 0", 0, processDestroyer.size());
+      assertFalse("Process destroyer should not exist as shutdown hook", processDestroyer.isAddedAsShutdownHook());
     }
 
     /**
@@ -464,36 +531,6 @@ public class DefaultExecutorTest extends
      }
 
     /**
-     * Test EXEC-44 (https://issues.apache.org/jira/browse/EXEC-44).
-     *
-     * Because the ExecuteWatchdog is the only way to destroy asynchronous
-     * processes, it should be possible to set it to an infinite timeout,
-     * for processes which should not timeout, but manually destroyed
-     * under some circumstances.
-     *
-     * @throws Exception the test failed
-     */
-    public void testExec44() throws Exception {
-
-        CommandLine cl = new CommandLine(foreverTestScript);
-        DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
-        ExecuteWatchdog watchdog = new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT);
-
-        exec.setWatchdog(watchdog);
-        exec.execute(cl, resultHandler);
-
-        // wait for script to run
-        Thread.sleep(5000);
-        assertTrue("The watchdog is watching the process", watchdog.isWatching());      

-
-        // terminate it
-        watchdog.destroyProcess();
-        assertTrue("The watchdog has killed the process", watchdog.killedProcess());
-        assertFalse("The watchdog is no longer watching any process", watchdog.isWatching());
-    }
-
-
-    /**
      * Runs the final tutorial example. The sample demonstrates the following
      * features of commons-exec
      * <ul>
@@ -505,7 +542,6 @@ public class DefaultExecutorTest extends
      *
      * @throws Exception the test failed
      */
-
     public void testTutorialExample() throws Exception {
 
         final long timeout1 = 5*1000;
@@ -522,7 +558,7 @@ public class DefaultExecutorTest extends
             map.put("file", "./pom.xml");
             commandLine.setSubstitutionMap(map);
 
-            // asynchronous execution is defined by using a 'resultHander'
+            // asynchronous execution is defined by using a 'resultHandler'
             DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler()
{
                 public void onProcessComplete(int exitValue) {
                     super.onProcessComplete(exitValue);
@@ -566,15 +602,15 @@ public class DefaultExecutorTest extends
     }
 
     /**
-     * The test script reads two arguments from stdin and prints
-     * the result to stdout. To make things slightly more intersting
+     * The test script reads an argument from <code>stdin<code> and prints
+     * the result to stdout. To make things slightly more interesting
      * we are using an asynchronous process.
      *
      * @throws Exception the test failed
      */
     public void testStdInHandling() throws Exception {
 
-        ByteArrayInputStream bais = new ByteArrayInputStream("Foo\nBar\n".getBytes());
+        ByteArrayInputStream bais = new ByteArrayInputStream("Foo\n".getBytes());
         CommandLine cl = new CommandLine(this.stdinSript);
         PumpStreamHandler pumpStreamHandler = new PumpStreamHandler( this.baos, System.err,
bais);
         DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
@@ -583,12 +619,26 @@ public class DefaultExecutorTest extends
         executor.execute(cl, resultHandler);
 
         resultHandler.waitFor();
-        
+
         assertTrue(resultHandler.getExitValue() == 0);
-        assertTrue(this.baos.toString().indexOf("Hello Foo Bar!") > 0);
+        assertTrue(this.baos.toString().indexOf("Hello Foo!") > 0);
     }
 
-    // === Testing bug fixes ====
+    /**
+     * Call a script to dump the environment variables of the subprocess. 
+     *
+     * @throws Exception the test failed
+     */
+    public void testEnvironmentVariables() throws Exception {
+        exec.execute(new CommandLine(environmentSript));
+        String environment = baos.toString().trim();
+        assertTrue("Found no environment variables", environment.length() > 0);
+        System.out.println(environment);
+    }
+
+    // ======================================================================
+    // === Testing bug fixes
+    // ======================================================================
 
     /**
      * Test the patch for EXEC-33 (https://issues.apache.org/jira/browse/EXEC-33)
@@ -607,6 +657,31 @@ public class DefaultExecutorTest extends
         assertFalse(exec.isFailure(exitValue));
     }
 
+    /**
+     * EXEC-34 https://issues.apache.org/jira/browse/EXEC-34
+     *
+     * Race condition prevent watchdog working using ExecuteStreamHandler.
+     * The test fails because when watchdog.destroyProcess() is invoked the
+     * external process is not bound to the watchdog yet
+     *
+     * @throws Exception the test failed
+     */
+    public void testExec34() throws Exception {
+
+        CommandLine cmdLine = new CommandLine(pingScript);
+        cmdLine.addArgument("10"); // sleep 10 secs
+
+        ExecuteWatchdog watchdog = new ExecuteWatchdog(Integer.MAX_VALUE);
+        DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
+        exec.setWatchdog(watchdog);
+        exec.execute(cmdLine, handler);
+        // if you comment out the next line the test will fail
+        Thread.sleep(2000);
+        // terminate it
+        watchdog.destroyProcess();
+        assertTrue("Watchdog should have killed the process",watchdog.killedProcess());
+    }
+
     
     /**
      * Test the patch for EXEC-41 (https://issues.apache.org/jira/browse/EXEC-41).
@@ -629,7 +704,7 @@ public class DefaultExecutorTest extends
      */
     public void testExec41WithStreams() throws Exception {
 
-		CommandLine cmdLine = new CommandLine(exec41Script);
+		CommandLine cmdLine = new CommandLine(pingScript);
 		cmdLine.addArgument("10"); // sleep 10 secs
 		DefaultExecutor executor = new DefaultExecutor();
 		ExecuteWatchdog watchdog = new ExecuteWatchdog(2*1000); // allow process no more than 2
secs
@@ -668,7 +743,7 @@ public class DefaultExecutorTest extends
      */
     public void testExec41WithoutStreams() throws Exception {
 
-		CommandLine cmdLine = new CommandLine(exec41Script);
+		CommandLine cmdLine = new CommandLine(pingScript);
 		cmdLine.addArgument("10"); // sleep 10 secs
 		DefaultExecutor executor = new DefaultExecutor();
 		ExecuteWatchdog watchdog = new ExecuteWatchdog(2*1000); // allow process no more than 2
secs
@@ -698,4 +773,67 @@ public class DefaultExecutorTest extends
         assertTrue("The process was killed by the watchdog", watchdog.killedProcess());
         assertTrue("SKipping the Thread.join() did not work", duration < 9000);
     }
+
+    /**
+     * Test EXEC-44 (https://issues.apache.org/jira/browse/EXEC-44).
+     *
+     * Because the ExecuteWatchdog is the only way to destroy asynchronous
+     * processes, it should be possible to set it to an infinite timeout,
+     * for processes which should not timeout, but manually destroyed
+     * under some circumstances.
+     *
+     * @throws Exception the test failed
+     */
+    public void testExec44() throws Exception {
+
+        CommandLine cl = new CommandLine(foreverTestScript);
+        DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();
+        ExecuteWatchdog watchdog = new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT);
+
+        exec.setWatchdog(watchdog);
+        exec.execute(cl, resultHandler);
+
+        // wait for script to run
+        Thread.sleep(5000);
+        assertTrue("The watchdog is watching the process", watchdog.isWatching());
+
+        // terminate it
+        watchdog.destroyProcess();
+        assertTrue("The watchdog has killed the process", watchdog.killedProcess());
+        assertFalse("The watchdog is no longer watching any process", watchdog.isWatching());
+    }
+
+
+    // ======================================================================
+    // === Helper methods
+    // ======================================================================
+
+    private String readFile(File file) throws Exception {
+
+        String text;
+        StringBuffer contents = new StringBuffer();
+        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(String data, char c) {
+
+        int result = 0;
+
+        for(int i=0; i<data.length(); i++) {
+            if(data.charAt(i) == c) {
+                result++;
+            }
+        }
+
+        return result;
+    }
 }

Added: commons/proper/exec/trunk/src/test/scripts/environment.bat
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/scripts/environment.bat?rev=985157&view=auto
==============================================================================
--- commons/proper/exec/trunk/src/test/scripts/environment.bat (added)
+++ commons/proper/exec/trunk/src/test/scripts/environment.bat Fri Aug 13 11:08:38 2010
@@ -0,0 +1,22 @@
+@ECHO OFF
+
+REM Little batch file to run nearly foerver
+REM see http://malektips.com/dos0017.html
+REM
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM
+REM      http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+
+REM print the environment variables
+set
\ No newline at end of file

Added: commons/proper/exec/trunk/src/test/scripts/environment.sh
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/scripts/environment.sh?rev=985157&view=auto
==============================================================================
--- commons/proper/exec/trunk/src/test/scripts/environment.sh (added)
+++ commons/proper/exec/trunk/src/test/scripts/environment.sh Fri Aug 13 11:08:38 2010
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+# print the environment variables
+env
\ No newline at end of file

Propchange: commons/proper/exec/trunk/src/test/scripts/environment.sh
------------------------------------------------------------------------------
    svn:executable = *

Modified: commons/proper/exec/trunk/src/test/scripts/forever.bat
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/scripts/forever.bat?rev=985157&r1=985156&r2=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/src/test/scripts/forever.bat (original)
+++ commons/proper/exec/trunk/src/test/scripts/forever.bat Fri Aug 13 11:08:38 2010
@@ -19,8 +19,9 @@ REM See the License for the specific lan
 REM limitations under the License.
 
 REM run an infinite loop so the script will never ever terminate on its behalf
+REM and append a '.' after each second
 
 :LOOP
   ECHO . > .\target\forever.txt
-  PAUSE > .\target\forever.txt
+  @ping 127.0.0.1 -n 2 -w 1000 > nul
 GOTO LOOP
\ No newline at end of file

Modified: commons/proper/exec/trunk/src/test/scripts/forever.sh
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/scripts/forever.sh?rev=985157&r1=985156&r2=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/src/test/scripts/forever.sh (original)
+++ commons/proper/exec/trunk/src/test/scripts/forever.sh Fri Aug 13 11:08:38 2010
@@ -18,6 +18,7 @@
 #
 
 # run an infinite loop so the script will never ever terminate on its behalf
+# and append a '.' after each second
 
 while test "notempty"
 do

Copied: commons/proper/exec/trunk/src/test/scripts/ping.bat (from r984732, commons/proper/exec/trunk/src/test/scripts/exec41.bat)
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/scripts/ping.bat?p2=commons/proper/exec/trunk/src/test/scripts/ping.bat&p1=commons/proper/exec/trunk/src/test/scripts/exec41.bat&r1=984732&r2=985157&rev=985157&view=diff
==============================================================================
    (empty)

Propchange: commons/proper/exec/trunk/src/test/scripts/ping.bat
------------------------------------------------------------------------------
    svn:eol-style = CRLF

Copied: commons/proper/exec/trunk/src/test/scripts/ping.sh (from r984732, commons/proper/exec/trunk/src/test/scripts/exec41.sh)
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/scripts/ping.sh?p2=commons/proper/exec/trunk/src/test/scripts/ping.sh&p1=commons/proper/exec/trunk/src/test/scripts/exec41.sh&r1=984732&r2=985157&rev=985157&view=diff
==============================================================================
    (empty)

Propchange: commons/proper/exec/trunk/src/test/scripts/ping.sh
------------------------------------------------------------------------------
    svn:eol-style = LF

Propchange: commons/proper/exec/trunk/src/test/scripts/ping.sh
------------------------------------------------------------------------------
    svn:executable = *

Added: commons/proper/exec/trunk/src/test/scripts/stdin.bat
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/scripts/stdin.bat?rev=985157&view=auto
==============================================================================
--- commons/proper/exec/trunk/src/test/scripts/stdin.bat (added)
+++ commons/proper/exec/trunk/src/test/scripts/stdin.bat Fri Aug 13 11:08:38 2010
@@ -0,0 +1,19 @@
+@ECHO OFF
+
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM
+REM      http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+
+set /p answer=What's your name? : 
+echo Hello %answer%!
\ No newline at end of file

Propchange: commons/proper/exec/trunk/src/test/scripts/stdin.bat
------------------------------------------------------------------------------
    svn:executable = *

Modified: commons/proper/exec/trunk/src/test/scripts/stdin.sh
URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/scripts/stdin.sh?rev=985157&r1=985156&r2=985157&view=diff
==============================================================================
--- commons/proper/exec/trunk/src/test/scripts/stdin.sh (original)
+++ commons/proper/exec/trunk/src/test/scripts/stdin.sh Fri Aug 13 11:08:38 2010
@@ -17,9 +17,7 @@
 # limitations under the License.
 #
 
-echo "What's your first name? : "
-read firstName
-echo "What's your surname? : "
-read surname
-echo "Hello $firstName $surname!"
+echo "What's your name? : "
+read answer
+echo "Hello $answer!"
 



Mime
View raw message