blob: a6af4c69b39a6104ba7a3baffa356916ddd73d0b [file] [log] [blame]
/*
* 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).
*
*/
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 seconds
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 seconds
final DefaultExecutor executor = new DefaultExecutor();
final ExecuteWatchdog watchdog = new ExecuteWatchdog(2*1000); // allow process no more than 2 seconds
// 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);
}
}