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 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