Timeout.java revision aeb93fc33cae3aadbb9b46083350ad2dc9aea645
1package org.junit.rules; 2 3import org.junit.internal.runners.statements.FailOnTimeout; 4import org.junit.runner.Description; 5import org.junit.runners.model.Statement; 6 7import 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 * @Rule 15 * public Timeout globalTimeout= new Timeout(20); 16 * 17 * @Test 18 * public void run1() throws InterruptedException { 19 * Thread.sleep(100); 20 * } 21 * 22 * @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 */ 40public class Timeout implements TestRule { 41 private final long timeout; 42 private final TimeUnit timeUnit; 43 private final boolean lookForStuckThread; 44 45 /** 46 * Returns a new builder for building an instance. 47 * 48 * @since 4.12 49 */ 50 public static Builder builder() { 51 return new Builder(); 52 } 53 54 /** 55 * Create a {@code Timeout} instance with the timeout specified 56 * in milliseconds. 57 * <p> 58 * This constructor is deprecated. 59 * <p> 60 * Instead use {@link #Timeout(long, java.util.concurrent.TimeUnit)}, 61 * {@link Timeout#millis(long)}, or {@link Timeout#seconds(long)}. 62 * 63 * @param millis the maximum time in milliseconds to allow the 64 * test to run before it should timeout 65 */ 66 @Deprecated 67 public Timeout(int millis) { 68 this(millis, TimeUnit.MILLISECONDS); 69 } 70 71 /** 72 * Create a {@code Timeout} instance with the timeout specified 73 * at the timeUnit of granularity of the provided {@code TimeUnit}. 74 * 75 * @param timeout the maximum time to allow the test to run 76 * before it should timeout 77 * @param timeUnit the time unit for the {@code timeout} 78 * @since 4.12 79 */ 80 public Timeout(long timeout, TimeUnit timeUnit) { 81 this.timeout = timeout; 82 this.timeUnit = timeUnit; 83 lookForStuckThread = false; 84 } 85 86 /** 87 * Create a {@code Timeout} instance initialized with values form 88 * a builder. 89 * 90 * @since 4.12 91 */ 92 protected Timeout(Builder builder) { 93 timeout = builder.getTimeout(); 94 timeUnit = builder.getTimeUnit(); 95 lookForStuckThread = builder.getLookingForStuckThread(); 96 } 97 98 /** 99 * Creates a {@link Timeout} that will timeout a test after the 100 * given duration, in milliseconds. 101 * 102 * @since 4.12 103 */ 104 public static Timeout millis(long millis) { 105 return new Timeout(millis, TimeUnit.MILLISECONDS); 106 } 107 108 /** 109 * Creates a {@link Timeout} that will timeout a test after the 110 * given duration, in seconds. 111 * 112 * @since 4.12 113 */ 114 public static Timeout seconds(long seconds) { 115 return new Timeout(seconds, TimeUnit.SECONDS); 116 } 117 118 /** 119 * Gets the timeout configured for this rule, in the given units. 120 * 121 * @since 4.12 122 */ 123 protected final long getTimeout(TimeUnit unit) { 124 return unit.convert(timeout, timeUnit); 125 } 126 127 /** 128 * Gets whether this {@code Timeout} will look for a stuck thread 129 * when the test times out. 130 * 131 * @since 4.12 132 */ 133 protected final boolean getLookingForStuckThread() { 134 return lookForStuckThread; 135 } 136 137 /** 138 * Creates a {@link Statement} that will run the given 139 * {@code statement}, and timeout the operation based 140 * on the values configured in this rule. Subclasses 141 * can override this method for different behavior. 142 * 143 * @since 4.12 144 */ 145 protected Statement createFailOnTimeoutStatement( 146 Statement statement) throws Exception { 147 return FailOnTimeout.builder() 148 .withTimeout(timeout, timeUnit) 149 .withLookingForStuckThread(lookForStuckThread) 150 .build(statement); 151 } 152 153 public Statement apply(Statement base, Description description) { 154 try { 155 return createFailOnTimeoutStatement(base); 156 } catch (final Exception e) { 157 return new Statement() { 158 @Override public void evaluate() throws Throwable { 159 throw new RuntimeException("Invalid parameters for Timeout", e); 160 } 161 }; 162 } 163 } 164 165 /** 166 * Builder for {@link Timeout}. 167 * 168 * @since 4.12 169 */ 170 public static class Builder { 171 private boolean lookForStuckThread = false; 172 private long timeout = 0; 173 private TimeUnit timeUnit = TimeUnit.SECONDS; 174 175 protected Builder() { 176 } 177 178 /** 179 * Specifies the time to wait before timing out the test. 180 * 181 * <p>If this is not called, or is called with a 182 * {@code timeout} of {@code 0}, the returned {@code Timeout} 183 * rule instance will cause the tests to wait forever to 184 * complete, however the tests will still launch from a 185 * separate thread. This can be useful for disabling timeouts 186 * in environments where they are dynamically set based on 187 * some property. 188 * 189 * @param timeout the maximum time to wait 190 * @param unit the time unit of the {@code timeout} argument 191 * @return {@code this} for method chaining. 192 */ 193 public Builder withTimeout(long timeout, TimeUnit unit) { 194 this.timeout = timeout; 195 this.timeUnit = unit; 196 return this; 197 } 198 199 protected long getTimeout() { 200 return timeout; 201 } 202 203 protected TimeUnit getTimeUnit() { 204 return timeUnit; 205 } 206 207 /** 208 * Specifies whether to look for a stuck thread. If a timeout occurs and this 209 * feature is enabled, the rule will look for a thread that appears to be stuck 210 * and dump its backtrace. This feature is experimental. Behavior may change 211 * after the 4.12 release in response to feedback. 212 * 213 * @param enable {@code true} to enable the feature 214 * @return {@code this} for method chaining. 215 */ 216 public Builder withLookingForStuckThread(boolean enable) { 217 this.lookForStuckThread = enable; 218 return this; 219 } 220 221 protected boolean getLookingForStuckThread() { 222 return lookForStuckThread; 223 } 224 225 226 /** 227 * Builds a {@link Timeout} instance using the values in this builder., 228 */ 229 public Timeout build() { 230 return new Timeout(this); 231 } 232 } 233} 234