package org.junit.internal.runners.statements; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.runners.model.Statement; import org.junit.runners.model.TestTimedOutException; public class FailOnTimeout extends Statement { private final Statement originalStatement; private final TimeUnit timeUnit; private final long timeout; /** * Returns a new builder for building an instance. * * @since 4.12 */ public static Builder builder() { return new Builder(); } /** * Creates an instance wrapping the given statement with the given timeout in milliseconds. * * @param statement the statement to wrap * @param timeoutMillis the timeout in milliseconds * @deprecated use {@link #builder()} instead. */ @Deprecated public FailOnTimeout(Statement statement, long timeoutMillis) { this(builder().withTimeout(timeoutMillis, TimeUnit.MILLISECONDS), statement); } private FailOnTimeout(Builder builder, Statement statement) { originalStatement = statement; timeout = builder.timeout; timeUnit = builder.unit; } /** * Builder for {@link FailOnTimeout}. * * @since 4.12 */ public static class Builder { private long timeout = 0; private TimeUnit unit = TimeUnit.SECONDS; private Builder() { } /** * Specifies the time to wait before timing out the test. * *
If this is not called, or is called with a {@code timeout} of
* {@code 0}, the returned {@code Statement} will wait forever for the
* test to complete, however the test will still launch from a separate
* thread. This can be useful for disabling timeouts in environments
* where they are dynamically set based on some property.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the {@code timeout} argument
* @return {@code this} for method chaining.
*/
public Builder withTimeout(long timeout, TimeUnit unit) {
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be non-negative");
}
if (unit == null) {
throw new NullPointerException("TimeUnit cannot be null");
}
this.timeout = timeout;
this.unit = unit;
return this;
}
/**
* Builds a {@link FailOnTimeout} instance using the values in this builder,
* wrapping the given statement.
*
* @param statement
*/
public FailOnTimeout build(Statement statement) {
if (statement == null) {
throw new NullPointerException("statement cannot be null");
}
return new FailOnTimeout(this, statement);
}
}
@Override
public void evaluate() throws Throwable {
CallableStatement callable = new CallableStatement();
FutureTask