Home | History | Annotate | Download | only in rules
      1 package org.junit.rules;
      2 
      3 import org.junit.internal.runners.statements.FailOnTimeout;
      4 import org.junit.runner.Description;
      5 import org.junit.runners.model.Statement;
      6 
      7 import java.util.concurrent.TimeUnit;
      8 
      9 /**
     10  * The Timeout Rule applies the same timeout to all test methods in a class:
     11  * <pre>
     12  * public static class HasGlobalLongTimeout {
     13  *
     14  *  &#064;Rule
     15  *  public Timeout globalTimeout= new Timeout(20);
     16  *
     17  *  &#064;Test
     18  *  public void run1() throws InterruptedException {
     19  *      Thread.sleep(100);
     20  *  }
     21  *
     22  *  &#064;Test
     23  *  public void infiniteLoop() {
     24  *      while (true) {}
     25  *  }
     26  * }
     27  * </pre>
     28  * <p>
     29  * Each test is run in a new thread. If the specified timeout elapses before
     30  * the test completes, its execution is interrupted via {@link Thread#interrupt()}.
     31  * This happens in interruptable I/O and locks, and methods in {@link Object}
     32  * and {@link Thread} throwing {@link InterruptedException}.
     33  * <p>
     34  * A specified timeout of 0 will be interpreted as not set, however tests will
     35  * still launch from separate threads. This can be useful for disabling timeouts
     36  * in environments where they are dynamically set based on some property.
     37  *
     38  * @since 4.7
     39  */
     40 public class Timeout implements TestRule {
     41     private final long timeout;
     42     private final TimeUnit timeUnit;
     43 
     44     /**
     45      * Returns a new builder for building an instance.
     46      *
     47      * @since 4.12
     48      */
     49     public static Builder builder() {
     50         return new Builder();
     51     }
     52 
     53     /**
     54      * Create a {@code Timeout} instance with the timeout specified
     55      * in milliseconds.
     56      * <p>
     57      * This constructor is deprecated.
     58      * <p>
     59      * Instead use {@link #Timeout(long, java.util.concurrent.TimeUnit)},
     60      * {@link Timeout#millis(long)}, or {@link Timeout#seconds(long)}.
     61      *
     62      * @param millis the maximum time in milliseconds to allow the
     63      * test to run before it should timeout
     64      */
     65     @Deprecated
     66     public Timeout(int millis) {
     67         this(millis, TimeUnit.MILLISECONDS);
     68     }
     69 
     70     /**
     71      * Create a {@code Timeout} instance with the timeout specified
     72      * at the timeUnit of granularity of the provided {@code TimeUnit}.
     73      *
     74      * @param timeout the maximum time to allow the test to run
     75      * before it should timeout
     76      * @param timeUnit the time unit for the {@code timeout}
     77      * @since 4.12
     78      */
     79     public Timeout(long timeout, TimeUnit timeUnit) {
     80         this.timeout = timeout;
     81         this.timeUnit = timeUnit;
     82     }
     83 
     84     /**
     85      * Create a {@code Timeout} instance initialized with values form
     86      * a builder.
     87      *
     88      * @since 4.12
     89      */
     90     protected Timeout(Builder builder) {
     91         timeout = builder.getTimeout();
     92         timeUnit = builder.getTimeUnit();
     93     }
     94 
     95     /**
     96      * Creates a {@link Timeout} that will timeout a test after the
     97      * given duration, in milliseconds.
     98      *
     99      * @since 4.12
    100      */
    101     public static Timeout millis(long millis) {
    102         return new Timeout(millis, TimeUnit.MILLISECONDS);
    103     }
    104 
    105     /**
    106      * Creates a {@link Timeout} that will timeout a test after the
    107      * given duration, in seconds.
    108      *
    109      * @since 4.12
    110      */
    111     public static Timeout seconds(long seconds) {
    112         return new Timeout(seconds, TimeUnit.SECONDS);
    113     }
    114 
    115     /**
    116      * Gets the timeout configured for this rule, in the given units.
    117      *
    118      * @since 4.12
    119      */
    120     protected final long getTimeout(TimeUnit unit) {
    121         return unit.convert(timeout, timeUnit);
    122     }
    123 
    124     /**
    125      * Creates a {@link Statement} that will run the given
    126      * {@code statement}, and timeout the operation based
    127      * on the values configured in this rule. Subclasses
    128      * can override this method for different behavior.
    129      *
    130      * @since 4.12
    131      */
    132     protected Statement createFailOnTimeoutStatement(
    133             Statement statement) throws Exception {
    134         return FailOnTimeout.builder()
    135             .withTimeout(timeout, timeUnit)
    136             .build(statement);
    137     }
    138 
    139     public Statement apply(Statement base, Description description) {
    140         try {
    141             return createFailOnTimeoutStatement(base);
    142         } catch (final Exception e) {
    143             return new Statement() {
    144                 @Override public void evaluate() throws Throwable {
    145                     throw new RuntimeException("Invalid parameters for Timeout", e);
    146                 }
    147             };
    148         }
    149     }
    150 
    151     /**
    152      * Builder for {@link Timeout}.
    153      *
    154      * @since 4.12
    155      */
    156     public static class Builder {
    157         private boolean lookForStuckThread = false;
    158         private long timeout = 0;
    159         private TimeUnit timeUnit = TimeUnit.SECONDS;
    160 
    161         protected Builder() {
    162         }
    163 
    164         /**
    165          * Specifies the time to wait before timing out the test.
    166          *
    167          * <p>If this is not called, or is called with a
    168          * {@code timeout} of {@code 0}, the returned {@code Timeout}
    169          * rule instance will cause the tests to wait forever to
    170          * complete, however the tests will still launch from a
    171          * separate thread. This can be useful for disabling timeouts
    172          * in environments where they are dynamically set based on
    173          * some property.
    174          *
    175          * @param timeout the maximum time to wait
    176          * @param unit the time unit of the {@code timeout} argument
    177          * @return {@code this} for method chaining.
    178          */
    179         public Builder withTimeout(long timeout, TimeUnit unit) {
    180             this.timeout = timeout;
    181             this.timeUnit = unit;
    182             return this;
    183         }
    184 
    185         protected long getTimeout() {
    186             return timeout;
    187         }
    188 
    189         protected TimeUnit getTimeUnit()  {
    190             return timeUnit;
    191         }
    192 
    193         /**
    194          * Builds a {@link Timeout} instance using the values in this builder.,
    195          */
    196         public Timeout build() {
    197             return new Timeout(this);
    198         }
    199     }
    200 }
    201