1
|
1 |
package org.junit.internal.runners;
|
|
2 |
|
|
3 |
import java.lang.reflect.InvocationTargetException;
|
|
4 |
import java.lang.reflect.Method;
|
|
5 |
import java.util.concurrent.Callable;
|
|
6 |
import java.util.concurrent.ExecutorService;
|
|
7 |
import java.util.concurrent.Executors;
|
|
8 |
import java.util.concurrent.Future;
|
|
9 |
import java.util.concurrent.TimeUnit;
|
|
10 |
import java.util.concurrent.TimeoutException;
|
|
11 |
|
|
12 |
import org.junit.After;
|
|
13 |
import org.junit.Before;
|
|
14 |
import org.junit.runner.Description;
|
|
15 |
import org.junit.runner.notification.Failure;
|
|
16 |
import org.junit.runner.notification.RunNotifier;
|
|
17 |
|
|
18 |
public class TestMethodRunner extends BeforeAndAfterRunner {
|
|
19 |
private final Object fTest;
|
|
20 |
private final Method fMethod;
|
|
21 |
private final RunNotifier fNotifier;
|
|
22 |
private final TestIntrospector fTestIntrospector;
|
|
23 |
private final Description fDescription;
|
|
24 |
|
|
25 |
public TestMethodRunner(Object test, Method method, RunNotifier notifier, Description description) {
|
|
26 |
super(test.getClass(), Before.class, After.class, test);
|
|
27 |
fTest= test;
|
|
28 |
fMethod= method;
|
|
29 |
fNotifier= notifier;
|
|
30 |
fTestIntrospector= new TestIntrospector(test.getClass());
|
|
31 |
fDescription= description;
|
|
32 |
}
|
|
33 |
|
|
34 |
public void run() {
|
|
35 |
if (fTestIntrospector.isIgnored(fMethod)) {
|
|
36 |
fNotifier.fireTestIgnored(fDescription);
|
|
37 |
return;
|
|
38 |
}
|
|
39 |
fNotifier.fireTestStarted(fDescription);
|
|
40 |
try {
|
|
41 |
long timeout= fTestIntrospector.getTimeout(fMethod);
|
|
42 |
if (timeout > 0)
|
|
43 |
runWithTimeout(timeout);
|
|
44 |
else
|
|
45 |
runMethod();
|
|
46 |
} finally {
|
|
47 |
fNotifier.fireTestFinished(fDescription);
|
|
48 |
}
|
|
49 |
}
|
|
50 |
|
|
51 |
private void runWithTimeout(long timeout) {
|
|
52 |
ExecutorService service= Executors.newSingleThreadExecutor();
|
|
53 |
Callable<Object> callable= new Callable<Object>() {
|
|
54 |
public Object call() throws Exception {
|
|
55 |
runMethod();
|
|
56 |
return null;
|
|
57 |
}
|
|
58 |
};
|
|
59 |
Future<Object> result= service.submit(callable);
|
|
60 |
service.shutdown();
|
|
61 |
try {
|
|
62 |
boolean terminated= service.awaitTermination(timeout,
|
|
63 |
TimeUnit.MILLISECONDS);
|
|
64 |
if (!terminated)
|
|
65 |
service.shutdownNow();
|
|
66 |
result.get(0, TimeUnit.MILLISECONDS); // throws the exception if one occurred during the invocation
|
|
67 |
} catch (TimeoutException e) {
|
|
68 |
addFailure(new Exception(String.format("test timed out after %d milliseconds", timeout)));
|
|
69 |
} catch (Exception e) {
|
|
70 |
addFailure(e);
|
|
71 |
}
|
|
72 |
}
|
|
73 |
|
|
74 |
private void runMethod() {
|
|
75 |
runProtected();
|
|
76 |
}
|
|
77 |
|
|
78 |
@Override
|
|
79 |
protected void runUnprotected() {
|
|
80 |
try {
|
|
81 |
executeMethodBody();
|
|
82 |
if (expectsException())
|
|
83 |
addFailure(new AssertionError("Expected exception: " + expectedException().getName()));
|
|
84 |
} catch (InvocationTargetException e) {
|
|
85 |
Throwable actual= e.getTargetException();
|
|
86 |
if (!expectsException())
|
|
87 |
addFailure(actual);
|
|
88 |
else if (isUnexpected(actual)) {
|
|
89 |
String message= "Unexpected exception, expected<" + expectedException().getName() + "> but was<"
|
|
90 |
+ actual.getClass().getName() + ">";
|
|
91 |
addFailure(new Exception(message, actual));
|
|
92 |
}
|
|
93 |
} catch (Throwable e) {
|
|
94 |
addFailure(e);
|
|
95 |
}
|
|
96 |
}
|
|
97 |
|
|
98 |
protected void executeMethodBody() throws IllegalAccessException, InvocationTargetException {
|
|
99 |
fMethod.invoke(fTest);
|
|
100 |
}
|
|
101 |
|
|
102 |
@Override
|
|
103 |
protected void addFailure(Throwable e) {
|
|
104 |
fNotifier.fireTestFailure(new Failure(fDescription, e));
|
|
105 |
}
|
|
106 |
|
|
107 |
private boolean expectsException() {
|
|
108 |
return expectedException() != null;
|
|
109 |
}
|
|
110 |
|
|
111 |
private Class<? extends Throwable> expectedException() {
|
|
112 |
return fTestIntrospector.expectedException(fMethod);
|
|
113 |
}
|
|
114 |
|
|
115 |
private boolean isUnexpected(Throwable exception) {
|
|
116 |
return ! expectedException().isAssignableFrom(exception.getClass());
|
|
117 |
}
|
|
118 |
}
|
|
119 |
|