View Javadoc
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         // "prime the pump": running these beforehand makes the runtimes more predictable
133         //                   (because of class loading?)
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")); // Make sure we have the stalled frame on the stack somewhere
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                     // ok, tests are over
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); // long enough to suspend thread execution
292             } catch (InterruptedException e) {
293                 // Don't care
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 }