Vogar.java revision 8a9cc00a0d2c02483690de28eabe2b60b5804538
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;
187850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
19d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.comimport com.google.common.collect.Lists;
207850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.File;
214cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.comimport java.io.FileNotFoundException;
227850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.IOException;
237850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.ArrayList;
24d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.comimport java.util.Date;
257850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.LinkedHashSet;
267850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.List;
277850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.Set;
287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.UUID;
29969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.ActivityMode;
30969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.AndroidSdk;
31969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.DeviceDalvikVm;
32969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.DeviceFileCache;
33969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.EnvironmentDevice;
34969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.HostDalvikVm;
35d59b17f5dc87d856a01714853d5296d387ff8dedjessewilson@google.comimport vogar.util.Strings;
367850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
377850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com/**
387850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Command line interface for running benchmarks and tests on dalvik.
397850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com */
407850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.compublic final class Vogar {
417850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
428c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com    private static final int LARGE_TIMEOUT_MULTIPLIER = 10;
43126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com    private static final int NUM_PROCESSORS = Runtime.getRuntime().availableProcessors();
448c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com
45d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<File> actionFiles = new ArrayList<File>();
46d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<String> actionClassesAndPackages = new ArrayList<String>();
47d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<String> targetArgs = new ArrayList<String>();
48fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com    private final OptionParser optionParser = new OptionParser(this);
4925d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com    private File configFile = Vogar.dotFile(".vogarconfig");
5025d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com
51969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.com    public static File dotFile (String name) {
5225d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com        return new File(System.getProperty("user.home", "."), name);
5325d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com    }
5425d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com
55d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
56d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--expectations" })
57d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Set<File> expectationFiles = new LinkedHashSet<File>();
58d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    {
599f9a3ba8e244912c50140ba15ec583a8098dca41enh@google.com        expectationFiles.addAll(AndroidSdk.defaultExpectations());
60d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
617850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
62d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--mode" })
63d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private ModeId mode = ModeId.DEVICE;
647850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
65d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--timeout" })
66d296ba8af13d367b4a701ddeba405ee51caa05c1enh@google.com    private int timeoutSeconds = 1 * 60; // default is one minute;
677850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
68d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--monitor-timeout" })
695884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com    private int monitorTimeout = 30;
707850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
71126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com    @Option(names = { "--first-monitor-port" })
72126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com    private int firstMonitorPort = -1;
73126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com
74d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--clean-before" })
75d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean cleanBefore = true;
767850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
77d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--clean-after" })
78d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean cleanAfter = true;
797850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
80d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--clean" })
81d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean clean = true;
827850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
83d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--xml-reports-directory" })
84d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private File xmlReportsDirectory;
857850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
86d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--indent" })
87d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private String indent = "  ";
887850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
89d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--verbose" })
90d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean verbose;
917850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
92d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--stream" })
93d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean stream = true;
947850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
95d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--color" })
96d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean color = true;
977850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
9850bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    @Option(names = { "--pass-color" })
9950bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    private int passColor = 32; // green
10050bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com
10150bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    @Option(names = { "--warn-color" })
10250bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    private int warnColor = 33; // yellow
10350bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com
10450bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    @Option(names = { "--fail-color" })
10550bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    private int failColor = 31; // red
10650bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com
107d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--debug" })
108d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Integer debugPort;
109d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
1103d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com    @Option(names = { "--device-dir" })
1113d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com    private File deviceDir = new File("/sdcard/vogar");
112d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
113d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--vm-arg" })
114d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<String> vmArgs = new ArrayList<String>();
115d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
116d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--java-home" })
117d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private File javaHome;
118d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
119d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--javac-arg" })
120d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<String> javacArgs = new ArrayList<String>();
121d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
12282131e6aba37e8b6f8ebbadbbe57fb5a78b4f743jessewilson@google.com    @Option(names = { "--use-bootclasspath" })
123d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean useBootClasspath = false;
124d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
125d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--build-classpath" })
126d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<File> buildClasspath = new ArrayList<File>();
127d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
128d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--classpath", "-cp" })
129d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<File> classpath = new ArrayList<File>();
130d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
131d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--sourcepath" })
132d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<File> sourcepath = new ArrayList<File>();
133dd2774574cb456b48b8ec2aafbf0e6583f4faa41enh@google.com    {
134dd2774574cb456b48b8ec2aafbf0e6583f4faa41enh@google.com        sourcepath.addAll(AndroidSdk.defaultSourcePath());
135dd2774574cb456b48b8ec2aafbf0e6583f4faa41enh@google.com    }
136d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
13741a680807eb80e63fbfe42c218c9e1da6615d867jsharpe@google.com    @Option(names = { "--device-cache" })
1382c67cf17be7262353493480d98fb88ad0f8fc320jsharpe@google.com    private boolean deviceCache = true;
13941a680807eb80e63fbfe42c218c9e1da6615d867jsharpe@google.com
140d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--jar-search-dir" })
141d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    private List<File> jarSearchDirs = Lists.newArrayList();
142d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
143d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--vogar-dir" })
1444ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com    private File vogarDir = Vogar.dotFile(".vogar");
1454cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
1468918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com    @Option(names = { "--tag-dir" })
1478918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com    private File tagDir = null;
1488918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com
14900d4ce596c71916d975f6c8d967af53ab0a8f453jsharpe@google.com    @Option(names = { "--tag" }, savedInTag = false)
1504cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private String tagName = null;
1514cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
15200d4ce596c71916d975f6c8d967af53ab0a8f453jsharpe@google.com    @Option(names = { "--run-tag" }, savedInTag = false)
1534cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private String runTag = null;
1544cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
155d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--compare-to-tag" }, savedInTag = false)
156d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    private String compareToTag = null;
157d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
15800d4ce596c71916d975f6c8d967af53ab0a8f453jsharpe@google.com    @Option(names = { "--tag-overwrite" }, savedInTag = false)
1594cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private boolean tagOverwrite = false;
1604cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
161d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--record-results" })
162d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    private boolean recordResults = false;
163d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
164d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--results-dir" })
165d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    private File resultsDir = null;
166d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
1673dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com    @Option(names = { "--suggest-classpaths" })
1683dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com    private boolean suggestClasspaths = false;
1693dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com
1705bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com    @Option(names = { "--valgrind" })
1715bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com    private boolean valgrind = false;
1725bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com
1738a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com    @Option(names = { "--native-output" })
1748a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com    private boolean nativeOutput = false;
1758a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com
176d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Vogar() {}
177d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
178d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private void printUsage() {
179fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com        // have to reset fields so that "Default is: FOO" lines are accurate
180fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com        optionParser.reset();
181fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com
182d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("Usage: Vogar [options]... <actions>... [-- target args]...");
183d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
184d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  <actions>: .java files, directories, or class names.");
185d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      These should be JUnit tests, jtreg tests, Caliper benchmarks");
186d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      or executable Java classes.");
187d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
18872c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        System.out.println("      When passing in a JUnit test class, it may have \"#method_name\"");
18972c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        System.out.println("      appended to it, to specify a single test method.");
19072c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        System.out.println();
191d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  [args]: arguments passed to the target process. This is only useful when");
192d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      the target process is a Caliper benchmark or main method.");
193d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
194d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("GENERAL OPTIONS");
195d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
19679e4231584a3b24b44f42224475d41fcbe957af4jessewilson@google.com        System.out.println("  --mode <activity|device|sim|jvm>: specify which environment to run in.");
197d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      activity: runs in an Android application on a device or emulator");
198d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      device: runs in a Dalvik VM on a device or emulator");
199d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      sim: runs in a Dalvik VM on the local desktop.");
20079e4231584a3b24b44f42224475d41fcbe957af4jessewilson@google.com        System.out.println("      jvm: runs in a Java VM on the local desktop");
201d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + mode);
202d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
203d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean: synonym for --clean-before and --clean-after (default).");
204d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Disable with --no-clean if you want no files removed.");
205d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
206d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --stream: stream output as it is emitted.");
207d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
2088a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com        System.out.println("  --native-output: print out native output (prefixed with \"[native]\").");
2098a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com        System.out.println();
2105bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com        System.out.println("  --valgrind: run the VM under valgrind (not supported for all VMs).");
2115bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com        System.out.println();
212d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --timeout <seconds>: maximum execution time of each action before the");
213d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      runner aborts it. Specifying zero seconds or using --debug will");
2148c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        System.out.println("      disable the execution timeout. Tests tagged with 'large' will time");
2158c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        System.out.println("      out in " + LARGE_TIMEOUT_MULTIPLIER + "x this timeout.");
216d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + timeoutSeconds);
217d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
218d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --xml-reports-directory <path>: directory to emit JUnit-style");
219d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      XML test results.");
220d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
221d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --classpath <jar file>: add the .jar to both build and execute classpaths.");
222d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
223ba0670d6c4481a866ae558d4e31f8004c709dd77jessewilson@google.com        System.out.println("  --use-bootclasspath: use the classpath as search path for bootstrap classes.");
224d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
225d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --build-classpath <element>: add the directory or .jar to the build");
226d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      classpath. Such classes are available as build dependencies, but");
227d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      not at runtime.");
228d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
229d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --sourcepath <directory>: add the directory to the build sourcepath.");
230d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
231d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --vogar-dir <directory>: directory in which to find Vogar");
2326a52e048641707c987c6a00691ba8c9f891ccf00jsharpe@google.com        System.out.println("      configuration information, caches, saved results, and tags,");
2336a52e048641707c987c6a00691ba8c9f891ccf00jsharpe@google.com        System.out.println("      unless they've been put explicitly elsewhere.");
234d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      Default is: " + vogarDir);
2354cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
2366a52e048641707c987c6a00691ba8c9f891ccf00jsharpe@google.com        System.out.println("  --tag-dir <directory>: directory in which to find tag information.");
2374ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com        System.out.println("      Default is: " + vogarDir + "/tags");
2386a52e048641707c987c6a00691ba8c9f891ccf00jsharpe@google.com        System.out.println();
2394cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --tag <tag name>: creates a tag recording the arguments to this");
2404cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      invocation of Vogar so that it can be rerun later.");
2414cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
2424cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --run-tag <tag name>: runs Vogar with arguments as specified by the");
2434cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      tag. Any arguments supplied for this run will override those");
2444cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      supplied by the tag.");
2454cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
246d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --compare-to-tag <tag name>: compares the results of this run with");
247d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      the results saved when the tag was created. Defaults to the value");
248d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      of --run-tag if that argument is given.");
249d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
250d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --record-results: record test results for future comparison.");
251d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
252d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --results-dir <directory>: read and write (if --record-results used)");
253d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      results from and to this directory.");
254d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
2554cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --tag-overwrite: allow --tag to overwrite an existing tag.");
2564cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
257d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --verbose: turn on persistent verbose output.");
258d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
259d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("TARGET OPTIONS");
260d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
261d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --debug <port>: enable Java debugging on the specified port.");
262d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      This port must be free both on the device and on the local");
263d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      system. Disables the timeout specified by --timeout-seconds.");
264d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
2653d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com        System.out.println("  --device-dir <directory>: use the specified directory for");
266d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      on-device temporary files and code.");
2673d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com        System.out.println("      Default is: " + deviceDir);
268d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
269d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --vm-arg <argument>: include the specified argument when spawning a");
270d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      virtual machine. Examples: -Xint:fast, -ea, -Xmx16M");
271d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
272d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --java-home <java_home>: execute the actions on the local workstation");
273d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      using the specified java home directory. This does not impact");
274d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      which javac gets used. When unset, java is used from the PATH.");
275d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
276d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("EXOTIC OPTIONS");
277d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
2782c67cf17be7262353493480d98fb88ad0f8fc320jsharpe@google.com        System.out.println("  --device-cache: keep copies of dexed files on the SD card so they");
27941a680807eb80e63fbfe42c218c9e1da6615d867jsharpe@google.com        System.out.println("      don't need to be pushed each time a test is run, improving");
2802c67cf17be7262353493480d98fb88ad0f8fc320jsharpe@google.com        System.out.println("      start times (default). Only affects device mode. Disable with");
2814cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      --no-device-cache to save space on the SD card.");
28241a680807eb80e63fbfe42c218c9e1da6615d867jsharpe@google.com        System.out.println();
2833dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("  --suggest-classpaths: build an index of jar files under the");
284d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      directories given by --jar-search-dir arguments. If Vogar then ");
285d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      fails due to missing classes or packages, it will use the index to");
286d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      diagnose the problem and suggest a fix.");
2873dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println();
2883dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("      Currently only looks for jars called exactly \"classes.jar\".");
2893dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println();
290d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --jar-search-dir <directory>: a directory that should be searched for");
291d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      jar files to add to the class file index for use with");
292d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      --suggest-classpaths.");
293d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
294d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean-before: remove working directories before building and");
295d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      running (default). Disable with --no-clean-before if you are");
296d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      using interactively with your own temporary input files.");
297d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
298d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean-after: remove temporary files after running (default).");
299d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Disable with --no-clean-after and use with --verbose if");
300d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      you'd like to manually re-run commands afterwards.");
301d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
302d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --color: format output in technicolor.");
303d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
30450bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("  --pass-color: ANSI color code to use for passes.");
30550bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("      Default: 32 (green)");
30650bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println();
30750bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("  --warn-color: ANSI color code to use for warnings.");
30850bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("      Default: 33 (yellow)");
30950bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println();
31050bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("  --fail-color: ANSI color code to use for failures.");
31150bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("      Default: 31 (red)");
31250bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println();
313d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --expectations <file>: include the specified file when looking for");
314d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      action expectations. The file should include qualified action names");
315d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      and the corresponding expected output.");
316d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + expectationFiles);
317d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
3183dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("  --indent: amount to indent action result output. Can be set to ''");
319d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      (aka empty string) to simplify output parsing.");
320d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: '" + indent + "'");
321d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
322d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --javac-arg <argument>: include the specified argument when invoking");
323d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      javac. Examples: --javac-arg -Xmaxerrs --javac-arg 1");
324d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
325d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --monitor-timeout <seconds>: number of seconds to wait for the target");
326d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      process to launch. This can be used to prevent connection failures");
327d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      when dexopt is slow.");
328d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
329126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("  --first-monitor-port <port>: the port on the host (and possibly target)");
330126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("      used to traffic control messages between vogar and forked processes.");
331126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("      Use this to avoid port conflicts when running multiple vogar instances");
332126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("      concurrently. Vogar will use up to N ports starting with this one,");
333126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("      where N is the number of processors on the host (" + NUM_PROCESSORS + "). ");
334126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println();
335d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("CONFIG FILE");
336d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
337d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  User-defined default arguments can be specified in ~/.vogarconfig. See");
338d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  .vogarconfig.example for an example.");
339d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
340d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
341d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
342d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean parseArgs(String[] args) {
343d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        List<String> actionsAndTargetArgs;
344d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
345d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        // extract arguments from config file
3468918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com        String[] configArgs = optionParser.readFile(configFile);
347d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
348d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        // config file args are added first so that in a conflict, the currently supplied
349d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        // arguments win.
350d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        actionsAndTargetArgs = optionParser.parse(configArgs);
3518918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com        if (!actionsAndTargetArgs.isEmpty()) {
3528918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            throw new RuntimeException(
3538918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com                    "actions or targets given in .vogarconfig: " + actionsAndTargetArgs);
3548918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com        }
355d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
356d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        try {
357d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com            actionsAndTargetArgs.addAll(optionParser.parse(args));
358d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } catch (RuntimeException e) {
359d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println(e.getMessage());
360d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
361d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
362d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
3634cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        if (runTag != null && tagName != null) {
3644cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            System.out.println("Cannot use both --run-tag and --tag options");
3654cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            return false;
3664cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        }
3674cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
3684cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        if (runTag != null) {
3694cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            String oldTag = tagName;
3704cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            String[] runTagArgs;
3718918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            if (tagDir == null) {
3724ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com                tagDir = new File(vogarDir, "/tags");
3738918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            }
3744cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            try {
3754cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                runTagArgs = new Tag(tagDir, runTag, false).getArgs();
3764cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                System.out.println("Executing Vogar with additional arguments from tag \""
3774cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                        + runTag + "\":");
378c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                System.out.println(Strings.join(" ", (Object[]) runTagArgs));
3794cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            } catch (FileNotFoundException e) {
380fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com                System.out.println("Tag \"" + runTag + "\" doesn't exist");
381fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com                System.out.println("Existing tags are: "
382c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                        + Strings.join(", ", (Object[]) Tag.getAllTags(tagDir)));
3834cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                return false;
3844cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            }
385d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com            // rollback changes already made by the optionParser to insert tag arguments
3864cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            optionParser.reset();
387d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com            actionsAndTargetArgs = optionParser.parse(configArgs);
3884cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // runTags options are applied first so that the current command's arguments win if
3894cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // there is a conflict
390d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com            actionsAndTargetArgs.addAll(optionParser.parse(runTagArgs));
3914cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // tag is the only argument we don't allow to be supplied by the run tag
3924cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            tagName = oldTag;
3934cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            actionsAndTargetArgs.addAll(optionParser.parse(args));
3944cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        }
3954cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
396d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
397d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // Semantic error validation
398d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
399d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
400d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (javaHome != null && !new File(javaHome, "/bin/java").exists()) {
401d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Invalid java home: " + javaHome);
402d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
403d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
4047850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
405d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // check vm option consistency
406595d8fd07fcad6d6661466b4b22905e5e82eb857jessewilson@google.com        if (!mode.acceptsVmArgs() && !vmArgs.isEmpty()) {
407d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("VM args " + vmArgs + " should not be specified for mode " + mode);
408d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
409d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
410d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
411d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (xmlReportsDirectory != null && !xmlReportsDirectory.isDirectory()) {
412d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Invalid XML reports directory: " + xmlReportsDirectory);
413d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
414d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
415d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
416d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (!clean) {
417d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            cleanBefore = false;
418d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            cleanAfter = false;
419d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
4207850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
421d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
422d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // Post-processing arguments
423d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
424d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
425d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // disable timeout when debugging
426d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (debugPort != null) {
427d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            timeoutSeconds = 0;
428d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
429d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
430126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        if (firstMonitorPort == -1) {
431126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com            firstMonitorPort = mode.isHost() ? 8788 : 8787;
432126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        }
433126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com
434d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // separate the actions and the target args
435d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        int index = 0;
436d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        for (; index < actionsAndTargetArgs.size(); index++) {
437d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            String arg = actionsAndTargetArgs.get(index);
438d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            if (arg.equals("--")) {
439d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                index++;
440d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                break;
4417850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
4427850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
443d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            File file = new File(arg);
444d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            if (file.exists()) {
445d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                if (arg.endsWith(".java") || file.isDirectory()) {
446995a215ce56a98ed522888b0fdc286cd612c0218jessewilson@google.com                    actionFiles.add(file.getAbsoluteFile());
447d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                } else {
448d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                    System.out.println("Expected a .jar file, .java file, directory, "
449d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                            + "package name or classname, but was: " + arg);
450d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                    return false;
451d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                }
452d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            } else {
453d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                actionClassesAndPackages.add(arg);
4547850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
455d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
456d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
457d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        targetArgs.addAll(actionsAndTargetArgs.subList(index, actionsAndTargetArgs.size()));
4587850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
459d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (actionFiles.isEmpty() && actionClassesAndPackages.isEmpty()) {
460d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("No actions provided.");
461d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
4627850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
4637850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
464595d8fd07fcad6d6661466b4b22905e5e82eb857jessewilson@google.com        if (!mode.acceptsVmArgs() && !targetArgs.isEmpty()) {
465d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Target args " + targetArgs + " should not be specified for mode " + mode);
466d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
467d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
4687850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
4695bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com        if (valgrind && !mode.supportsValgrind()) {
4705bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com            System.out.println("Valgrind is not supported for mode " + mode);
4715bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com            return false;
4725bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com        }
4735bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com
4744cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        if (tagName != null) {
4758918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            if (tagDir == null) {
4764ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com                tagDir = new File(vogarDir, "/tags");
4778918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            }
4788918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            new Tag(tagDir, tagName, tagOverwrite).saveArgs(args);
4794cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        }
4804cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
481d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        return true;
482d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
4837850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
48475a72cc4c645e7e038f381c936d3f521ac6c30adbdc@google.com    private boolean run() {
4855884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com        Console.init(stream);
48650bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        Console.getInstance().setUseColor(color, passColor, warnColor, failColor);
487d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setIndent(indent);
488d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setVerbose(verbose);
489d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
490d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        ClassFileIndex classFileIndex = new ClassFileIndex(jarSearchDirs);
4913dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        if (suggestClasspaths) {
4923dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com            classFileIndex.createIndex();
4933dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        }
4943dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com
495d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        if (resultsDir == null) {
4964ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com            resultsDir = new File(vogarDir, "results");
497d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        }
4988918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com        if (tagDir == null) {
4994ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com            tagDir = new File(vogarDir, "results/tags");
5008918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com        }
5013d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com
5025884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com        int numRunners = (stream || this.mode == ModeId.ACTIVITY)
5035884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com                ? 1
504126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com                : NUM_PROCESSORS;
505d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Mode.Options modeOptions = new Mode.Options(Classpath.of(buildClasspath), sourcepath,
506c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                javacArgs, javaHome, firstMonitorPort, monitorTimeout, timeoutSeconds,
5078a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com                useBootClasspath, Classpath.of(classpath), nativeOutput);
508d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
509d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        AndroidSdk androidSdk = null;
510d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (mode.requiresAndroidSdk()) {
511d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            androidSdk = AndroidSdk.getFromPath();
5123d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com            if (deviceCache) {
5133d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com                androidSdk.setDeviceCache(new DeviceFileCache(deviceDir, androidSdk));
5143d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com            }
515d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            modeOptions.buildClasspath.addAll(androidSdk.getAndroidClasses());
516d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
517d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
518d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        File localTemp = new File("/tmp/vogar/" + UUID.randomUUID());
519d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Environment environment = mode.isHost()
520c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                ? new EnvironmentHost(cleanBefore, cleanAfter, debugPort, localTemp)
521c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                : new EnvironmentDevice(cleanBefore, cleanAfter, debugPort, firstMonitorPort,
522c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                        numRunners, localTemp, new File(deviceDir, "run"), androidSdk);
523d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
524d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Vm.Options vmOptions = (mode.acceptsVmArgs())
525d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                ? new Vm.Options(vmArgs, targetArgs)
526d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                : null;
527957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com
5287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Mode mode;
529c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com        switch (this.mode) {
530c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com            case JVM:
531c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                mode = new JavaVm(environment, modeOptions, vmOptions);
532c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                break;
533c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com            case SIM:
534c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                mode = new HostDalvikVm(environment, modeOptions, vmOptions, androidSdk, valgrind);
535c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                break;
536c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com            case DEVICE:
537c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                mode = new DeviceDalvikVm(environment, modeOptions, vmOptions);
538c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                break;
539c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com            case ACTIVITY:
540c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                mode = new ActivityMode(environment, modeOptions);
541c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                break;
542c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com            default:
543c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                throw new AssertionError();
5447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
5457850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
5467850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        ExpectationStore expectationStore;
5477850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        try {
548d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            expectationStore = ExpectationStore.parse(expectationFiles);
5497850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        } catch (IOException e) {
5507850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("Problem loading expectations: " + e);
55175a72cc4c645e7e038f381c936d3f521ac6c30adbdc@google.com            return false;
5527850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
5537850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
554d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        Date currentDate = new Date();
555d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
556d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        XmlReportPrinter xmlReportPrinter = xmlReportsDirectory != null
557d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com                ? new XmlReportPrinter(xmlReportsDirectory, expectationStore, currentDate)
5587850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                : null;
5597850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
560d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        // Automatically compare to a tag if we explicitly run it
561d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        if (runTag != null && compareToTag == null) {
562d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com            compareToTag = runTag;
563d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        }
564d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
5658c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        int smallTimeoutSeconds = timeoutSeconds;
5667850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Driver driver = new Driver(
5677850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                localTemp,
5687850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                mode,
5697850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                expectationStore,
570d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com                currentDate,
5717850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                xmlReportPrinter,
572126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com                firstMonitorPort,
5738c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com                smallTimeoutSeconds,
5743dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com                smallTimeoutSeconds * LARGE_TIMEOUT_MULTIPLIER,
5755884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com                classFileIndex,
576d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com                resultsDir,
5778918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com                tagDir,
578d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com                tagName,
579d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com                compareToTag,
580d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com                recordResults,
5815884b0e6bc3eec46f4a374254626a14d128179fajessewilson@google.com                numRunners);
5827850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
58375a72cc4c645e7e038f381c936d3f521ac6c30adbdc@google.com        return driver.buildAndRun(actionFiles, actionClassesAndPackages);
5847850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
5857850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
5867850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    public static void main(String[] args) {
5877850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Vogar vogar = new Vogar();
588d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (!vogar.parseArgs(args)) {
589d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            vogar.printUsage();
5907850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return;
5917850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
59275a72cc4c645e7e038f381c936d3f521ac6c30adbdc@google.com        boolean allSuccess = vogar.run();
59375a72cc4c645e7e038f381c936d3f521ac6c30adbdc@google.com        System.exit(allSuccess ? 0 : 1);
5947850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
595d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
596d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    enum ModeId {
597c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com        DEVICE, JVM, ACTIVITY, SIM, CRORE;
598d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
5995bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com        public boolean supportsValgrind() {
6005bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com            return this == SIM;
6015bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com        }
6025bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com
603d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        public boolean acceptsVmArgs() {
604c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com            return this != ACTIVITY && this != CRORE;
605d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
606d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
607d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        public boolean isHost() {
608c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com            return this == JVM || this == SIM || this == CRORE;
609d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
610d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
611d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        public boolean requiresAndroidSdk() {
612d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return this == DEVICE || this == ACTIVITY || this == SIM;
613d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
614d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
6157850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com}
616