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