• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.testing.local;
6 
7 import org.junit.runner.Computer;
8 import org.junit.runner.JUnitCore;
9 import org.junit.runner.Request;
10 import org.junit.runner.RunWith;
11 
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.Enumeration;
15 import java.util.List;
16 import java.util.jar.JarEntry;
17 import java.util.jar.JarFile;
18 import java.util.regex.Pattern;
19 
20 /**
21  *  Runs tests based on JUnit from the classpath on the host JVM based on the
22  *  provided filter configurations.
23  */
24 public final class JunitTestMain {
25     /** Enforced by {@link org.chromium.tools.errorprone.plugin.TestClassNameCheck}. */
26     private static final String TEST_CLASS_FILE_END = "Test.class";
27     private static final String CLASS_FILE_EXT = ".class";
28     private static final Pattern COLON = Pattern.compile(":");
29     private static final Pattern FORWARD_SLASH = Pattern.compile("/");
30 
JunitTestMain()31     private JunitTestMain() {
32     }
33 
34     /**
35      *  Finds all test classes on the class path annotated with RunWith.
36      */
findClassesFromClasspath()37     public static Class[] findClassesFromClasspath() {
38         String[] jarPaths = COLON.split(System.getProperty("java.class.path"));
39         List<Class> classes = new ArrayList<Class>();
40         for (String jp : jarPaths) {
41             try {
42                 JarFile jf = new JarFile(jp);
43                 for (Enumeration<JarEntry> eje = jf.entries(); eje.hasMoreElements();) {
44                     JarEntry je = eje.nextElement();
45                     String cn = je.getName();
46                     if (!cn.endsWith(TEST_CLASS_FILE_END) || cn.indexOf('$') != -1) {
47                         continue;
48                     }
49                     cn = cn.substring(0, cn.length() - CLASS_FILE_EXT.length());
50                     cn = FORWARD_SLASH.matcher(cn).replaceAll(".");
51                     Class<?> c = classOrNull(cn);
52                     if (c != null && c.isAnnotationPresent(RunWith.class)) {
53                         classes.add(c);
54                     }
55                 }
56                 jf.close();
57             } catch (IOException e) {
58                 System.err.println("Error while reading classes from " + jp);
59             }
60         }
61         return classes.toArray(new Class[0]);
62     }
63 
classOrNull(String className)64     private static Class<?> classOrNull(String className) {
65         try {
66             // Do not initialize classes (clinit) yet, Android methods are all
67             // stubs until robolectric loads the real implementations.
68             return Class.forName(
69                     className, /*initialize*/ false, JunitTestMain.class.getClassLoader());
70         } catch (ClassNotFoundException e) {
71             System.err.println("Class not found: " + className);
72         } catch (NoClassDefFoundError e) {
73             System.err.println("Class definition not found: " + className);
74         } catch (Exception e) {
75             System.err.println("Other exception while reading class: " + className);
76         }
77         return null;
78     }
79 
main(String[] args)80     public static void main(String[] args) {
81         JunitTestArgParser parser = JunitTestArgParser.parse(args);
82 
83         JUnitCore core = new JUnitCore();
84         Class[] classes = findClassesFromClasspath();
85 
86         Computer computer;
87         if (parser.isListTests()) {
88             // Causes test names to have the sdk version as a [suffix].
89             System.setProperty("robolectric.alwaysIncludeVariantMarkersInTestName", "true");
90             computer = new TestListComputer(System.out);
91         } else {
92             GtestLogger gtestLogger = new GtestLogger(System.out);
93             core.addListener(new GtestListener(gtestLogger));
94             JsonLogger jsonLogger = new JsonLogger(parser.getJsonOutputFile());
95             core.addListener(new JsonListener(jsonLogger));
96             computer = new GtestComputer(gtestLogger);
97         }
98 
99         Request testRequest = Request.classes(computer, classes);
100         for (String packageFilter : parser.getPackageFilters()) {
101             testRequest = testRequest.filterWith(new PackageFilter(packageFilter));
102         }
103         for (Class<?> runnerFilter : parser.getRunnerFilters()) {
104             testRequest = testRequest.filterWith(new RunnerFilter(runnerFilter));
105         }
106         for (String gtestFilter : parser.getGtestFilters()) {
107             testRequest = testRequest.filterWith(new GtestFilter(gtestFilter));
108         }
109         System.exit(core.run(testRequest).wasSuccessful() ? 0 : 1);
110     }
111 }
112