1 package junit.runner;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.PrintWriter;
10 import java.io.StringReader;
11 import java.io.StringWriter;
12 import java.lang.reflect.InvocationTargetException;
13 import java.lang.reflect.Method;
14 import java.lang.reflect.Modifier;
15 import java.text.NumberFormat;
16 import java.util.Properties;
17
18 import junit.framework.AssertionFailedError;
19 import junit.framework.Test;
20 import junit.framework.TestListener;
21 import junit.framework.TestSuite;
22
23
24
25
26
27 public abstract class BaseTestRunner implements TestListener {
28 public static final String SUITE_METHODNAME = "suite";
29
30 private static Properties fPreferences;
31 static int fgMaxMessageLength = 500;
32 static boolean fgFilterStack = true;
33 boolean fLoading = true;
34
35
36
37
38 public synchronized void startTest(Test test) {
39 testStarted(test.toString());
40 }
41
42 protected static void setPreferences(Properties preferences) {
43 fPreferences = preferences;
44 }
45
46 protected static Properties getPreferences() {
47 if (fPreferences == null) {
48 fPreferences = new Properties();
49 fPreferences.put("loading", "true");
50 fPreferences.put("filterstack", "true");
51 readPreferences();
52 }
53 return fPreferences;
54 }
55
56 public static void savePreferences() throws IOException {
57 FileOutputStream fos = new FileOutputStream(getPreferencesFile());
58 try {
59 getPreferences().store(fos, "");
60 } finally {
61 fos.close();
62 }
63 }
64
65 public static void setPreference(String key, String value) {
66 getPreferences().put(key, value);
67 }
68
69 public synchronized void endTest(Test test) {
70 testEnded(test.toString());
71 }
72
73 public synchronized void addError(final Test test, final Throwable e) {
74 testFailed(TestRunListener.STATUS_ERROR, test, e);
75 }
76
77 public synchronized void addFailure(final Test test, final AssertionFailedError e) {
78 testFailed(TestRunListener.STATUS_FAILURE, test, e);
79 }
80
81
82
83 public abstract void testStarted(String testName);
84
85 public abstract void testEnded(String testName);
86
87 public abstract void testFailed(int status, Test test, Throwable e);
88
89
90
91
92
93 public Test getTest(String suiteClassName) {
94 if (suiteClassName.length() <= 0) {
95 clearStatus();
96 return null;
97 }
98 Class<?> testClass = null;
99 try {
100 testClass = loadSuiteClass(suiteClassName);
101 } catch (ClassNotFoundException e) {
102 String clazz = e.getMessage();
103 if (clazz == null) {
104 clazz = suiteClassName;
105 }
106 runFailed("Class not found \"" + clazz + "\"");
107 return null;
108 } catch (Exception e) {
109 runFailed("Error: " + e.toString());
110 return null;
111 }
112 Method suiteMethod = null;
113 try {
114 suiteMethod = testClass.getMethod(SUITE_METHODNAME);
115 } catch (Exception e) {
116
117 clearStatus();
118 return new TestSuite(testClass);
119 }
120 if (!Modifier.isStatic(suiteMethod.getModifiers())) {
121 runFailed("Suite() method must be static");
122 return null;
123 }
124 Test test = null;
125 try {
126 test = (Test) suiteMethod.invoke(null);
127 if (test == null) {
128 return test;
129 }
130 } catch (InvocationTargetException e) {
131 runFailed("Failed to invoke suite():" + e.getTargetException().toString());
132 return null;
133 } catch (IllegalAccessException e) {
134 runFailed("Failed to invoke suite():" + e.toString());
135 return null;
136 }
137
138 clearStatus();
139 return test;
140 }
141
142
143
144
145 public String elapsedTimeAsString(long runTime) {
146 return NumberFormat.getInstance().format((double) runTime / 1000);
147 }
148
149
150
151
152
153 protected String processArguments(String[] args) {
154 String suiteName = null;
155 for (int i = 0; i < args.length; i++) {
156 if (args[i].equals("-noloading")) {
157 setLoading(false);
158 } else if (args[i].equals("-nofilterstack")) {
159 fgFilterStack = false;
160 } else if (args[i].equals("-c")) {
161 if (args.length > i + 1) {
162 suiteName = extractClassName(args[i + 1]);
163 } else {
164 System.out.println("Missing Test class name");
165 }
166 i++;
167 } else {
168 suiteName = args[i];
169 }
170 }
171 return suiteName;
172 }
173
174
175
176
177 public void setLoading(boolean enable) {
178 fLoading = enable;
179 }
180
181
182
183
184 public String extractClassName(String className) {
185 if (className.startsWith("Default package for")) {
186 return className.substring(className.lastIndexOf(".") + 1);
187 }
188 return className;
189 }
190
191
192
193
194 public static String truncate(String s) {
195 if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength) {
196 s = s.substring(0, fgMaxMessageLength) + "...";
197 }
198 return s;
199 }
200
201
202
203
204
205 protected abstract void runFailed(String message);
206
207
208
209
210 protected Class<?> loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
211 return Class.forName(suiteClassName);
212 }
213
214
215
216
217 protected void clearStatus() {
218 }
219
220 protected boolean useReloadingTestSuiteLoader() {
221 return getPreference("loading").equals("true") && fLoading;
222 }
223
224 private static File getPreferencesFile() {
225 String home = System.getProperty("user.home");
226 return new File(home, "junit.properties");
227 }
228
229 private static void readPreferences() {
230 InputStream is = null;
231 try {
232 is = new FileInputStream(getPreferencesFile());
233 setPreferences(new Properties(getPreferences()));
234 getPreferences().load(is);
235 } catch (IOException ignored) {
236 } finally {
237 try {
238 if (is != null) {
239 is.close();
240 }
241 } catch (IOException e1) {
242 }
243 }
244 }
245
246 public static String getPreference(String key) {
247 return getPreferences().getProperty(key);
248 }
249
250 public static int getPreference(String key, int dflt) {
251 String value = getPreference(key);
252 int intValue = dflt;
253 if (value == null) {
254 return intValue;
255 }
256 try {
257 intValue = Integer.parseInt(value);
258 } catch (NumberFormatException ne) {
259 }
260 return intValue;
261 }
262
263
264
265
266 public static String getFilteredTrace(Throwable e) {
267 StringWriter stringWriter = new StringWriter();
268 PrintWriter writer = new PrintWriter(stringWriter);
269 e.printStackTrace(writer);
270 String trace = stringWriter.toString();
271 return BaseTestRunner.getFilteredTrace(trace);
272 }
273
274
275
276
277 public static String getFilteredTrace(String stack) {
278 if (showStackRaw()) {
279 return stack;
280 }
281
282 StringWriter sw = new StringWriter();
283 PrintWriter pw = new PrintWriter(sw);
284 StringReader sr = new StringReader(stack);
285 BufferedReader br = new BufferedReader(sr);
286
287 String line;
288 try {
289 while ((line = br.readLine()) != null) {
290 if (!filterLine(line)) {
291 pw.println(line);
292 }
293 }
294 } catch (Exception IOException) {
295 return stack;
296 }
297 return sw.toString();
298 }
299
300 protected static boolean showStackRaw() {
301 return !getPreference("filterstack").equals("true") || fgFilterStack == false;
302 }
303
304 static boolean filterLine(String line) {
305 String[] patterns = new String[]{
306 "junit.framework.TestCase",
307 "junit.framework.TestResult",
308 "junit.framework.TestSuite",
309 "junit.framework.Assert.",
310 "junit.swingui.TestRunner",
311 "junit.awtui.TestRunner",
312 "junit.textui.TestRunner",
313 "java.lang.reflect.Method.invoke("
314 };
315 for (int i = 0; i < patterns.length; i++) {
316 if (line.indexOf(patterns[i]) > 0) {
317 return true;
318 }
319 }
320 return false;
321 }
322
323 static {
324 fgMaxMessageLength = getPreference("maxmessage", fgMaxMessageLength);
325 }
326
327 }