1/** 2 * 3 */ 4package org.junit.internal.runners.statements; 5 6import org.junit.runners.model.Statement; 7 8public class FailOnTimeout extends Statement { 9 private final Statement fOriginalStatement; 10 11 private final long fTimeout; 12 13 public FailOnTimeout(Statement originalStatement, long timeout) { 14 fOriginalStatement= originalStatement; 15 fTimeout= timeout; 16 } 17 18 @Override 19 public void evaluate() throws Throwable { 20 StatementThread thread= evaluateStatement(); 21 if (!thread.fFinished) 22 throwExceptionForUnfinishedThread(thread); 23 } 24 25 private StatementThread evaluateStatement() throws InterruptedException { 26 StatementThread thread= new StatementThread(fOriginalStatement); 27 thread.start(); 28 thread.join(fTimeout); 29 thread.interrupt(); 30 return thread; 31 } 32 33 private void throwExceptionForUnfinishedThread(StatementThread thread) 34 throws Throwable { 35 if (thread.fExceptionThrownByOriginalStatement != null) 36 throw thread.fExceptionThrownByOriginalStatement; 37 else 38 throwTimeoutException(thread); 39 } 40 41 private void throwTimeoutException(StatementThread thread) throws Exception { 42 Exception exception= new Exception(String.format( 43 "test timed out after %d milliseconds", fTimeout)); 44 exception.setStackTrace(thread.getStackTrace()); 45 throw exception; 46 } 47 48 private static class StatementThread extends Thread { 49 private final Statement fStatement; 50 51 private boolean fFinished= false; 52 53 private Throwable fExceptionThrownByOriginalStatement= null; 54 55 public StatementThread(Statement statement) { 56 fStatement= statement; 57 } 58 59 @Override 60 public void run() { 61 try { 62 fStatement.evaluate(); 63 fFinished= true; 64 } catch (InterruptedException e) { 65 //don't log the InterruptedException 66 } catch (Throwable e) { 67 fExceptionThrownByOriginalStatement= e; 68 } 69 } 70 } 71}