1 package org.junit.tests.running.methods;
2
3 import static org.hamcrest.CoreMatchers.containsString;
4 import static org.hamcrest.CoreMatchers.not;
5 import static org.hamcrest.CoreMatchers.is;
6 import static org.junit.Assert.assertEquals;
7 import static org.junit.Assert.assertThat;
8 import static org.junit.Assert.assertTrue;
9 import static org.junit.Assert.fail;
10
11 import java.io.PrintWriter;
12 import java.io.StringWriter;
13 import java.io.Writer;
14 import java.util.concurrent.TimeUnit;
15
16 import junit.framework.JUnit4TestAdapter;
17 import junit.framework.TestResult;
18 import org.junit.After;
19 import org.junit.Ignore;
20 import org.junit.Rule;
21 import org.junit.Test;
22 import org.junit.rules.TestRule;
23 import org.junit.rules.Timeout;
24 import org.junit.runner.JUnitCore;
25 import org.junit.runner.Result;
26
27 public class TimeoutTest {
28
29 public static class FailureWithTimeoutTest {
30 @Test(timeout = 1000)
31 public void failure() {
32 fail();
33 }
34 }
35
36 @Test
37 public void failureWithTimeout() throws Exception {
38 JUnitCore core = new JUnitCore();
39 Result result = core.run(FailureWithTimeoutTest.class);
40 assertEquals(1, result.getRunCount());
41 assertEquals(1, result.getFailureCount());
42 assertEquals(AssertionError.class, result.getFailures().get(0).getException().getClass());
43 }
44
45 public static class FailureWithTimeoutRunTimeExceptionTest {
46 @Test(timeout = 1000)
47 public void failure() {
48 throw new NullPointerException();
49 }
50 }
51
52 @Test
53 public void failureWithTimeoutRunTimeException() throws Exception {
54 JUnitCore core = new JUnitCore();
55 Result result = core.run(FailureWithTimeoutRunTimeExceptionTest.class);
56 assertEquals(1, result.getRunCount());
57 assertEquals(1, result.getFailureCount());
58 assertEquals(NullPointerException.class, result.getFailures().get(0).getException().getClass());
59 }
60
61 public static class SuccessWithTimeoutTest {
62 @Test(timeout = 1000)
63 public void success() {
64 }
65 }
66
67 @Test
68 public void successWithTimeout() throws Exception {
69 JUnitCore core = new JUnitCore();
70 Result result = core.run(SuccessWithTimeoutTest.class);
71 assertEquals(1, result.getRunCount());
72 assertEquals(0, result.getFailureCount());
73 }
74
75 public static class TimeoutFailureTest {
76 @Test(timeout = 100)
77 public void success() throws InterruptedException {
78 Thread.sleep(40000);
79 }
80 }
81
82 @Ignore("was breaking gump")
83 @Test
84 public void timeoutFailure() throws Exception {
85 JUnitCore core = new JUnitCore();
86 Result result = core.run(TimeoutFailureTest.class);
87 assertEquals(1, result.getRunCount());
88 assertEquals(1, result.getFailureCount());
89 assertEquals(InterruptedException.class, result.getFailures().get(0).getException().getClass());
90 }
91
92 public static class InfiniteLoopTest {
93 @Test(timeout = 100)
94 public void failure() {
95 infiniteLoop();
96 }
97
98 private void infiniteLoop() {
99 for (; ; ) {
100 try {
101 Thread.sleep(10);
102 } catch (InterruptedException e) {
103 }
104 }
105 }
106 }
107
108 @Test
109 public void infiniteLoop() throws Exception {
110 JUnitCore core = new JUnitCore();
111 Result result = core.run(InfiniteLoopTest.class);
112 assertEquals(1, result.getRunCount());
113 assertEquals(1, result.getFailureCount());
114 Throwable exception = result.getFailures().get(0).getException();
115 assertTrue(exception.getMessage().contains("test timed out after 100 milliseconds"));
116 }
117
118 public static class ImpatientLoopTest {
119 @Test(timeout = 1)
120 public void failure() {
121 infiniteLoop();
122 }
123
124 private void infiniteLoop() {
125 for (; ; ) ;
126 }
127 }
128
129 @Ignore("This breaks sporadically with time differences just slightly more than 200ms")
130 @Test
131 public void infiniteLoopRunsForApproximatelyLengthOfTimeout() throws Exception {
132
133
134 JUnitCore.runClasses(InfiniteLoopTest.class, ImpatientLoopTest.class);
135 long longTime = runAndTime(InfiniteLoopTest.class);
136 long shortTime = runAndTime(ImpatientLoopTest.class);
137 long difference = longTime - shortTime;
138 assertTrue(String.format("Difference was %sms", difference), difference < 200);
139 }
140
141 private long runAndTime(Class<?> clazz) {
142 JUnitCore core = new JUnitCore();
143 long startTime = System.currentTimeMillis();
144 core.run(clazz);
145 long totalTime = System.currentTimeMillis() - startTime;
146 return totalTime;
147 }
148
149 private String stackForException(Throwable exception) {
150 Writer buffer = new StringWriter();
151 PrintWriter writer = new PrintWriter(buffer);
152 exception.printStackTrace(writer);
153 return buffer.toString();
154 }
155
156 @Test
157 public void stalledThreadAppearsInStackTrace() throws Exception {
158 JUnitCore core = new JUnitCore();
159 Result result = core.run(InfiniteLoopTest.class);
160 assertEquals(1, result.getRunCount());
161 assertEquals(1, result.getFailureCount());
162 Throwable exception = result.getFailures().get(0).getException();
163 assertThat(stackForException(exception), containsString("infiniteLoop"));
164 }
165
166 public static class InfiniteLoopMultithreaded {
167
168 private static class ThreadTest implements Runnable {
169 private boolean fStall;
170
171 public ThreadTest(boolean stall) {
172 fStall = stall;
173 }
174
175 public void run() {
176 if (fStall)
177 for (; ; ) ;
178 try {
179 Thread.sleep(500);
180 } catch (InterruptedException e) {
181 }
182 }
183 }
184
185 public void failure(boolean mainThreadStalls) throws Exception {
186 Thread t1 = new Thread(new ThreadTest(false), "timeout-thr1");
187 Thread t2 = new Thread(new ThreadTest(!mainThreadStalls), "timeout-thr2");
188 Thread t3 = new Thread(new ThreadTest(false), "timeout-thr3");
189 t1.start();
190 t2.start();
191 t3.start();
192 if (mainThreadStalls)
193 for (; ; ) ;
194 t1.join();
195 t2.join();
196 t3.join();
197 }
198 }
199
200 public static class InfiniteLoopWithStuckThreadTest {
201 @Rule
202 public TestRule globalTimeout = Timeout.builder()
203 .withTimeout(100, TimeUnit.MILLISECONDS)
204 .withLookingForStuckThread(true)
205 .build();
206
207 @Test
208 public void failure() throws Exception {
209 (new InfiniteLoopMultithreaded()).failure(false);
210 }
211 }
212
213 public static class InfiniteLoopStuckInMainThreadTest {
214 @Rule
215 public TestRule globalTimeout = Timeout.builder()
216 .withTimeout(100, TimeUnit.MILLISECONDS)
217 .withLookingForStuckThread(true)
218 .build();
219
220 @Test
221 public void failure() throws Exception {
222 (new InfiniteLoopMultithreaded()).failure(true);
223 }
224 }
225
226 @Test
227 public void timeoutFailureMultithreaded() throws Exception {
228 JUnitCore core = new JUnitCore();
229 Result result = core.run(InfiniteLoopWithStuckThreadTest.class);
230 assertEquals(1, result.getRunCount());
231 assertEquals(2, result.getFailureCount());
232 Throwable exception[] = new Throwable[2];
233 for (int i = 0; i < 2; i++)
234 exception[i] = result.getFailures().get(i).getException();
235 assertThat(exception[0].getMessage(), containsString("test timed out after 100 milliseconds"));
236 assertThat(stackForException(exception[0]), containsString("Thread.join"));
237 assertThat(exception[1].getMessage(), containsString("Appears to be stuck in thread timeout-thr2"));
238 }
239
240 @Test
241 public void timeoutFailureMultithreadedStuckInMain() throws Exception {
242 JUnitCore core = new JUnitCore();
243 Result result = core.run(InfiniteLoopStuckInMainThreadTest.class);
244 assertEquals(1, result.getRunCount());
245 assertEquals(1, result.getFailureCount());
246 Throwable exception = result.getFailures().get(0).getException();
247 assertThat(exception.getMessage(), containsString("test timed out after 100 milliseconds"));
248 assertThat(exception.getMessage(), not(containsString("Appears to be stuck")));
249 }
250
251 @Test
252 public void compatibility() {
253 TestResult result = new TestResult();
254 new JUnit4TestAdapter(InfiniteLoopTest.class).run(result);
255 assertEquals(1, result.errorCount());
256 }
257
258 public static class WillTimeOut {
259 static boolean afterWasCalled = false;
260
261 @Test(timeout = 1)
262 public void test() {
263 for (; ; ) {
264 try {
265 Thread.sleep(10000);
266 } catch (InterruptedException e) {
267
268 }
269 }
270 }
271
272 @After
273 public void after() {
274 afterWasCalled = true;
275 }
276 }
277
278 @Test
279 public void makeSureAfterIsCalledAfterATimeout() {
280 JUnitCore.runClasses(WillTimeOut.class);
281 assertThat(WillTimeOut.afterWasCalled, is(true));
282 }
283
284 public static class TimeOutZero {
285 @Rule
286 public Timeout timeout = Timeout.seconds(0);
287
288 @Test
289 public void test() {
290 try {
291 Thread.sleep(200);
292 } catch (InterruptedException e) {
293
294 }
295 }
296 }
297
298 @Test
299 public void testZeroTimeoutIsIgnored() {
300 JUnitCore core = new JUnitCore();
301 Result result = core.run(TimeOutZero.class);
302 assertEquals("Should run the test", 1, result.getRunCount());
303 assertEquals("Test should not have failed", 0, result.getFailureCount());
304 }
305
306 private static class TimeoutSubclass extends Timeout {
307
308 public TimeoutSubclass(long timeout, TimeUnit timeUnit) {
309 super(timeout, timeUnit);
310 }
311
312 public long getTimeoutFromSuperclass(TimeUnit unit) {
313 return super.getTimeout(unit);
314 }
315 }
316
317 public static class TimeOutOneSecond {
318 @Rule
319 public TimeoutSubclass timeout = new TimeoutSubclass(1, TimeUnit.SECONDS);
320
321 @Test
322 public void test() {
323 assertEquals(1000, timeout.getTimeoutFromSuperclass(TimeUnit.MILLISECONDS));
324 }
325 }
326
327 @Test
328 public void testGetTimeout() {
329 JUnitCore core = new JUnitCore();
330 Result result = core.run(TimeOutOneSecond.class);
331 assertEquals("Should run the test", 1, result.getRunCount());
332 assertEquals("Test should not have failed", 0, result.getFailureCount());
333 }
334 }