Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id EAC4610EF9 for ; Fri, 10 Jan 2014 14:24:30 +0000 (UTC) Received: (qmail 1867 invoked by uid 500); 10 Jan 2014 14:24:21 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 1761 invoked by uid 500); 10 Jan 2014 14:24:14 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 1736 invoked by uid 99); 10 Jan 2014 14:24:05 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Jan 2014 14:24:05 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Jan 2014 14:24:01 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 6C186238883D; Fri, 10 Jan 2014 14:23:41 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1557130 - in /commons/proper/exec/trunk/src/test/java/org/apache/commons/exec: ./ issues/ Date: Fri, 10 Jan 2014 14:23:40 -0000 To: commits@commons.apache.org From: britter@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140110142341.6C186238883D@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: britter Date: Fri Jan 10 14:23:40 2014 New Revision: 1557130 URL: http://svn.apache.org/r1557130 Log: Move issue specific tests into own package, away from general test code Added: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec33Test.java (with props) commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec34Test.java (with props) commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec36Test.java (with props) commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec41Test.java (with props) commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec44Test.java (with props) commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec49Test.java (with props) commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec57Test.java (with props) commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec60Test.java (with props) Modified: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/DefaultExecutorTest.java 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=1557130&r1=1557129&r2=1557130&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 Jan 10 14:23:40 2014 @@ -33,8 +33,6 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; import java.util.HashMap; import java.util.Map; @@ -63,7 +61,6 @@ public class DefaultExecutorTest { 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 pingScript = TestUtil.resolveScriptForOS(testDir + "/ping"); private final File printArgsScript = TestUtil.resolveScriptForOS(testDir + "/printargs"); // private final File acroRd32Script = TestUtil.resolveScriptForOS(testDir + "/acrord32"); private final File stdinSript = TestUtil.resolveScriptForOS(testDir + "/stdin"); @@ -700,486 +697,6 @@ public class DefaultExecutorTest { } // ====================================================================== - // === Testing bug fixes - // ====================================================================== - - /** - * Test the patch for EXEC-33 (https://issues.apache.org/jira/browse/EXEC-33) - * - * PumpStreamHandler hangs if System.in is redirect to process input stream . - * - * @throws Exception the test failed - */ - @Test - public void testExec33() throws Exception { - final CommandLine cl = new CommandLine(testScript); - final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(System.out, System.err, System.in); - final DefaultExecutor executor = new DefaultExecutor(); - executor.setStreamHandler(pumpStreamHandler); - final int exitValue = executor.execute(cl); - 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 - */ - @Test - public void testExec34_1() throws Exception { - - final CommandLine cmdLine = new CommandLine(pingScript); - cmdLine.addArgument("10"); // sleep 10 secs - - final ExecuteWatchdog watchdog = new ExecuteWatchdog(Integer.MAX_VALUE); - final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler(); - exec.setWatchdog(watchdog); - exec.execute(cmdLine, handler); - assertTrue(watchdog.isWatching()); - watchdog.destroyProcess(); - assertTrue("Watchdog should have killed the process",watchdog.killedProcess()); - assertFalse("Watchdog is no longer watching the process",watchdog.isWatching()); - } - - /** - * EXEC-34 https://issues.apache.org/jira/browse/EXEC-34 - * - * Some user waited for an asynchronous process using watchdog.isWatching() which - * is now properly implemented using DefaultExecuteResultHandler. - * - * @throws Exception the test failed - */ - @Test - public void testExec34_2() throws Exception { - - final CommandLine cmdLine = new CommandLine(pingScript); - cmdLine.addArgument("10"); // sleep 10 secs - - final ExecuteWatchdog watchdog = new ExecuteWatchdog(5000); - final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler(); - exec.setWatchdog(watchdog); - exec.execute(cmdLine, handler); - handler.waitFor(); - assertTrue("Process has exited", handler.hasResult()); - assertNotNull("Process was aborted", handler.getException()); - assertTrue("Watchdog should have killed the process", watchdog.killedProcess()); - assertFalse("Watchdog is no longer watching the process", watchdog.isWatching()); - } - - /** - * Test EXEC-36 see https://issues.apache.org/jira/browse/EXEC-36 - * - * Original example from Kai Hu which only can be tested on Unix - * - * @throws Exception the test failed - */ - @Test - public void testExec36_1() throws Exception { - - if (OS.isFamilyUnix()) { - - CommandLine cmdl; - - /** - * ./script/jrake cruise:publish_installers INSTALLER_VERSION=unstable_2_1 \ - * INSTALLER_PATH="/var/lib/ cruise-agent/installers" INSTALLER_DOWNLOAD_SERVER='something' WITHOUT_HELP_DOC=true - */ - - final String expected = "./script/jrake\n" + - "cruise:publish_installers\n" + - "INSTALLER_VERSION=unstable_2_1\n" + - "INSTALLER_PATH=\"/var/lib/ cruise-agent/installers\"\n" + - "INSTALLER_DOWNLOAD_SERVER='something'\n" + - "WITHOUT_HELP_DOC=true"; - - cmdl = new CommandLine(printArgsScript); - cmdl.addArgument("./script/jrake", false); - cmdl.addArgument("cruise:publish_installers", false); - cmdl.addArgument("INSTALLER_VERSION=unstable_2_1", false); - cmdl.addArgument("INSTALLER_PATH=\"/var/lib/ cruise-agent/installers\"", false); - cmdl.addArgument("INSTALLER_DOWNLOAD_SERVER='something'", false); - cmdl.addArgument("WITHOUT_HELP_DOC=true", false); - - final int exitValue = exec.execute(cmdl); - final String result = baos.toString().trim(); - assertFalse(exec.isFailure(exitValue)); - assertEquals(expected, result); - } - else { - System.err.println("The test 'testExec36_1' does not support the following OS : " + System.getProperty("os.name")); - return; - } - } - - /** - * Test EXEC-36 see https://issues.apache.org/jira/browse/EXEC-36 - * - * Test a complex real example found at - * http://blogs.msdn.com/b/astebner/archive/2005/12/13/503471.aspx - * - * The command line is so weird that it even falls apart under Windows - * - * @throws Exception the test failed - */ - @Test - public void testExec36_2() throws Exception { - - String expected; - - // the original command line - // dotnetfx.exe /q:a /c:"install.exe /l ""\Documents and Settings\myusername\Local Settings\Temp\netfx.log"" /q" - - if (OS.isFamilyWindows()) { - expected = "dotnetfx.exe\n" + - "/q:a\n" + - "/c:\"install.exe /l \"\"\\Documents and Settings\\myusername\\Local Settings\\Temp\\netfx.log\"\" /q\""; - } - else if (OS.isFamilyUnix()) { - expected = "dotnetfx.exe\n" + - "/q:a\n" + - "/c:\"install.exe /l \"\"/Documents and Settings/myusername/Local Settings/Temp/netfx.log\"\" /q\""; - } - else { - System.err.println("The test 'testExec36_3' does not support the following OS : " + System.getProperty("os.name")); - return; - } - - CommandLine cmdl; - final File file = new File("/Documents and Settings/myusername/Local Settings/Temp/netfx.log"); - final Map map = new HashMap(); - map.put("FILE", file); - - cmdl = new CommandLine(printArgsScript); - cmdl.setSubstitutionMap(map); - cmdl.addArgument("dotnetfx.exe", false); - cmdl.addArgument("/q:a", false); - cmdl.addArgument("/c:\"install.exe /l \"\"${FILE}\"\" /q\"", false); - - final int exitValue = exec.execute(cmdl); - final String result = baos.toString().trim(); - assertFalse(exec.isFailure(exitValue)); - - if (OS.isFamilyUnix()) { - // the parameters fall literally apart under Windows - need to disable the check for Win32 - assertEquals(expected, result); - } - } - - /** - * Test the patch for EXEC-41 (https://issues.apache.org/jira/browse/EXEC-41). - * - * When a process runs longer than allowed by a configured watchdog's - * timeout, the watchdog tries to destroy it and then DefaultExecutor - * tries to clean up by joining with all installed pump stream threads. - * Problem is, that sometimes the native process doesn't die and thus - * streams aren't closed and the stream threads do not complete. - * - * @throws Exception the test failed - */ - @Test - public void testExec41WithStreams() throws Exception { - - CommandLine cmdLine; - - if (OS.isFamilyWindows()) { - cmdLine = CommandLine.parse("ping.exe -n 10 -w 1000 127.0.0.1"); - } else if ("HP-UX".equals(System.getProperty("os.name"))) { - // see EXEC-52 - option must appear after the hostname! - cmdLine = CommandLine.parse("ping 127.0.0.1 -n 10"); - } else if (OS.isFamilyUnix()) { - cmdLine = CommandLine.parse("ping -c 10 127.0.0.1"); - } else { - System.err.println("The test 'testExec41WithStreams' does not support the following OS : " - + System.getProperty("os.name")); - return; - } - - final DefaultExecutor executor = new DefaultExecutor(); - final ExecuteWatchdog watchdog = new ExecuteWatchdog(2 * 1000); // allow process no more than 2 secs - final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(System.out, System.err); - // this method was part of the patch I reverted - // pumpStreamHandler.setAlwaysWaitForStreamThreads(false); - - executor.setWatchdog(watchdog); - executor.setStreamHandler(pumpStreamHandler); - - final long startTime = System.currentTimeMillis(); - - try { - executor.execute(cmdLine); - } catch (final ExecuteException e) { - // nothing to do - } - - final long duration = System.currentTimeMillis() - startTime; - - System.out.println("Process completed in " + duration + " millis; below is its output"); - - if (watchdog.killedProcess()) { - System.out.println("Process timed out and was killed by watchdog."); - } - - assertTrue("The process was killed by the watchdog", watchdog.killedProcess()); - assertTrue("Skipping the Thread.join() did not work", duration < 9000); - } - - /** - * Test EXEC-41 with a disabled PumpStreamHandler to check if we could return - * immediately after killing the process (no streams implies no blocking - * stream pumper threads). But you have to be 100% sure that the subprocess - * is not writing to 'stdout' and 'stderr'. - * - * For this test we are using the batch file - under Windows the 'ping' - * process can't be killed (not supported by Win32) and will happily - * run the given time (e.g. 10 seconds) even hwen the batch file is already - * killed. - * - * @throws Exception the test failed - */ - @Test - public void testExec41WithoutStreams() throws Exception { - - final CommandLine cmdLine = new CommandLine(pingScript); - cmdLine.addArgument("10"); // sleep 10 secs - final DefaultExecutor executor = new DefaultExecutor(); - final ExecuteWatchdog watchdog = new ExecuteWatchdog(2*1000); // allow process no more than 2 secs - - // create a custom "PumpStreamHandler" doing no pumping at all - final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(null, null, null); - - executor.setWatchdog(watchdog); - executor.setStreamHandler(pumpStreamHandler); - - final long startTime = System.currentTimeMillis(); - - try { - executor.execute(cmdLine); - } catch (final ExecuteException e) { - System.out.println(e); - } - - final long duration = System.currentTimeMillis() - startTime; - - System.out.println("Process completed in " + duration +" millis; below is its output"); - - if (watchdog.killedProcess()) { - System.out.println("Process timed out and was killed."); - } - - assertTrue("The process was killed by the watchdog", watchdog.killedProcess()); - assertTrue("Skipping the Thread.join() did not work, duration="+duration, 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 - */ - @Test - public void testExec44() throws Exception { - - final CommandLine cl = new CommandLine(foreverTestScript); - final DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler(); - final 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()); - } - - /** - * Test EXEC-49 (https://issues.apache.org/jira/browse/EXEC-49). - * - * The issue was detected when trying to capture stdout/stderr with a PipedOutputStream and - * then pass that to a PipedInputStream. The following code will produce the error. - * The reason for the error is the PipedOutputStream is not being closed correctly, - * causing the PipedInputStream to break. - * - * @throws Exception the test failed - */ - @Test - public void testExec49_1() throws Exception { - - if (OS.isFamilyUnix()) { - - final CommandLine cl = CommandLine.parse("/bin/ls"); - cl.addArgument("/opt"); - - // redirect stdout/stderr to pipedOutputStream - final PipedOutputStream pipedOutputStream = new PipedOutputStream(); - final PumpStreamHandler psh = new PumpStreamHandler(pipedOutputStream); - exec.setStreamHandler(psh); - - // start an asynchronous process to enable the main thread - System.out.println("Preparing to execute process - commandLine=" + cl.toString()); - final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler(); - exec.execute(cl, handler); - System.out.println("Process spun off successfully - process=" + cl.getExecutable()); - - int x; - final PipedInputStream pis = new PipedInputStream(pipedOutputStream); - while ((x = pis.read()) >= 0) { - // System.out.println("pis.available() " + pis.available()); - // System.out.println("x " + x); - } - pis.close(); - - handler.waitFor(); - } - } - - /** - * Test EXEC-49 (https://issues.apache.org/jira/browse/EXEC-49). - * - * The issue was detected when trying to capture stdout with a PipedOutputStream and - * then pass that to a PipedInputStream. The following code will produce the error. - * The reason for the error is the PipedOutputStream is not being closed correctly, - * causing the PipedInputStream to break. - * - * @throws Exception the test failed - */ - @Test - public void testExec49_2() throws Exception { - - if (OS.isFamilyUnix()) { - - final CommandLine cl = CommandLine.parse("/bin/ls"); - cl.addArgument("/opt"); - - // redirect only stdout to pipedOutputStream - final PipedOutputStream pipedOutputStream = new PipedOutputStream(); - final PumpStreamHandler psh = new PumpStreamHandler(pipedOutputStream, new ByteArrayOutputStream()); - exec.setStreamHandler(psh); - - // start an asynchronous process to enable the main thread - System.out.println("Preparing to execute process - commandLine=" + cl.toString()); - final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler(); - exec.execute(cl, handler); - System.out.println("Process spun off successfully - process=" + cl.getExecutable()); - - int x; - final PipedInputStream pis = new PipedInputStream(pipedOutputStream); - while ((x = pis.read()) >= 0) { - // System.out.println("pis.available() " + pis.available()); - // System.out.println("x " + x); - } - pis.close(); - - handler.waitFor(); - } - } - - /** - * Test EXEC-57 (https://issues.apache.org/jira/browse/EXEC-57). - * - * DefaultExecutor.execute() does not return even if child process terminated - in this - * case the child process hangs because the grand children is connected to stdout & stderr - * and is still running. As work-around a stop timeout is used for the PumpStreamHandler - * to ensure that the caller does not block forever but if the stop timeout is exceeded - * an ExecuteException is thrown to notify the caller. - * - * @throws Exception the test failed - */ - @Test - public void testExec_57() throws IOException { - - if (!OS.isFamilyUnix()) { - System.err.println("The test 'testSyncInvocationOfBackgroundProcess' does not support the following OS : " + System.getProperty("os.name")); - return; - } - - final CommandLine cmdLine = new CommandLine("sh").addArgument("-c").addArgument(testDir + "/invoker.sh", false); - - final DefaultExecutor executor = new DefaultExecutor(); - final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(System.out, System.err); - - // Without this timeout current thread will be blocked - // even if command we'll invoke will terminate immediately. - pumpStreamHandler.setStopTimeout(2000); - executor.setStreamHandler(pumpStreamHandler); - final long startTime = System.currentTimeMillis(); - - System.out.println("Executing " + cmdLine); - - try { - executor.execute(cmdLine); - } - catch (final ExecuteException e) { - final long duration = System.currentTimeMillis() - startTime; - System.out.println("Process completed in " + duration +" millis; above is its output"); - return; - } - - fail("Expecting an ExecuteException"); - } - - /** - * Test EXEC-60 (https://issues.apache.org/jira/browse/EXEC-60). - * - * Possible deadlock when a process is terminating at the same time its timing out. Please - * note that a successful test is no proof that the issues was indeed fixed. - * - */ - @Test - public void testExec_60() throws Exception { - - final int start = 0; - final int seconds = 1; - final int offsetMultiplier = 1; - final int maxRetries = 180; - int processTerminatedCounter = 0; - int watchdogKilledProcessCounter = 0; - final CommandLine cmdLine = new CommandLine(pingScript); - cmdLine.addArgument(Integer.toString(seconds + 1)); // need to add "1" to wait the requested number of seconds - - final long startTime = System.currentTimeMillis(); - for (int offset = start; offset <= maxRetries; offset++) { - // wait progressively longer for process to complete - // tricky to get this test right. We want to try and catch the process while it is terminating, - // so we increase the timeout gradually until the test terminates normally. - // However if the increase is too gradual, we never wait long enough for any test to exit normally - final ExecuteWatchdog watchdog = new ExecuteWatchdog(seconds * 1000 + offset * offsetMultiplier); - exec.setWatchdog(watchdog); - try { - exec.execute(cmdLine); - processTerminatedCounter++; -// System.out.println(offset + ": process has terminated: " + watchdog.killedProcess()); - if (processTerminatedCounter > 5) { - break; - } - } catch (final ExecuteException ex) { -// System.out.println(offset + ": process was killed: " + watchdog.killedProcess()); - assertTrue("Watchdog killed the process", watchdog.killedProcess()); - watchdogKilledProcessCounter++; - } - } - - final long avg = (System.currentTimeMillis() - startTime) / - (watchdogKilledProcessCounter+processTerminatedCounter); - System.out.println("Processes terminated: "+processTerminatedCounter+" killed: "+watchdogKilledProcessCounter - +" Multiplier: "+offsetMultiplier+" MaxRetries: "+maxRetries+" Elapsed (avg ms): "+avg); - assertTrue("Not a single process terminated on its own", processTerminatedCounter > 0); - assertTrue("Not a single process was killed by the watch dog", watchdogKilledProcessCounter > 0); - } - - // ====================================================================== // === Long running tests // ====================================================================== Added: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec33Test.java URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec33Test.java?rev=1557130&view=auto ============================================================================== --- commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec33Test.java (added) +++ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec33Test.java Fri Jan 10 14:23:40 2014 @@ -0,0 +1,53 @@ +/* + * 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.issues; + +import static org.junit.Assert.assertFalse; + +import java.io.File; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.exec.TestUtil; +import org.junit.Test; + +/** + * Test the patch for EXEC-33 (https://issues.apache.org/jira/browse/EXEC-33) + * + * PumpStreamHandler hangs if System.in is redirect to process input stream . + * + * @version $Id$ + */ +public class Exec33Test { + + private final Executor exec = new DefaultExecutor(); + private final File testDir = new File("src/test/scripts"); + private final File testScript = TestUtil.resolveScriptForOS(testDir + "/test"); + + @Test + public void testExec33() throws Exception { + final CommandLine cl = new CommandLine(testScript); + final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(System.out, System.err, System.in); + final DefaultExecutor executor = new DefaultExecutor(); + executor.setStreamHandler(pumpStreamHandler); + final int exitValue = executor.execute(cl); + assertFalse(exec.isFailure(exitValue)); + } +} Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec33Test.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec33Test.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec34Test.java URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec34Test.java?rev=1557130&view=auto ============================================================================== --- commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec34Test.java (added) +++ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec34Test.java Fri Jan 10 14:23:40 2014 @@ -0,0 +1,91 @@ +/* + * 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.issues; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecuteResultHandler; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.TestUtil; +import org.junit.Test; + +/** + * EXEC-34 https://issues.apache.org/jira/browse/EXEC-34 + * + * @version $Id$ + */ +public class Exec34Test { + + private final Executor exec = new DefaultExecutor(); + private final File testDir = new File("src/test/scripts"); + private final File pingScript = TestUtil.resolveScriptForOS(testDir + "/ping"); + + /** + * + * 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 + */ + @Test + public void testExec34_1() throws Exception { + + final CommandLine cmdLine = new CommandLine(pingScript); + cmdLine.addArgument("10"); // sleep 10 secs + + final ExecuteWatchdog watchdog = new ExecuteWatchdog(Integer.MAX_VALUE); + final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler(); + exec.setWatchdog(watchdog); + exec.execute(cmdLine, handler); + assertTrue(watchdog.isWatching()); + watchdog.destroyProcess(); + assertTrue("Watchdog should have killed the process",watchdog.killedProcess()); + assertFalse("Watchdog is no longer watching the process",watchdog.isWatching()); + } + + /** + * Some user waited for an asynchronous process using watchdog.isWatching() which + * is now properly implemented using DefaultExecuteResultHandler. + * + * @throws Exception the test failed + */ + @Test + public void testExec34_2() throws Exception { + + final CommandLine cmdLine = new CommandLine(pingScript); + cmdLine.addArgument("10"); // sleep 10 secs + + final ExecuteWatchdog watchdog = new ExecuteWatchdog(5000); + final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler(); + exec.setWatchdog(watchdog); + exec.execute(cmdLine, handler); + handler.waitFor(); + assertTrue("Process has exited", handler.hasResult()); + assertNotNull("Process was aborted", handler.getException()); + assertTrue("Watchdog should have killed the process", watchdog.killedProcess()); + assertFalse("Watchdog is no longer watching the process", watchdog.isWatching()); + } +} Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec34Test.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec34Test.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec36Test.java URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec36Test.java?rev=1557130&view=auto ============================================================================== --- commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec36Test.java (added) +++ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec36Test.java Fri Jan 10 14:23:40 2014 @@ -0,0 +1,160 @@ +/* + * 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.issues; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.OS; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.exec.TestUtil; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Test EXEC-36 see https://issues.apache.org/jira/browse/EXEC-36 + * + * @version $Id$ + */ +public class Exec36Test { + + + private final Executor exec = new DefaultExecutor(); + private final File testDir = new File("src/test/scripts"); + private final File printArgsScript = TestUtil.resolveScriptForOS(testDir + "/printargs"); + + private ByteArrayOutputStream baos; + + @Before + public void setUp() throws Exception { + // 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(); + } + + /** + * + * Original example from Kai Hu which only can be tested on Unix + * + * @throws Exception the test failed + */ + @Test + public void testExec36_1() throws Exception { + + if (OS.isFamilyUnix()) { + + CommandLine cmdl; + + /** + * ./script/jrake cruise:publish_installers INSTALLER_VERSION=unstable_2_1 \ + * INSTALLER_PATH="/var/lib/ cruise-agent/installers" INSTALLER_DOWNLOAD_SERVER='something' WITHOUT_HELP_DOC=true + */ + + final String expected = "./script/jrake\n" + + "cruise:publish_installers\n" + + "INSTALLER_VERSION=unstable_2_1\n" + + "INSTALLER_PATH=\"/var/lib/ cruise-agent/installers\"\n" + + "INSTALLER_DOWNLOAD_SERVER='something'\n" + + "WITHOUT_HELP_DOC=true"; + + cmdl = new CommandLine(printArgsScript); + cmdl.addArgument("./script/jrake", false); + cmdl.addArgument("cruise:publish_installers", false); + cmdl.addArgument("INSTALLER_VERSION=unstable_2_1", false); + cmdl.addArgument("INSTALLER_PATH=\"/var/lib/ cruise-agent/installers\"", false); + cmdl.addArgument("INSTALLER_DOWNLOAD_SERVER='something'", false); + cmdl.addArgument("WITHOUT_HELP_DOC=true", false); + + final int exitValue = exec.execute(cmdl); + final String result = baos.toString().trim(); + assertFalse(exec.isFailure(exitValue)); + assertEquals(expected, result); + } + else { + System.err.println("The test 'testExec36_1' does not support the following OS : " + System.getProperty("os.name")); + return; + } + } + + /** + * Test a complex real example found at + * http://blogs.msdn.com/b/astebner/archive/2005/12/13/503471.aspx + * + * The command line is so weird that it even falls apart under Windows + * + * @throws Exception the test failed + */ + @Test + public void testExec36_2() throws Exception { + + String expected; + + // the original command line + // dotnetfx.exe /q:a /c:"install.exe /l ""\Documents and Settings\myusername\Local Settings\Temp\netfx.log"" /q" + + if (OS.isFamilyWindows()) { + expected = "dotnetfx.exe\n" + + "/q:a\n" + + "/c:\"install.exe /l \"\"\\Documents and Settings\\myusername\\Local Settings\\Temp\\netfx.log\"\" /q\""; + } + else if (OS.isFamilyUnix()) { + expected = "dotnetfx.exe\n" + + "/q:a\n" + + "/c:\"install.exe /l \"\"/Documents and Settings/myusername/Local Settings/Temp/netfx.log\"\" /q\""; + } + else { + System.err.println("The test 'testExec36_3' does not support the following OS : " + System.getProperty("os.name")); + return; + } + + CommandLine cmdl; + final File file = new File("/Documents and Settings/myusername/Local Settings/Temp/netfx.log"); + final Map map = new HashMap(); + map.put("FILE", file); + + cmdl = new CommandLine(printArgsScript); + cmdl.setSubstitutionMap(map); + cmdl.addArgument("dotnetfx.exe", false); + cmdl.addArgument("/q:a", false); + cmdl.addArgument("/c:\"install.exe /l \"\"${FILE}\"\" /q\"", false); + + final int exitValue = exec.execute(cmdl); + final String result = baos.toString().trim(); + assertFalse(exec.isFailure(exitValue)); + + if (OS.isFamilyUnix()) { + // the parameters fall literally apart under Windows - need to disable the check for Win32 + assertEquals(expected, result); + } + } + +} Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec36Test.java ------------------------------------------------------------------------------ svn:eol-style = native Added: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec41Test.java URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec41Test.java?rev=1557130&view=auto ============================================================================== --- commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec41Test.java (added) +++ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec41Test.java Fri Jan 10 14:23:40 2014 @@ -0,0 +1,146 @@ +/* + * 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.issues; + +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.OS; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.exec.TestUtil; +import org.junit.Test; + +/** + * Test the patch for EXEC-41 (https://issues.apache.org/jira/browse/EXEC-41). + * + * @version $Id$ + */ +public class Exec41Test { + + private final File testDir = new File("src/test/scripts"); + private final File pingScript = TestUtil.resolveScriptForOS(testDir + "/ping"); + + /** + * + * When a process runs longer than allowed by a configured watchdog's + * timeout, the watchdog tries to destroy it and then DefaultExecutor + * tries to clean up by joining with all installed pump stream threads. + * Problem is, that sometimes the native process doesn't die and thus + * streams aren't closed and the stream threads do not complete. + * + * @throws Exception the test failed + */ + @Test + public void testExec41WithStreams() throws Exception { + + CommandLine cmdLine; + + if (OS.isFamilyWindows()) { + cmdLine = CommandLine.parse("ping.exe -n 10 -w 1000 127.0.0.1"); + } else if ("HP-UX".equals(System.getProperty("os.name"))) { + // see EXEC-52 - option must appear after the hostname! + cmdLine = CommandLine.parse("ping 127.0.0.1 -n 10"); + } else if (OS.isFamilyUnix()) { + cmdLine = CommandLine.parse("ping -c 10 127.0.0.1"); + } else { + System.err.println("The test 'testExec41WithStreams' does not support the following OS : " + + System.getProperty("os.name")); + return; + } + + final DefaultExecutor executor = new DefaultExecutor(); + final ExecuteWatchdog watchdog = new ExecuteWatchdog(2 * 1000); // allow process no more than 2 secs + final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(System.out, System.err); + // this method was part of the patch I reverted + // pumpStreamHandler.setAlwaysWaitForStreamThreads(false); + + executor.setWatchdog(watchdog); + executor.setStreamHandler(pumpStreamHandler); + + final long startTime = System.currentTimeMillis(); + + try { + executor.execute(cmdLine); + } catch (final ExecuteException e) { + // nothing to do + } + + final long duration = System.currentTimeMillis() - startTime; + + System.out.println("Process completed in " + duration + " millis; below is its output"); + + if (watchdog.killedProcess()) { + System.out.println("Process timed out and was killed by watchdog."); + } + + assertTrue("The process was killed by the watchdog", watchdog.killedProcess()); + assertTrue("Skipping the Thread.join() did not work", duration < 9000); + } + + /** + * Test EXEC-41 with a disabled PumpStreamHandler to check if we could return + * immediately after killing the process (no streams implies no blocking + * stream pumper threads). But you have to be 100% sure that the subprocess + * is not writing to 'stdout' and 'stderr'. + * + * For this test we are using the batch file - under Windows the 'ping' + * process can't be killed (not supported by Win32) and will happily + * run the given time (e.g. 10 seconds) even hwen the batch file is already + * killed. + * + * @throws Exception the test failed + */ + @Test + public void testExec41WithoutStreams() throws Exception { + + final CommandLine cmdLine = new CommandLine(pingScript); + cmdLine.addArgument("10"); // sleep 10 secs + final DefaultExecutor executor = new DefaultExecutor(); + final ExecuteWatchdog watchdog = new ExecuteWatchdog(2*1000); // allow process no more than 2 secs + + // create a custom "PumpStreamHandler" doing no pumping at all + final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(null, null, null); + + executor.setWatchdog(watchdog); + executor.setStreamHandler(pumpStreamHandler); + + final long startTime = System.currentTimeMillis(); + + try { + executor.execute(cmdLine); + } catch (final ExecuteException e) { + System.out.println(e); + } + + final long duration = System.currentTimeMillis() - startTime; + + System.out.println("Process completed in " + duration +" millis; below is its output"); + + if (watchdog.killedProcess()) { + System.out.println("Process timed out and was killed."); + } + + assertTrue("The process was killed by the watchdog", watchdog.killedProcess()); + assertTrue("Skipping the Thread.join() did not work, duration="+duration, duration < 9000); + } +} Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec41Test.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec41Test.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec44Test.java URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec44Test.java?rev=1557130&view=auto ============================================================================== --- commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec44Test.java (added) +++ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec44Test.java Fri Jan 10 14:23:40 2014 @@ -0,0 +1,72 @@ +/* + * 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.issues; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecuteResultHandler; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.TestUtil; +import org.junit.Test; + +/** + * Test EXEC-44 (https://issues.apache.org/jira/browse/EXEC-44). + * + * @version $Id$ + */ +public class Exec44Test { + + private final Executor exec = new DefaultExecutor(); + private final File testDir = new File("src/test/scripts"); + private final File foreverTestScript = TestUtil.resolveScriptForOS(testDir + "/forever"); + + /** + * + * 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 + */ + @Test + public void testExec44() throws Exception { + + final CommandLine cl = new CommandLine(foreverTestScript); + final DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler(); + final 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()); + } +} Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec44Test.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec44Test.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec49Test.java URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec49Test.java?rev=1557130&view=auto ============================================================================== --- commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec49Test.java (added) +++ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec49Test.java Fri Jan 10 14:23:40 2014 @@ -0,0 +1,119 @@ +/* + * 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.issues; + +import java.io.ByteArrayOutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecuteResultHandler; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.OS; +import org.apache.commons.exec.PumpStreamHandler; +import org.junit.Test; + +/** + * Test EXEC-44 (https://issues.apache.org/jira/browse/EXEC-44). + * + * @version $Id$ + */ +public class Exec49Test { + + private final Executor exec = new DefaultExecutor(); + + /** + * The issue was detected when trying to capture stdout/stderr with a PipedOutputStream and + * then pass that to a PipedInputStream. The following code will produce the error. + * The reason for the error is the PipedOutputStream is not being closed correctly, + * causing the PipedInputStream to break. + * + * @throws Exception the test failed + */ + @Test + public void testExec49_1() throws Exception { + + if (OS.isFamilyUnix()) { + + final CommandLine cl = CommandLine.parse("/bin/ls"); + cl.addArgument("/opt"); + + // redirect stdout/stderr to pipedOutputStream + final PipedOutputStream pipedOutputStream = new PipedOutputStream(); + final PumpStreamHandler psh = new PumpStreamHandler(pipedOutputStream); + exec.setStreamHandler(psh); + + // start an asynchronous process to enable the main thread + System.out.println("Preparing to execute process - commandLine=" + cl.toString()); + final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler(); + exec.execute(cl, handler); + System.out.println("Process spun off successfully - process=" + cl.getExecutable()); + + int x; + final PipedInputStream pis = new PipedInputStream(pipedOutputStream); + while ((x = pis.read()) >= 0) { + // System.out.println("pis.available() " + pis.available()); + // System.out.println("x " + x); + } + pis.close(); + + handler.waitFor(); + } + } + + /** + * The issue was detected when trying to capture stdout with a PipedOutputStream and + * then pass that to a PipedInputStream. The following code will produce the error. + * The reason for the error is the PipedOutputStream is not being closed correctly, + * causing the PipedInputStream to break. + * + * @throws Exception the test failed + */ + @Test + public void testExec49_2() throws Exception { + + if (OS.isFamilyUnix()) { + + final CommandLine cl = CommandLine.parse("/bin/ls"); + cl.addArgument("/opt"); + + // redirect only stdout to pipedOutputStream + final PipedOutputStream pipedOutputStream = new PipedOutputStream(); + final PumpStreamHandler psh = new PumpStreamHandler(pipedOutputStream, new ByteArrayOutputStream()); + exec.setStreamHandler(psh); + + // start an asynchronous process to enable the main thread + System.out.println("Preparing to execute process - commandLine=" + cl.toString()); + final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler(); + exec.execute(cl, handler); + System.out.println("Process spun off successfully - process=" + cl.getExecutable()); + + int x; + final PipedInputStream pis = new PipedInputStream(pipedOutputStream); + while ((x = pis.read()) >= 0) { + // System.out.println("pis.available() " + pis.available()); + // System.out.println("x " + x); + } + pis.close(); + + handler.waitFor(); + } + } + +} Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec49Test.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec49Test.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec57Test.java URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec57Test.java?rev=1557130&view=auto ============================================================================== --- commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec57Test.java (added) +++ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec57Test.java Fri Jan 10 14:23:40 2014 @@ -0,0 +1,86 @@ +/* + * 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.issues; + +import static org.junit.Assert.fail; + +import java.io.File; +import java.io.IOException; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.OS; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.exec.TestUtil; +import org.junit.Test; + +/** + * Test EXEC-57 (https://issues.apache.org/jira/browse/EXEC-57). + * + * @version $Id$ + */ +public class Exec57Test { + + private final File testDir = new File("src/test/scripts"); + + + /** + * + * DefaultExecutor.execute() does not return even if child process terminated - in this + * case the child process hangs because the grand children is connected to stdout & stderr + * and is still running. As work-around a stop timeout is used for the PumpStreamHandler + * to ensure that the caller does not block forever but if the stop timeout is exceeded + * an ExecuteException is thrown to notify the caller. + * + * @throws Exception the test failed + */ + @Test + public void testExec_57() throws IOException { + + if (!OS.isFamilyUnix()) { + System.err.println("The test 'testSyncInvocationOfBackgroundProcess' does not support the following OS : " + System.getProperty("os.name")); + return; + } + + final CommandLine cmdLine = new CommandLine("sh").addArgument("-c").addArgument(testDir + "/invoker.sh", false); + + final DefaultExecutor executor = new DefaultExecutor(); + final PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(System.out, System.err); + + // Without this timeout current thread will be blocked + // even if command we'll invoke will terminate immediately. + pumpStreamHandler.setStopTimeout(2000); + executor.setStreamHandler(pumpStreamHandler); + final long startTime = System.currentTimeMillis(); + + System.out.println("Executing " + cmdLine); + + try { + executor.execute(cmdLine); + } + catch (final ExecuteException e) { + final long duration = System.currentTimeMillis() - startTime; + System.out.println("Process completed in " + duration +" millis; above is its output"); + return; + } + + fail("Expecting an ExecuteException"); + } +} Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec57Test.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec57Test.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec60Test.java URL: http://svn.apache.org/viewvc/commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec60Test.java?rev=1557130&view=auto ============================================================================== --- commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec60Test.java (added) +++ commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec60Test.java Fri Jan 10 14:23:40 2014 @@ -0,0 +1,88 @@ +/* + * 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.issues; + +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.TestUtil; +import org.junit.Test; + +/** + * Test EXEC-60 (https://issues.apache.org/jira/browse/EXEC-60). + * + * @version $Id$ + */ +public class Exec60Test { + + private final Executor exec = new DefaultExecutor(); + private final File testDir = new File("src/test/scripts"); + private final File pingScript = TestUtil.resolveScriptForOS(testDir + "/ping"); + + /** + * Possible deadlock when a process is terminating at the same time its timing out. Please + * note that a successful test is no proof that the issues was indeed fixed. + */ + @Test + public void testExec_60() throws Exception { + + final int start = 0; + final int seconds = 1; + final int offsetMultiplier = 1; + final int maxRetries = 180; + int processTerminatedCounter = 0; + int watchdogKilledProcessCounter = 0; + final CommandLine cmdLine = new CommandLine(pingScript); + cmdLine.addArgument(Integer.toString(seconds + 1)); // need to add "1" to wait the requested number of seconds + + final long startTime = System.currentTimeMillis(); + for (int offset = start; offset <= maxRetries; offset++) { + // wait progressively longer for process to complete + // tricky to get this test right. We want to try and catch the process while it is terminating, + // so we increase the timeout gradually until the test terminates normally. + // However if the increase is too gradual, we never wait long enough for any test to exit normally + final ExecuteWatchdog watchdog = new ExecuteWatchdog(seconds * 1000 + offset * offsetMultiplier); + exec.setWatchdog(watchdog); + try { + exec.execute(cmdLine); + processTerminatedCounter++; +// System.out.println(offset + ": process has terminated: " + watchdog.killedProcess()); + if (processTerminatedCounter > 5) { + break; + } + } catch (final ExecuteException ex) { +// System.out.println(offset + ": process was killed: " + watchdog.killedProcess()); + assertTrue("Watchdog killed the process", watchdog.killedProcess()); + watchdogKilledProcessCounter++; + } + } + + final long avg = (System.currentTimeMillis() - startTime) / + (watchdogKilledProcessCounter+processTerminatedCounter); + System.out.println("Processes terminated: " + processTerminatedCounter + " killed: " + watchdogKilledProcessCounter + + " Multiplier: " + offsetMultiplier + " MaxRetries: " + maxRetries + " Elapsed (avg ms): " + avg); + assertTrue("Not a single process terminated on its own", processTerminatedCounter > 0); + assertTrue("Not a single process was killed by the watch dog", watchdogKilledProcessCounter > 0); + } +} Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec60Test.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/exec/trunk/src/test/java/org/apache/commons/exec/issues/Exec60Test.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL