package org.junit.internal.runners; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.internal.AssumptionViolatedException; import org.junit.runner.Description; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; /** * @deprecated Included for backwards compatibility with JUnit 4.4. Will be * removed in the next release. Please use * {@link BlockJUnit4ClassRunner} in place of {@link JUnit4ClassRunner}. */ @Deprecated public class MethodRoadie { private final Object fTest; private final RunNotifier fNotifier; private final Description fDescription; private TestMethod fTestMethod; public MethodRoadie(Object test, TestMethod method, RunNotifier notifier, Description description) { fTest = test; fNotifier = notifier; fDescription = description; fTestMethod = method; } public void run() { if (fTestMethod.isIgnored()) { fNotifier.fireTestIgnored(fDescription); return; } fNotifier.fireTestStarted(fDescription); try { long timeout = fTestMethod.getTimeout(); if (timeout > 0) { runWithTimeout(timeout); } else { runTest(); } } finally { fNotifier.fireTestFinished(fDescription); } } private void runWithTimeout(final long timeout) { runBeforesThenTestThenAfters(new Runnable() { public void run() { ExecutorService service = Executors.newSingleThreadExecutor(); Callable<Object> callable = new Callable<Object>() { public Object call() throws Exception { runTestMethod(); return null; } }; Future<Object> result = service.submit(callable); service.shutdown(); try { boolean terminated = service.awaitTermination(timeout, TimeUnit.MILLISECONDS); if (!terminated) { service.shutdownNow(); } result.get(0, TimeUnit.MILLISECONDS); // throws the exception if one occurred during the invocation } catch (TimeoutException e) { addFailure(new Exception(String.format("test timed out after %d milliseconds", timeout))); } catch (Exception e) { addFailure(e); } } }); } public void runTest() { runBeforesThenTestThenAfters(new Runnable() { public void run() { runTestMethod(); } }); } public void runBeforesThenTestThenAfters(Runnable test) { try { runBefores(); test.run(); } catch (FailedBefore e) { } catch (Exception e) { throw new RuntimeException("test should never throw an exception to this level"); } finally { runAfters(); } } protected void runTestMethod() { try { fTestMethod.invoke(fTest); if (fTestMethod.expectsException()) { addFailure(new AssertionError("Expected exception: " + fTestMethod.getExpectedException().getName())); } } catch (InvocationTargetException e) { Throwable actual = e.getTargetException(); if (actual instanceof AssumptionViolatedException) { return; } else if (!fTestMethod.expectsException()) { addFailure(actual); } else if (fTestMethod.isUnexpected(actual)) { String message = "Unexpected exception, expected<" + fTestMethod.getExpectedException().getName() + "> but was<" + actual.getClass().getName() + ">"; addFailure(new Exception(message, actual)); } } catch (Throwable e) { addFailure(e); } } private void runBefores() throws FailedBefore { try { try { List<Method> befores = fTestMethod.getBefores(); for (Method before : befores) { before.invoke(fTest); } } catch (InvocationTargetException e) { throw e.getTargetException(); } } catch (AssumptionViolatedException e) { throw new FailedBefore(); } catch (Throwable e) { addFailure(e); throw new FailedBefore(); } } private void runAfters() { List<Method> afters = fTestMethod.getAfters(); for (Method after : afters) { try { after.invoke(fTest); } catch (InvocationTargetException e) { addFailure(e.getTargetException()); } catch (Throwable e) { addFailure(e); // Untested, but seems impossible } } } protected void addFailure(Throwable e) { fNotifier.fireTestFailure(new Failure(fDescription, e)); } }