blob: 5e26715b15617cfc19eedf3be9c5e5b16470e6ff [file] [log] [blame]
package com.gemstone.gemfire.internal.process;
import static org.junit.Assert.*;
import java.util.concurrent.Callable;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import com.gemstone.gemfire.internal.process.ProcessStreamReader.InputListener;
import com.gemstone.gemfire.internal.process.ProcessStreamReader.ReadingMode;
import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
/**
* Tests NonBlockingProcessStreamReader which was introduced to fix TRAC bug #51967.
*
* None of the tests should be skipped or hang on Windows.
*
* @author Kirk Lund
* @since 8.2
*/
@Category(IntegrationTest.class)
public class NonBlockingProcessStreamReaderJUnitTest extends ProcessStreamReaderTestCase {
@Test
public void canCloseStreamsWhileProcessIsAlive() throws Exception {
this.process = new ProcessBuilder(createCommandLine(ProcessSleeps.class)).start();
this.stderr = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getErrorStream())
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stdout = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getInputStream())
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stderr.start();
this.stdout.start();
assertIsAlive(this.process);
assertEventuallyIsRunning(this.stderr);
assertEventuallyIsRunning(this.stdout);
this.process.getErrorStream().close();
this.process.getOutputStream().close();
this.process.getInputStream().close();
this.stderr.stop();
this.stdout.stop();
assertIsAlive(this.process);
this.process.destroy();
}
@Test
public void canStopReadersWhileProcessIsAlive() throws Exception {
this.process = new ProcessBuilder(createCommandLine(ProcessSleeps.class)).start();
this.stderr = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getErrorStream())
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stdout = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getInputStream())
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stderr.start();
this.stdout.start();
assertIsAlive(this.process);
assertEventuallyIsRunning(this.stderr);
assertEventuallyIsRunning(this.stdout);
this.stderr.stop();
this.stdout.stop();
this.process.getErrorStream().close();
this.process.getOutputStream().close();
this.process.getInputStream().close();
assertIsAlive(this.process);
this.process.destroy();
}
@Test
public void capturesStdoutWhileProcessIsAlive() throws Exception {
this.process = new ProcessBuilder(createCommandLine(ProcessPrintsToStdout.class)).start();
final StringBuffer stderrBuffer = new StringBuffer();
InputListener stderrListener = new InputListener() {
@Override
public void notifyInputLine(String line) {
stderrBuffer.append(line);
}
};
final StringBuffer stdoutBuffer = new StringBuffer();
InputListener stdoutListener = new InputListener() {
@Override
public void notifyInputLine(String line) {
stdoutBuffer.append(line);
}
};
this.stderr = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getErrorStream())
.inputListener(stderrListener)
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stdout = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getInputStream())
.inputListener(stdoutListener)
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stderr.start();
this.stdout.start();
// wait for process to start
assertEventuallyTrue("Process never started", new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return ProcessUtils.isProcessAlive(process);
}
}, WAIT_FOR_PROCESS_TO_START_TIMEOUT, INTERVAL);
// wait for process to die
assertEventuallyFalse("Process never died", new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return ProcessUtils.isProcessAlive(process);
}
}, WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
final int exitValue = this.process.exitValue();
assertEquals(0, exitValue);
this.stderr.join(READER_JOIN_TIMEOUT);
assertFalse(this.stderr.isRunning());
this.stdout.join(READER_JOIN_TIMEOUT);
assertFalse(this.stdout.isRunning());
//System.out.println("Stopping ProcessStreamReader");
this.stderr.stop();
this.stdout.stop();
//System.out.println("stderr=\n" + stderrBuffer.toString());
assertEquals("", stderrBuffer.toString());
//System.out.println("stdout=\n" + stdoutBuffer.toString());
StringBuilder sb = new StringBuilder().append(ProcessPrintsToStdout.LINES[0]).append(ProcessPrintsToStdout.LINES[1]).append(ProcessPrintsToStdout.LINES[2]);
assertEquals(sb.toString(), stdoutBuffer.toString());
//System.out.println("Closing streams");
this.process.getErrorStream().close();
this.process.getInputStream().close();
this.process.destroy();
}
@Test
public void capturesStderrWhileProcessIsAlive() throws Exception {
this.process = new ProcessBuilder(createCommandLine(ProcessPrintsToStderr.class)).start();
final StringBuffer stderrBuffer = new StringBuffer();
InputListener stderrListener = new InputListener() {
@Override
public void notifyInputLine(String line) {
stderrBuffer.append(line);
}
};
final StringBuffer stdoutBuffer = new StringBuffer();
InputListener stdoutListener = new InputListener() {
@Override
public void notifyInputLine(String line) {
stdoutBuffer.append(line);
}
};
this.stderr = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getErrorStream())
.inputListener(stderrListener)
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stdout = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getInputStream())
.inputListener(stdoutListener)
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stderr.start();
this.stdout.start();
// wait for process to start
assertEventuallyTrue("Process never started", new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return ProcessUtils.isProcessAlive(process);
}
}, WAIT_FOR_PROCESS_TO_START_TIMEOUT, INTERVAL);
// wait for process to die
assertEventuallyFalse("Process never died", new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return ProcessUtils.isProcessAlive(process);
}
}, WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
final int exitValue = this.process.exitValue();
assertEquals(0, exitValue);
this.stderr.join(READER_JOIN_TIMEOUT);
assertFalse(this.stderr.isRunning());
this.stdout.join(READER_JOIN_TIMEOUT);
assertFalse(this.stdout.isRunning());
//System.out.println("Stopping ProcessStreamReader");
this.stderr.stop();
this.stdout.stop();
//System.out.println("stderr=\n" + stderrBuffer.toString());
StringBuilder sb = new StringBuilder().append(ProcessPrintsToStderr.LINES[0]).append(ProcessPrintsToStderr.LINES[1]).append(ProcessPrintsToStderr.LINES[2]);
assertEquals(sb.toString(), stderrBuffer.toString());
//System.out.println("stdout=\n" + stdoutBuffer.toString());
assertEquals("", stdoutBuffer.toString());
//System.out.println("Closing streams");
this.process.getErrorStream().close();
this.process.getInputStream().close();
this.process.destroy();
}
@Test
public void capturesBothWhileProcessIsAlive() throws Exception {
this.process = new ProcessBuilder(createCommandLine(ProcessPrintsToBoth.class)).start();
final StringBuffer stderrBuffer = new StringBuffer();
InputListener stderrListener = new InputListener() {
@Override
public void notifyInputLine(String line) {
stderrBuffer.append(line);
}
};
final StringBuffer stdoutBuffer = new StringBuffer();
InputListener stdoutListener = new InputListener() {
@Override
public void notifyInputLine(String line) {
stdoutBuffer.append(line);
}
};
this.stderr = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getErrorStream())
.inputListener(stderrListener)
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stdout = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getInputStream())
.inputListener(stdoutListener)
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stderr.start();
this.stdout.start();
// wait for process to start
assertEventuallyTrue("Process never started", new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return ProcessUtils.isProcessAlive(process);
}
}, WAIT_FOR_PROCESS_TO_START_TIMEOUT, INTERVAL);
// wait for process to die
assertEventuallyFalse("Process never died", new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return ProcessUtils.isProcessAlive(process);
}
}, WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
final int exitValue = this.process.exitValue();
assertEquals(0, exitValue);
this.stderr.join(READER_JOIN_TIMEOUT);
assertFalse(this.stderr.isRunning());
this.stdout.join(READER_JOIN_TIMEOUT);
assertFalse(this.stdout.isRunning());
//System.out.println("Stopping ProcessStreamReader");
this.stderr.stop();
this.stdout.stop();
//System.out.println("stderr=\n" + stderrBuffer.toString());
StringBuilder sb = new StringBuilder().append(ProcessPrintsToBoth.ERR_LINES[0]).append(ProcessPrintsToBoth.ERR_LINES[1]).append(ProcessPrintsToBoth.ERR_LINES[2]);
assertEquals(sb.toString(), stderrBuffer.toString());
//System.out.println("stdout=\n" + stdoutBuffer.toString());
sb = new StringBuilder().append(ProcessPrintsToBoth.OUT_LINES[0]).append(ProcessPrintsToBoth.OUT_LINES[1]).append(ProcessPrintsToBoth.OUT_LINES[2]);
assertEquals(sb.toString(), stdoutBuffer.toString());
//System.out.println("Closing streams");
this.process.getErrorStream().close();
this.process.getInputStream().close();
this.process.destroy();
}
@Test
public void capturesStderrWhenProcessFailsDuringStart() throws Exception {
this.process = new ProcessBuilder(createCommandLine(ProcessThrowsError.class)).start();
final StringBuffer stderrBuffer = new StringBuffer();
InputListener stderrListener = new InputListener() {
@Override
public void notifyInputLine(String line) {
stderrBuffer.append(line);
}
};
final StringBuffer stdoutBuffer = new StringBuffer();
InputListener stdoutListener = new InputListener() {
@Override
public void notifyInputLine(String line) {
stdoutBuffer.append(line);
}
};
this.stderr = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getErrorStream())
.inputListener(stderrListener)
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stdout = new ProcessStreamReader.Builder(this.process)
.inputStream(this.process.getInputStream())
.inputListener(stdoutListener)
.readingMode(ReadingMode.NON_BLOCKING)
.build();
this.stderr.start();
this.stdout.start();
// wait for process to die
assertEventuallyFalse("Process never died", new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return ProcessUtils.isProcessAlive(process);
}
}, WAIT_FOR_PROCESS_TO_DIE_TIMEOUT, INTERVAL);
final int exitValue = this.process.exitValue();
assertNotEquals(0, exitValue);
this.stderr.join(READER_JOIN_TIMEOUT);
assertFalse(this.stderr.isRunning());
this.stdout.join(READER_JOIN_TIMEOUT);
assertFalse(this.stdout.isRunning());
//System.out.println("Stopping ProcessStreamReader");
this.stderr.stop();
this.stdout.stop();
//System.out.println("stderr=\n" + stderrBuffer.toString());
assertTrue(stderrBuffer.toString() + " does not contain " + ProcessThrowsError.ERROR_MSG, stderrBuffer.toString().contains(ProcessThrowsError.ERROR_MSG));
//System.out.println("stdout=\n" + stdoutBuffer.toString());
//System.out.println("Closing streams");
this.process.getErrorStream().close();
this.process.getInputStream().close();
this.process.destroy();
}
}