name.didier.david.test4j.utils.StdCaptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ndd-test4j Show documentation
Show all versions of ndd-test4j Show documentation
Test4J provides testing support.
The newest version!
package name.didier.david.test4j.utils;
import static name.didier.david.check4j.ConciseCheckers.checkStrictlyPositive;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
/**
* Capture the standard output stream and the standard error stream. Usage:
*
*
* StdCaptor captor = new StdCaptor();
* try {
* captor.startStdOutCapture();
* captor.startStdErrCapture();
* outputSomething();
* } catch (Exception e) {
* propagate(e);
* } finally {
* String stdOutCapture = captor.stopStdOutCapture(printStdOut);
* String stdErrCapture = captor.stopStdErrCapture(printStdErr);
* doSomething(stdOutCapture, stdErrCapture);
* }
*
*
* @author ddidier
*/
public class StdCaptor {
/** The default size of the capturing buffers. */
private static final int DEFAULT_BUFFER_SIZE = 1024;
/** The size of the capturing buffers. */
private final Integer bufferSize;
/** The backup STDOUT. */
private PrintStream oldStdOut;
/** The capturing STDOUT. */
private ByteArrayOutputStream newStdOut;
/** The backup STDERR. */
private PrintStream oldStdErr;
/** The capturing STDERR. */
private ByteArrayOutputStream newStdErr;
/** Default constructor. */
public StdCaptor() {
this(DEFAULT_BUFFER_SIZE);
}
/**
* Default constructor.
*
* @param bufferSize the size of the capturing buffers.
*/
public StdCaptor(final int bufferSize) {
super();
this.bufferSize = checkStrictlyPositive(bufferSize, "bufferSize");
}
/**
* Start to capture the standard output. The standard output stream is reassigned so do not forget to restore the
* previous state with {@link #stopStdOutCapture()}. Use a {@code finally} block!
*
* @throws IllegalStateException if already capturing STDOUT.
*/
public void startStdOutCapture() {
if (isCapturingStdOut()) {
throw new IllegalStateException("Already capturing STDOUT");
}
oldStdOut = System.out;
newStdOut = new ByteArrayOutputStream(bufferSize);
System.setOut(newPrintStream(newStdOut));
}
/**
* Stop to capture the standard output. The previous output stream is restored. Should be used in a {@code finally}
* block!
*
* @return the captured data.
* @throws IllegalStateException if not capturing STDOUT.
*/
public String stopStdOutCapture() {
return stopStdOutCapture(false);
}
/**
* Stop to capture the standard output then print the capture data to STDOUT. The previous output stream is
* restored. Should be used in a {@code finally} block!
*
* @param print true
to print the capture data to STDOUT, false
otherwise.
* @return the captured data.
* @throws IllegalStateException if not capturing STDOUT.
*/
public String stopStdOutCapture(final boolean print) {
if (!isCapturingStdOut()) {
throw new IllegalStateException("Not capturing STDOUT");
}
System.out.flush();
System.setOut(oldStdOut);
String capture = toString(newStdOut);
resetStdOut();
if (print) {
// CSOFF: RegexpCheck +1
System.out.print(capture);
}
return capture;
}
/**
* @return true
if capturing the standard stream, false
otherwise.
*/
public boolean isCapturingStdOut() {
return newStdOut != null;
}
// -----------------------------------------------------------------------------------------------------------------
/**
* Start to capture the standard error. The standard error stream is reassigned so do not forget to restore the
* previous state with {@link #stopStdErrCapture()}. Use a {@code finally} block!
*
* @throws IllegalStateException if already capturing STDERR.
*/
public void startStdErrCapture() {
if (isCapturingStdErr()) {
throw new IllegalStateException("Already capturing STDERR");
}
oldStdErr = System.err;
newStdErr = new ByteArrayOutputStream(bufferSize);
System.setErr(newPrintStream(newStdErr));
}
/**
* Stop to capture the standard error. The previous error stream is restored. Should be used in a {@code finally}
* block!
*
* @return the captured data.
* @throws IllegalStateException if not capturing STDERR.
*/
public String stopStdErrCapture() {
return stopStdErrCapture(false);
}
/**
* Stop to capture the standard error then print the capture data to STDERR. The previous error stream is restored.
* Should be used in a {@code finally} block!
*
* @param print true
to print the capture data to STDERR, false
otherwise.
* @return the captured data.
* @throws IllegalStateException if not capturing STDERR.
*/
public String stopStdErrCapture(final boolean print) {
if (!isCapturingStdErr()) {
throw new IllegalStateException("Not capturing STDERR");
}
System.err.flush();
System.setErr(oldStdErr);
String capture = toString(newStdErr);
resetStdErr();
if (print) {
// CSOFF: RegexpCheck +1
System.err.print(capture);
}
return capture;
}
/**
* @return true
if capturing the error stream, false
otherwise.
*/
public boolean isCapturingStdErr() {
return newStdErr != null;
}
// -----------------------------------------------------------------------------------------------------------------
/**
* Reset the capturing state of STDOUT.
*/
private void resetStdOut() {
oldStdOut = null;
newStdOut = null;
}
/**
* Reset the capturing state of STDERR.
*/
private void resetStdErr() {
oldStdErr = null;
newStdErr = null;
}
/**
* @param out the output stream to which values and objects will be printed.
* @return a new {@link PrintStream} with UTF-8 encoding.
*/
private PrintStream newPrintStream(final OutputStream out) {
try {
return new PrintStream(out, false, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
// should never happen
throw new RuntimeException("Error while creating stream", e);
}
}
/**
* @param baos the stream to decode.
* @return the content of the stream.
*/
private String toString(final ByteArrayOutputStream baos) {
try {
return baos.toString(StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
// should never happen
throw new RuntimeException("Error while printing stream", e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy