aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/junit/internal/runners/MethodRoadie.java
blob: 4407821f5a771bf6e4236646df329a7632ede513 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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));
	}
}