TestRunner.java revision 3cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91
17850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com/*
27850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Copyright (C) 2009 The Android Open Source Project
37850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com *
47850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Licensed under the Apache License, Version 2.0 (the "License");
57850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * you may not use this file except in compliance with the License.
67850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * You may obtain a copy of the License at
77850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com *
87850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com *      http://www.apache.org/licenses/LICENSE-2.0
97850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com *
107850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Unless required by applicable law or agreed to in writing, software
117850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * distributed under the License is distributed on an "AS IS" BASIS,
127850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * See the License for the specific language governing permissions and
147850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * limitations under the License.
157850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com */
167850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
177850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.compackage vogar.target;
187850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
191bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.comimport java.io.File;
207850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.IOException;
217850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.InputStream;
227850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.PrintStream;
235884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.comimport java.util.ArrayList;
24a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.comimport java.util.Arrays;
253c513c52be35990697865d1ad171378565cae1f0jsharpe@google.comimport java.util.HashSet;
265884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.comimport java.util.Iterator;
27a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.comimport java.util.List;
287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.Properties;
29a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.comimport java.util.Set;
303cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91jessewilson@google.comimport java.util.concurrent.atomic.AtomicReference;
313cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91jessewilson@google.com
32400bee347dd7464ecc17dc24c82f59c59645ff44jessewilson@google.comimport vogar.Result;
337850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport vogar.TestProperties;
34c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.comimport vogar.monitor.TargetMonitor;
357850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
367850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com/**
377850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Runs an action, in process on the target.
387850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com */
398c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.compublic final class TestRunner {
407850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
417850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    protected final Properties properties;
427850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
437850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    protected final String qualifiedName;
4472c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com    protected final String qualifiedClassOrPackageName;
45dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com
46dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com    /** the monitor port if a monitor is expected, or null for no monitor */
47dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com    protected final Integer monitorPort;
483cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91jessewilson@google.com
493cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91jessewilson@google.com    /** use an atomic reference so the runner can null it out when it is encountered. */
503cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91jessewilson@google.com    protected final AtomicReference<String> skipPastReference;
51638d42932a6aca6ddb0454674dc20b96e68faf32enh@google.com    protected final int timeoutSeconds;
52a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com    protected final List<Runner> runners;
531bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    private final boolean profile;
541bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    private final int profileDepth;
551bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    private final int profileInterval;
561bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    private final File profileFile;
571bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    private final boolean profileThreadGroup;
585884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com    protected final String[] args;
59dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com    private boolean useSocketMonitor;
607850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
61c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com    public TestRunner(List<String> argsList) {
627850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        properties = loadProperties();
637850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        qualifiedName = properties.getProperty(TestProperties.QUALIFIED_NAME);
6472c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        qualifiedClassOrPackageName = properties.getProperty(TestProperties.TEST_CLASS_OR_PACKAGE);
65638d42932a6aca6ddb0454674dc20b96e68faf32enh@google.com        timeoutSeconds = Integer.parseInt(properties.getProperty(TestProperties.TIMEOUT));
66a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com        runners = Arrays.asList(new JUnitRunner(),
673b87953e156bf57511664a32ed95bcedb8131e0ddominicc@google.com                                new JUnit4Runner(),
68a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com                                new CaliperRunner(),
69a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com                                new MainRunner());
705884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com
715884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com        int monitorPort = Integer.parseInt(properties.getProperty(TestProperties.MONITOR_PORT));
723cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com        String skipPast = null;
731bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        boolean profile = Boolean.parseBoolean(properties.getProperty(TestProperties.PROFILE));
741bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        int profileDepth = Integer.parseInt(properties.getProperty(TestProperties.PROFILE_DEPTH));
751bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        int profileInterval
761bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com                = Integer.parseInt(properties.getProperty(TestProperties.PROFILE_INTERVAL));
771bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        File profileFile = new File(properties.getProperty(TestProperties.PROFILE_FILE));
781bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        boolean profileThreadGroup
791bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com                = Boolean.parseBoolean(properties.getProperty(TestProperties.PROFILE_THREAD_GROUP));
801bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
815884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com        for (Iterator<String> i = argsList.iterator(); i.hasNext(); ) {
823cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com            String arg = i.next();
833cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com            if (arg.equals("--monitorPort")) {
845884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com                i.remove();
855884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com                monitorPort = Integer.parseInt(i.next());
865884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com                i.remove();
875884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com            }
883cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com            if (arg.equals("--skipPast")) {
893cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com                i.remove();
903cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com                skipPast = i.next();
913cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com                i.remove();
923cc430f91313dab5074cffa6508c0b47cd9f2b50jessewilson@google.com            }
935884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com        }
945884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com
955884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com        this.monitorPort = monitorPort;
963cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91jessewilson@google.com        this.skipPastReference = new AtomicReference<String>(skipPast);
971bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        this.profile = profile;
981bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        this.profileDepth = profileDepth;
991bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        this.profileInterval = profileInterval;
1001bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        this.profileFile = profileFile;
1011bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        this.profileThreadGroup = profileThreadGroup;
1025884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com        this.args = argsList.toArray(new String[argsList.size()]);
1037850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
1047850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
1058c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com    private Properties loadProperties() {
1067850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        try {
107ee67ab77cdaa11c37318aa01c22b7b1cb88c914cjessewilson@google.com            InputStream in = getPropertiesStream();
108ee67ab77cdaa11c37318aa01c22b7b1cb88c914cjessewilson@google.com            Properties properties = new Properties();
109ee67ab77cdaa11c37318aa01c22b7b1cb88c914cjessewilson@google.com            properties.load(in);
110ee67ab77cdaa11c37318aa01c22b7b1cb88c914cjessewilson@google.com            in.close();
1117850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return properties;
1127850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        } catch (IOException e) {
1137850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            throw new RuntimeException(e);
1147850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
1157850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
1167850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
117a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com    /**
118dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com     * Configure this test runner to await an incoming socket connection when
119dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com     * writing test results. Otherwise all communication happens over
120dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com     * System.out.
121dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com     */
122dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com    public void useSocketMonitor() {
123dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com        this.useSocketMonitor = true;
124dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com    }
125dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com
126dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com    /**
1278c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com     * Attempt to load the test properties file from both the application and system classloader.
1288c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com     * This is necessary because sometimes we run tests from the boot classpath.
1298c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com     */
1308c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com    private InputStream getPropertiesStream() throws IOException {
1318c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        for (Class<?> classToLoadFrom : new Class<?>[] { TestRunner.class, Object.class }) {
1328c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com            InputStream propertiesStream = classToLoadFrom.getResourceAsStream(
1338c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com                    "/" + TestProperties.FILE);
1348c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com            if (propertiesStream != null) {
1358c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com                return propertiesStream;
1368c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com            }
1378c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        }
1388c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        throw new IOException(TestProperties.FILE + " missing!");
1398c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com    }
1408c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com
1418c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com    /**
142a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com     * Returns the class to run the test with based on {@param klass}. For instance, a class
143a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com     * that extends junit.framework.TestCase should be run with JUnitSpec.
1441d4fef707a383dc57285e6608ca290be48811a85jsharpe@google.com     *
1451d4fef707a383dc57285e6608ca290be48811a85jsharpe@google.com     * Returns null if no such associated runner exists.
146a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com     */
147a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com    private Class<?> runnerClass(Class<?> klass) {
148a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com        for (Runner runner : runners) {
149a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com            if (runner.supports(klass)) {
150a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com                return runner.getClass();
1517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
1527850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
153a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com
1541d4fef707a383dc57285e6608ca290be48811a85jsharpe@google.com        return null;
1557850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
1567850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
1571bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    public void run() throws IOException {
158dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com        TargetMonitor monitor = useSocketMonitor
159dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com                ? TargetMonitor.await(monitorPort)
160dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com                : TargetMonitor.forPrintStream(System.out);
161dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com        try {
1621bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com            run(monitor);
163dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com        } finally {
164dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com            monitor.close();
165dbd85addb4e44255c4296b82d3ca45ad33a56649jessewilson@google.com        }
166c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com    }
167c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com
1681bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    public void run(final TargetMonitor monitor) {
1697850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        PrintStream monitorPrintStream = new PrintStream(System.out) {
1708a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void print(long l) {
1718a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                print(String.valueOf(l));
1728a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
1738a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
1748a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void print(int i) {
1758a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                print(String.valueOf(i));
1768a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
1778a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
1788a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void print(float f) {
1798a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                print(String.valueOf(f));
1808a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
1818a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
1828a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void print(double d) {
1838a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                print(String.valueOf(d));
1848a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
1858a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
1868a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void print(char[] s) {
1878a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                print(String.valueOf(s));
1888a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
1898a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
1908a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void print(char c) {
1918a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                print(String.valueOf(c));
1928a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
1938a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
1948a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void print(Object obj) {
1958a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                print(obj != null ? obj.toString() : "null");
1968a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
1978a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
1987850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            @Override public void print(String str) {
199c1808e2e978c6f96aacee728d39e1fc6eaad766ejessewilson@google.com                monitor.output(str != null ? str : "null");
2007850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
201127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com
202127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com            @Override public void println() {
203127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com                print("\n");
204127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com            }
205127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com
206127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com            /**
207127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com             * Although println() is documented to be equivalent to print()
208127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com             * followed by println(), this isn't the behavior on HotSpot
209127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com             * and we must manually override println(String) to ensure that
210127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com             * newlines aren't dropped.
211127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com             */
212127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com            @Override public void println(String s) {
213127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com                print(s + "\n");
214127e44af6f749f1dcc027958501c0e62f44cde5cjessewilson@google.com            }
2158a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
2168a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void println(long l) {
2178a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                println(String.valueOf(l));
2188a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
2198a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
2208a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void println(int i) {
2218a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                println(String.valueOf(i));
2228a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
2238a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
2248a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void println(float f) {
2258a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                println(String.valueOf(f));
2268a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
2278a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
2288a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void println(double d) {
2298a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                println(String.valueOf(d));
2308a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
2318a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
2328a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void println(char[] s) {
2338a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                println(String.valueOf(s));
2348a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
2358a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
2368a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void println(char c) {
2378a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                println(String.valueOf(c));
2388a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
2398a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
2408a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            @Override public void println(Object obj) {
2418a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                println(obj != null ? obj.toString() : "null");
2428a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com            }
2437850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        };
2447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        System.setOut(monitorPrintStream);
2457850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        System.setErr(monitorPrintStream);
2467850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
24784f59696573fe05a50e77832ee26c5abde46fa9ejessewilson@google.com        TestEnvironment testEnvironment = new TestEnvironment();
24884f59696573fe05a50e77832ee26c5abde46fa9ejessewilson@google.com        testEnvironment.reset();
24984f59696573fe05a50e77832ee26c5abde46fa9ejessewilson@google.com
25072c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        String classOrPackageName;
25172c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        String qualification;
25272c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com
25372c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        // Check whether the class or package is qualified and, if so, strip it off and pass it
25472c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        // separately to the runners. For instance, may qualify a junit class by appending
25572c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        // #method_name, where method_name is the name of a single test of the class to run.
25672c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        int hash_position = qualifiedClassOrPackageName.indexOf("#");
25772c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        if (hash_position != -1) {
25872c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com            classOrPackageName = qualifiedClassOrPackageName.substring(0, hash_position);
25972c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com            qualification = qualifiedClassOrPackageName.substring(hash_position + 1);
26072c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        } else {
26172c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com            classOrPackageName = qualifiedClassOrPackageName;
26272c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com            qualification = null;
26372c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        }
26472c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com
265a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com        Set<Class<?>> classes = new ClassFinder().find(classOrPackageName);
266a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com
2673c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com        // if there is more than one class in the set, this must be a package. Since we're
2683c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com        // running everything in the package already, remove any class called AllTests.
2693c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com        if (classes.size() > 1) {
2703c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com            Set<Class<?>> toRemove = new HashSet<Class<?>>();
2713c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com            for (Class<?> klass : classes) {
2723c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com                if (klass.getName().endsWith(".AllTests")) {
2733c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com                    toRemove.add(klass);
2743c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com                }
2753c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com            }
2763c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com            classes.removeAll(toRemove);
2773c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com        }
2783c513c52be35990697865d1ad171378565cae1f0jsharpe@google.com
2791bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        Profiler profiler = profile ? Profiler.getInstance() : null;
2801bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        if (profiler != null) {
2816fa1029b5a60514952d707a51253f5929628a4ecbdc@google.com            profiler.setup(profileThreadGroup, profileDepth, profileInterval);
2821bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        }
283a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com        for (Class<?> klass : classes) {
284a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com            Class<?> runnerClass = runnerClass(klass);
285a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com            if (runnerClass == null) {
286fcd851661001aec3c2c0db3a72f20c30c934ae44bjdodson@google.com                monitor.outcomeStarted(null, klass.getName(), qualifiedName);
287a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com                System.out.println("Skipping " + klass.getName()
288a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com                        + ": no associated runner class");
2891d4fef707a383dc57285e6608ca290be48811a85jsharpe@google.com                monitor.outcomeFinished(Result.UNSUPPORTED);
290a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com                continue;
291a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com            }
292a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com
293a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com            Runner runner;
294a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com            try {
295a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com                runner = (Runner) runnerClass.newInstance();
2963cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91jessewilson@google.com                runner.init(monitor, qualifiedName, qualification, klass, skipPastReference,
2973cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91jessewilson@google.com                        testEnvironment, timeoutSeconds, profile);
298a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com            } catch (Exception e) {
299a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com                monitor.outcomeStarted(null, qualifiedName, qualifiedName);
300a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com                e.printStackTrace();
301a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com                monitor.outcomeFinished(Result.ERROR);
302a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com                return;
303a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com            }
3043cea2f55f3da60eb0c4bdd1616cbfa964ee2cd91jessewilson@google.com            boolean completedNormally = runner.run(qualifiedName, profiler, args);
305a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com            if (!completedNormally) {
306a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com                return; // let the caller start another process
307a7a8fe1efa0fb3299d68709d60701a045bcc72f3jsharpe@google.com            }
3087850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
3091bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        if (profiler != null) {
3106fa1029b5a60514952d707a51253f5929628a4ecbdc@google.com            profiler.shutdown(profileFile);
3111bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        }
312a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com
313a20d57c3defdf4faad67b052e29aaa8be099cae6jessewilson@google.com        monitor.completedNormally(true);
3147850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
3157850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
316693bab6f249797311a9c4bcd4c9d9c7cfd5ae8d3jessewilson@google.com    public static void main(String[] args) throws IOException {
3171bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        new TestRunner(new ArrayList<String>(Arrays.asList(args))).run();
3187850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
3197850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com}
320