001    package org.junit.rules;
002    
003    import org.junit.internal.runners.statements.FailOnTimeout;
004    import org.junit.runner.Description;
005    import org.junit.runners.model.Statement;
006    
007    import java.util.concurrent.TimeUnit;
008    
009    /**
010     * The Timeout Rule applies the same timeout to all test methods in a class:
011     * <pre>
012     * public static class HasGlobalLongTimeout {
013     *
014     *  &#064;Rule
015     *  public Timeout globalTimeout= new Timeout(20);
016     *
017     *  &#064;Test
018     *  public void run1() throws InterruptedException {
019     *      Thread.sleep(100);
020     *  }
021     *
022     *  &#064;Test
023     *  public void infiniteLoop() {
024     *      while (true) {}
025     *  }
026     * }
027     * </pre>
028     * <p>
029     * Each test is run in a new thread. If the specified timeout elapses before
030     * the test completes, its execution is interrupted via {@link Thread#interrupt()}.
031     * This happens in interruptable I/O and locks, and methods in {@link Object}
032     * and {@link Thread} throwing {@link InterruptedException}.
033     * <p>
034     * A specified timeout of 0 will be interpreted as not set, however tests will
035     * still launch from separate threads. This can be useful for disabling timeouts
036     * in environments where they are dynamically set based on some property.
037     *
038     * @since 4.7
039     */
040    public class Timeout implements TestRule {
041        private final long timeout;
042        private final TimeUnit timeUnit;
043        private final boolean lookForStuckThread;
044    
045        /**
046         * Create a {@code Timeout} instance with the timeout specified
047         * in milliseconds.
048         * <p>
049         * This constructor is deprecated.
050         * <p>
051         * Instead use {@link #Timeout(long, java.util.concurrent.TimeUnit)},
052         * {@link Timeout#millis(long)}, or {@link Timeout#seconds(long)}.
053         *
054         * @param millis the maximum time in milliseconds to allow the
055         * test to run before it should timeout
056         */
057        @Deprecated
058        public Timeout(int millis) {
059            this(millis, TimeUnit.MILLISECONDS);
060        }
061    
062        /**
063         * Create a {@code Timeout} instance with the timeout specified
064         * at the timeUnit of granularity of the provided {@code TimeUnit}.
065         *
066         * @param timeout the maximum time to allow the test to run
067         * before it should timeout
068         * @param timeUnit the time unit for the {@code timeout}
069         * @since 4.12
070         */
071        public Timeout(long timeout, TimeUnit timeUnit) {
072            this.timeout = timeout;
073            this.timeUnit = timeUnit;
074            lookForStuckThread = false;
075        }
076    
077        /**
078         * Create a {@code Timeout} instance with the same fields as {@code t}
079         * except for {@code lookForStuckThread}.
080         *
081         * @param t the {@code Timeout} instance to copy
082         * @param lookForStuckThread whether to look for a stuck thread
083         * @since 4.12
084         */
085        protected Timeout(Timeout t, boolean lookForStuckThread) {
086            timeout = t.timeout;
087            timeUnit = t.timeUnit;
088            this.lookForStuckThread = lookForStuckThread;
089        }
090    
091        /**
092         * @param millis the timeout in milliseconds
093         * @since 4.12
094         */
095        public static Timeout millis(long millis) {
096            return new Timeout(millis, TimeUnit.MILLISECONDS);
097        }
098    
099        /**
100         * @param seconds the timeout in seconds
101         * @since 4.12
102         */
103        public static Timeout seconds(long seconds) {
104            return new Timeout(seconds, TimeUnit.SECONDS);
105        }
106    
107        /**
108         * Specifies whether to look for a stuck thread.  If a timeout occurs and this
109         * feature is enabled, the test will look for a thread that appears to be stuck
110         * and dump its backtrace.  This feature is experimental.  Behavior may change
111         * after the 4.12 release in response to feedback.
112         * @param enable {@code true} to enable the feature
113         * @return This object
114         * @since 4.12
115         */
116        public Timeout lookingForStuckThread(boolean enable) {
117            return new Timeout(this, enable);
118        }
119    
120        public Statement apply(Statement base, Description description) {
121            return new FailOnTimeout(base, timeout, timeUnit, lookForStuckThread);
122        }
123    }