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