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 * @Rule 015 * public Timeout globalTimeout= new Timeout(20); 016 * 017 * @Test 018 * public void run1() throws InterruptedException { 019 * Thread.sleep(100); 020 * } 021 * 022 * @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 }