• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Base class for all test runners.
25  * This class was born live on stage in Sardinia during XP2000.
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     * Implementation of TestListener
37     */
startTest(Test test)38 	public synchronized void startTest(Test test) {
39 		testStarted(test.toString());
40 	}
41 
setPreferences(Properties preferences)42 	protected static void setPreferences(Properties preferences) {
43 		fPreferences= preferences;
44 	}
45 
getPreferences()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 
savePreferences()56 	public static void savePreferences() throws IOException {
57 		FileOutputStream fos= new FileOutputStream(getPreferencesFile());
58 		try {
59 			// calling of the deprecated save method to enable compiling under 1.1.7
60 			getPreferences().save(fos, "");
61 		} finally {
62 			fos.close();
63 		}
64 	}
65 
setPreference(String key, String value)66 	public static void setPreference(String key, String value) {
67 		getPreferences().put(key, value);
68 	}
69 
endTest(Test test)70 	public synchronized void endTest(Test test) {
71 		testEnded(test.toString());
72 	}
73 
addError(final Test test, final Throwable t)74 	public synchronized void addError(final Test test, final Throwable t) {
75 		testFailed(TestRunListener.STATUS_ERROR, test, t);
76 	}
77 
addFailure(final Test test, final AssertionFailedError t)78 	public synchronized void addFailure(final Test test, final AssertionFailedError t) {
79 		testFailed(TestRunListener.STATUS_FAILURE, test, t);
80 	}
81 
82 	// TestRunListener implementation
83 
testStarted(String testName)84 	public abstract void testStarted(String testName);
85 
testEnded(String testName)86 	public abstract void testEnded(String testName);
87 
testFailed(int status, Test test, Throwable t)88 	public abstract void testFailed(int status, Test test, Throwable t);
89 
90 	/**
91 	 * Returns the Test corresponding to the given suite. This is
92 	 * a template method, subclasses override runFailed(), clearStatus().
93 	 */
getTest(String suiteClassName)94 	public Test getTest(String suiteClassName) {
95 		if (suiteClassName.length() <= 0) {
96 			clearStatus();
97 			return null;
98 		}
99 		Class testClass= null;
100 		try {
101 			testClass= loadSuiteClass(suiteClassName);
102 		} catch (ClassNotFoundException e) {
103 			String clazz= e.getMessage();
104 			if (clazz == null)
105 				clazz= suiteClassName;
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, new Class[0]);
115 	 	} catch(Exception e) {
116 	 		// try to extract a test suite automatically
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, (Object[])new Class[0]); // static method
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 		}
134 		catch (IllegalAccessException e) {
135 			runFailed("Failed to invoke suite():" + e.toString());
136 			return null;
137 		}
138 
139 		clearStatus();
140 		return test;
141 	}
142 
143 	/**
144 	 * Returns the formatted string of the elapsed time.
145 	 */
elapsedTimeAsString(long runTime)146 	public String elapsedTimeAsString(long runTime) {
147 		return NumberFormat.getInstance().format((double)runTime/1000);
148 	}
149 
150 	/**
151 	 * Processes the command line arguments and
152 	 * returns the name of the suite class to run or null
153 	 */
processArguments(String[] args)154 	protected String processArguments(String[] args) {
155 		String suiteName= null;
156 		for (int i= 0; i < args.length; i++) {
157 			if (args[i].equals("-noloading")) {
158 				setLoading(false);
159 			} else if (args[i].equals("-nofilterstack")) {
160 				fgFilterStack= false;
161 			} else if (args[i].equals("-c")) {
162 				if (args.length > i+1)
163 					suiteName= extractClassName(args[i+1]);
164 				else
165 					System.out.println("Missing Test class name");
166 				i++;
167 			} else {
168 				suiteName= args[i];
169 			}
170 		}
171 		return suiteName;
172 	}
173 
174 	/**
175 	 * Sets the loading behaviour of the test runner
176 	 */
setLoading(boolean enable)177 	public void setLoading(boolean enable) {
178 		fLoading= enable;
179 	}
180 	/**
181 	 * Extract the class name from a String in VA/Java style
182 	 */
extractClassName(String className)183 	public String extractClassName(String className) {
184 		if(className.startsWith("Default package for"))
185 			return className.substring(className.lastIndexOf(".")+1);
186 		return className;
187 	}
188 
189 	/**
190 	 * Truncates a String to the maximum length.
191 	 */
truncate(String s)192 	public static String truncate(String s) {
193 		if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength)
194 			s= s.substring(0, fgMaxMessageLength)+"...";
195 		return s;
196 	}
197 
198 	/**
199 	 * Override to define how to handle a failed loading of
200 	 * a test suite.
201 	 */
runFailed(String message)202 	protected abstract void runFailed(String message);
203 
204 	/**
205 	 * Returns the loaded Class for a suite name.
206 	 */
loadSuiteClass(String suiteClassName)207 	protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
208 		return getLoader().load(suiteClassName);
209 	}
210 
211 	/**
212 	 * Clears the status message.
213 	 */
clearStatus()214 	protected void clearStatus() { // Belongs in the GUI TestRunner class
215 	}
216 
217 	/**
218 	 * Returns the loader to be used.
219 	 */
getLoader()220 	public TestSuiteLoader getLoader() {
221 		if (useReloadingTestSuiteLoader())
222 			return new ReloadingTestSuiteLoader();
223 		return new StandardTestSuiteLoader();
224 	}
225 
useReloadingTestSuiteLoader()226 	protected boolean useReloadingTestSuiteLoader() {
227 		return getPreference("loading").equals("true") && !inVAJava() && fLoading;
228 	}
229 
getPreferencesFile()230 	private static File getPreferencesFile() {
231 	 	String home= System.getProperty("user.home");
232  		return new File(home, "junit.properties");
233  	}
234 
readPreferences()235  	private static void readPreferences() {
236  		InputStream is= null;
237  		try {
238  			is= new FileInputStream(getPreferencesFile());
239  			setPreferences(new Properties(getPreferences()));
240 			getPreferences().load(is);
241 		} catch (IOException e) {
242 			try {
243 				if (is != null)
244 					is.close();
245 			} catch (IOException e1) {
246 			}
247 		}
248  	}
249 
getPreference(String key)250  	public static String getPreference(String key) {
251  		return getPreferences().getProperty(key);
252  	}
253 
getPreference(String key, int dflt)254  	public static int getPreference(String key, int dflt) {
255  		String value= getPreference(key);
256  		int intValue= dflt;
257  		if (value == null)
258  			return intValue;
259  		try {
260  			intValue= Integer.parseInt(value);
261  	 	} catch (NumberFormatException ne) {
262  		}
263  		return intValue;
264  	}
265 
inVAJava()266  	public static boolean inVAJava() {
267 		try {
268 			Class.forName("com.ibm.uvm.tools.DebugSupport");
269 		}
270 		catch (Exception e) {
271 			return false;
272 		}
273 		return true;
274 	}
275 
inMac()276 	public static boolean inMac() {
277 		return System.getProperty("mrj.version") != null;
278 	}
279 
280 
281 	/**
282 	 * Returns a filtered stack trace
283 	 */
getFilteredTrace(Throwable t)284 	public static String getFilteredTrace(Throwable t) {
285 		StringWriter stringWriter= new StringWriter();
286 		PrintWriter writer= new PrintWriter(stringWriter);
287 		t.printStackTrace(writer);
288 		StringBuffer buffer= stringWriter.getBuffer();
289 		String trace= buffer.toString();
290 		return BaseTestRunner.getFilteredTrace(trace);
291 	}
292 
293 	/**
294 	 * Filters stack frames from internal JUnit classes
295 	 */
getFilteredTrace(String stack)296 	public static String getFilteredTrace(String stack) {
297 		if (showStackRaw())
298 			return stack;
299 
300 		StringWriter sw= new StringWriter();
301 		PrintWriter pw= new PrintWriter(sw);
302 		StringReader sr= new StringReader(stack);
303 		BufferedReader br= new BufferedReader(sr);
304 
305 		String line;
306 		try {
307 			while ((line= br.readLine()) != null) {
308 				if (!filterLine(line))
309 					pw.println(line);
310 			}
311 		} catch (Exception IOException) {
312 			return stack; // return the stack unfiltered
313 		}
314 		return sw.toString();
315 	}
316 
showStackRaw()317 	protected static boolean showStackRaw() {
318 		return !getPreference("filterstack").equals("true") || fgFilterStack == false;
319 	}
320 
filterLine(String line)321 	static boolean filterLine(String line) {
322 		String[] patterns= new String[] {
323 			"junit.framework.TestCase",
324 			"junit.framework.TestResult",
325 			"junit.framework.TestSuite",
326 			"junit.framework.Assert.", // don't filter AssertionFailure
327 			"junit.swingui.TestRunner",
328 			"junit.awtui.TestRunner",
329 			"junit.textui.TestRunner",
330 			"java.lang.reflect.Method.invoke("
331 		};
332 		for (int i= 0; i < patterns.length; i++) {
333 			if (line.indexOf(patterns[i]) > 0)
334 				return true;
335 		}
336 		return false;
337 	}
338 
339  	static {
340  		fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength);
341  	}
342 
343 }
344