Vogar.java revision dc0120df8603b26adfd4ddfbeac422ff99a002b5
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;
20d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.comimport com.google.inject.Provides;
21d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.comimport com.google.inject.mini.MiniGuice;
227850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.File;
234cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.comimport java.io.FileNotFoundException;
247850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.IOException;
257850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.ArrayList;
26d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.comimport java.util.Date;
277850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.LinkedHashSet;
287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.List;
297850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.Set;
307850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.UUID;
31d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.comimport javax.inject.Named;
32d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.comimport javax.inject.Provider;
33d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.comimport javax.inject.Singleton;
34969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.ActivityMode;
35969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.AndroidSdk;
361359051f7f2b5e928d5fbb0b621d5d4ddcd6cc31bdc@google.comimport vogar.android.AppProcessMode;
37969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.DeviceDalvikVm;
38969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.DeviceFileCache;
39969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.EnvironmentDevice;
40969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.comimport vogar.android.HostDalvikVm;
41b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.comimport vogar.commands.Mkdir;
42d59b17f5dc87d856a01714853d5296d387ff8dedjessewilson@google.comimport vogar.util.Strings;
437850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com/**
457850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Command line interface for running benchmarks and tests on dalvik.
467850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com */
477850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.compublic final class Vogar {
487850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
498c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com    private static final int LARGE_TIMEOUT_MULTIPLIER = 10;
50126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com    private static final int NUM_PROCESSORS = Runtime.getRuntime().availableProcessors();
518c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com
52d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<File> actionFiles = new ArrayList<File>();
53d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<String> actionClassesAndPackages = new ArrayList<String>();
54d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<String> targetArgs = new ArrayList<String>();
55fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com    private final OptionParser optionParser = new OptionParser(this);
5625d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com    private File configFile = Vogar.dotFile(".vogarconfig");
5725d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com
58969d5622a380e2f2f9ebdfbf7a22cbb3e031125bjessewilson@google.com    public static File dotFile (String name) {
5925d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com        return new File(System.getProperty("user.home", "."), name);
6025d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com    }
6125d56e71aa66d20d4326eee3696f4ce060201708bdc@google.com
62d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--expectations" })
63d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Set<File> expectationFiles = new LinkedHashSet<File>();
64d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    {
659f9a3ba8e244912c50140ba15ec583a8098dca41enh@google.com        expectationFiles.addAll(AndroidSdk.defaultExpectations());
66d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
677850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
68d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--mode" })
69d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private ModeId mode = ModeId.DEVICE;
707850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
71d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--timeout" })
72d296ba8af13d367b4a701ddeba405ee51caa05c1enh@google.com    private int timeoutSeconds = 1 * 60; // default is one minute;
737850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
74126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com    @Option(names = { "--first-monitor-port" })
75126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com    private int firstMonitorPort = -1;
76126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com
77d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--clean-before" })
78d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean cleanBefore = true;
797850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
80d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--clean-after" })
81d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean cleanAfter = true;
827850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
83d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--clean" })
84d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean clean = true;
857850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
86d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--xml-reports-directory" })
87d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private File xmlReportsDirectory;
887850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
89d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--indent" })
90d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private String indent = "  ";
917850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
92d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--verbose" })
93d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean verbose;
947850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
95d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--stream" })
96d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean stream = true;
977850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
98d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--color" })
99d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean color = true;
1007850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
10150bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    @Option(names = { "--pass-color" })
10250bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    private int passColor = 32; // green
10350bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com
10450bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    @Option(names = { "--warn-color" })
10550bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    private int warnColor = 33; // yellow
10650bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com
10750bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    @Option(names = { "--fail-color" })
10850bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com    private int failColor = 31; // red
10950bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com
1100942355a74d759fb2e50a002b6b0b93430f07d72bdc@google.com    @Option(names = { "--ansi" })
1110942355a74d759fb2e50a002b6b0b93430f07d72bdc@google.com    private boolean ansi = !"dumb".equals(System.getenv("TERM"));
1120942355a74d759fb2e50a002b6b0b93430f07d72bdc@google.com
113d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--debug" })
114d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Integer debugPort;
115d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
1163d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com    @Option(names = { "--device-dir" })
1173d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com    private File deviceDir = new File("/sdcard/vogar");
118d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
119d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--vm-arg" })
120d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<String> vmArgs = new ArrayList<String>();
121d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
122d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--java-home" })
123d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private File javaHome;
124d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
125d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--javac-arg" })
126d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<String> javacArgs = new ArrayList<String>();
127d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
12882131e6aba37e8b6f8ebbadbbe57fb5a78b4f743jessewilson@google.com    @Option(names = { "--use-bootclasspath" })
129d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean useBootClasspath = false;
130d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
131d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--build-classpath" })
132d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<File> buildClasspath = new ArrayList<File>();
133d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
134d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--classpath", "-cp" })
135d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<File> classpath = new ArrayList<File>();
136d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
137d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--sourcepath" })
138d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<File> sourcepath = new ArrayList<File>();
139dd2774574cb456b48b8ec2aafbf0e6583f4faa41enh@google.com    {
140dd2774574cb456b48b8ec2aafbf0e6583f4faa41enh@google.com        sourcepath.addAll(AndroidSdk.defaultSourcePath());
141dd2774574cb456b48b8ec2aafbf0e6583f4faa41enh@google.com    }
142d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
143d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--jar-search-dir" })
144d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    private List<File> jarSearchDirs = Lists.newArrayList();
145d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
146d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--vogar-dir" })
1474ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com    private File vogarDir = Vogar.dotFile(".vogar");
1484cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
1498918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com    @Option(names = { "--tag-dir" })
1508918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com    private File tagDir = null;
1518918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com
15200d4ce596c71916d975f6c8d967af53ab0a8f453jsharpe@google.com    @Option(names = { "--tag" }, savedInTag = false)
1534cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private String tagName = null;
1544cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
15500d4ce596c71916d975f6c8d967af53ab0a8f453jsharpe@google.com    @Option(names = { "--run-tag" }, savedInTag = false)
1564cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private String runTag = null;
1574cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
158d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--compare-to-tag" }, savedInTag = false)
159d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    private String compareToTag = null;
160d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
16100d4ce596c71916d975f6c8d967af53ab0a8f453jsharpe@google.com    @Option(names = { "--tag-overwrite" }, savedInTag = false)
1624cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private boolean tagOverwrite = false;
1634cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
164d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--record-results" })
165d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    private boolean recordResults = false;
166d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
167d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    @Option(names = { "--results-dir" })
168d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com    private File resultsDir = null;
169d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
1703dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com    @Option(names = { "--suggest-classpaths" })
1713dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com    private boolean suggestClasspaths = false;
1723dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com
1730ebefc061203658ed8b7f5df31a65d2cf6ea89b2jsharpe@google.com    @Option(names = { "--invoke-with" })
1740ebefc061203658ed8b7f5df31a65d2cf6ea89b2jsharpe@google.com    private String invokeWith = null;
1755bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com
176e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com    @Option(names = { "--benchmark" })
177e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com    private boolean benchmark = false;
178e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com
17934688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com    @Option(names = { "--open-bugs-command" })
18034688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com    private String openBugsCommand;
18134688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com
1821bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    @Option(names = { "--profile" })
1831bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    private boolean profile = false;
1841bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
18534b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com    @Option(names = { "--profile-binary" })
18634b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com    private boolean profileBinary = false;
18734b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com
1881bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    @Option(names = { "--profile-file" })
18934b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com    private File profileFile;
1901bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
1911bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    @Option(names = { "--profile-depth" })
1921bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    private int profileDepth = 4;
1931bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
1941bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    @Option(names = { "--profile-interval" })
1951bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    private int profileInterval = 10;
1961bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
1971bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    @Option(names = { "--profile-thread-group" })
1981bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com    private boolean profileThreadGroup = false;
1991bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
200d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Vogar() {}
201d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
202d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private void printUsage() {
203fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com        // have to reset fields so that "Default is: FOO" lines are accurate
204fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com        optionParser.reset();
205fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com
206d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("Usage: Vogar [options]... <actions>... [-- target args]...");
207d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
208d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  <actions>: .java files, directories, or class names.");
209d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      These should be JUnit tests, jtreg tests, Caliper benchmarks");
210d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      or executable Java classes.");
211d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
21272c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        System.out.println("      When passing in a JUnit test class, it may have \"#method_name\"");
21372c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        System.out.println("      appended to it, to specify a single test method.");
21472c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        System.out.println();
215d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  [args]: arguments passed to the target process. This is only useful when");
216d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      the target process is a Caliper benchmark or main method.");
217d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
218d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("GENERAL OPTIONS");
219d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
22088cd944c99e5f9197bb7dcdb4f9874c011e7ed9bjessewilson@google.com        System.out.println("  --mode <activity|device|sim|host|jvm>: specify which environment to run in.");
221d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      activity: runs in an Android application on a device or emulator");
222d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      device: runs in a Dalvik VM on a device or emulator");
22388cd944c99e5f9197bb7dcdb4f9874c011e7ed9bjessewilson@google.com        System.out.println("      sim: runs in a Dalvik VM on the local desktop built with sim-eng lunch combo");
22488cd944c99e5f9197bb7dcdb4f9874c011e7ed9bjessewilson@google.com        System.out.println("      host: runs in a Dalvik VM on the local desktop built with any lunch combo.");
22579e4231584a3b24b44f42224475d41fcbe957af4jessewilson@google.com        System.out.println("      jvm: runs in a Java VM on the local desktop");
226d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + mode);
227d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
228d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean: synonym for --clean-before and --clean-after (default).");
229d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Disable with --no-clean if you want no files removed.");
230d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
231d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --stream: stream output as it is emitted.");
232d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
2338a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com        System.out.println("  --native-output: print out native output (prefixed with \"[native]\").");
2348a9cc00a0d2c02483690de28eabe2b60b5804538jsharpe@google.com        System.out.println();
235e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com        System.out.println("  --benchmark: for use with dalvikvm, this dexes all files together,");
236e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com        System.out.println("      and is mandatory for running Caliper benchmarks, and a good idea");
237e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com        System.out.println("      other performance sensitive code.");
238e5dfbecbaa8568c2885a4cb859c8afa8b6a08d5bjsharpe@google.com        System.out.println();
23934b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com        System.out.println("  --profile: run with a profiler to produce an hprof file.");
24034b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com        System.out.println();
24134b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com        System.out.println("  --profile-binary: produce a binary hprof file instead of the default ASCII.");
2421bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println();
2431bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println("  --profile-file <filename>: filename for hprof profile data.");
24434b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com        System.out.println("      Default is java.hprof.txt in ASCII mode and java.hprof in binary mode.");
2451bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println();
2461bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println("  --profile-depth <count>: number of frames in profile stack traces.");
2471bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println("      Default is: " + profileDepth);
2481bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println();
2491bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println("  --profile-interval <milliseconds>: interval between profile samples.");
2501bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println("      Default is: " + profileInterval);
2511bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println();
2521bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println("  --profile-thread-group: profile thread group instead of single thread in dalvikvms");
2531bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println("      Note --mode jvm only supports full VM profiling.");
2541bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println("      Default is: " + profileThreadGroup);
2551bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        System.out.println();
2565b644afaebd7afc43f75010b7c32f02129638a49bdc@google.com        System.out.println("  --invoke-with: provide a command to invoke the VM with. Examples:");
2575b644afaebd7afc43f75010b7c32f02129638a49bdc@google.com        System.out.println("      --mode host --invoke-with \"valgrind --leak-check=full\"");
258fe3edd898b04ad1647a8fe4914a70245c01dc03abdc@google.com        System.out.println("      --mode device --invoke-with \"strace -f -o/sdcard/strace.txt\"");
2595bbc674fa121ae7898bfa6987e7a39c5ba4299e2enh@google.com        System.out.println();
260d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --timeout <seconds>: maximum execution time of each action before the");
261d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      runner aborts it. Specifying zero seconds or using --debug will");
2628c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        System.out.println("      disable the execution timeout. Tests tagged with 'large' will time");
2638c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        System.out.println("      out in " + LARGE_TIMEOUT_MULTIPLIER + "x this timeout.");
264d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + timeoutSeconds);
265d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
266d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --xml-reports-directory <path>: directory to emit JUnit-style");
267d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      XML test results.");
268d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
269d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --classpath <jar file>: add the .jar to both build and execute classpaths.");
270d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
271ba0670d6c4481a866ae558d4e31f8004c709dd77jessewilson@google.com        System.out.println("  --use-bootclasspath: use the classpath as search path for bootstrap classes.");
272d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
273d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --build-classpath <element>: add the directory or .jar to the build");
274d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      classpath. Such classes are available as build dependencies, but");
275d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      not at runtime.");
276d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
277d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --sourcepath <directory>: add the directory to the build sourcepath.");
278d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
279d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --vogar-dir <directory>: directory in which to find Vogar");
2806a52e048641707c987c6a00691ba8c9f891ccf00jsharpe@google.com        System.out.println("      configuration information, caches, saved results, and tags,");
2816a52e048641707c987c6a00691ba8c9f891ccf00jsharpe@google.com        System.out.println("      unless they've been put explicitly elsewhere.");
282d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      Default is: " + vogarDir);
2834cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
2846a52e048641707c987c6a00691ba8c9f891ccf00jsharpe@google.com        System.out.println("  --tag-dir <directory>: directory in which to find tag information.");
2854ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com        System.out.println("      Default is: " + vogarDir + "/tags");
2866a52e048641707c987c6a00691ba8c9f891ccf00jsharpe@google.com        System.out.println();
2874cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --tag <tag name>: creates a tag recording the arguments to this");
2884cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      invocation of Vogar so that it can be rerun later.");
2894cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
2904cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --run-tag <tag name>: runs Vogar with arguments as specified by the");
2914cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      tag. Any arguments supplied for this run will override those");
2924cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      supplied by the tag.");
2934cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
294d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --compare-to-tag <tag name>: compares the results of this run with");
295d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      the results saved when the tag was created. Defaults to the value");
296d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      of --run-tag if that argument is given.");
297d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
298d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --record-results: record test results for future comparison.");
299d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
300d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --results-dir <directory>: read and write (if --record-results used)");
301d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      results from and to this directory.");
302d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
3034cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --tag-overwrite: allow --tag to overwrite an existing tag.");
3044cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
305d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --verbose: turn on persistent verbose output.");
306d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
307d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("TARGET OPTIONS");
308d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
309d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --debug <port>: enable Java debugging on the specified port.");
310d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      This port must be free both on the device and on the local");
311d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      system. Disables the timeout specified by --timeout-seconds.");
312d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
3133d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com        System.out.println("  --device-dir <directory>: use the specified directory for");
314d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      on-device temporary files and code.");
3153d6e772fe3a0d392af6f6ca008c556ba7c253503bdc@google.com        System.out.println("      Default is: " + deviceDir);
316d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
317d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --vm-arg <argument>: include the specified argument when spawning a");
318d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      virtual machine. Examples: -Xint:fast, -ea, -Xmx16M");
319d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
320d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --java-home <java_home>: execute the actions on the local workstation");
321d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      using the specified java home directory. This does not impact");
322d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      which javac gets used. When unset, java is used from the PATH.");
323d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
324d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("EXOTIC OPTIONS");
325d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
3263dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("  --suggest-classpaths: build an index of jar files under the");
327d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      directories given by --jar-search-dir arguments. If Vogar then ");
328d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      fails due to missing classes or packages, it will use the index to");
329d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      diagnose the problem and suggest a fix.");
3303dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println();
3313dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("      Currently only looks for jars called exactly \"classes.jar\".");
3323dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println();
333d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  --jar-search-dir <directory>: a directory that should be searched for");
334d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      jar files to add to the class file index for use with");
335d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("      --suggest-classpaths.");
336d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
337d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean-before: remove working directories before building and");
338d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      running (default). Disable with --no-clean-before if you are");
339d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      using interactively with your own temporary input files.");
340d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
341d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean-after: remove temporary files after running (default).");
342d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Disable with --no-clean-after and use with --verbose if");
343d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      you'd like to manually re-run commands afterwards.");
344d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
345d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --color: format output in technicolor.");
346d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
34750bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("  --pass-color: ANSI color code to use for passes.");
34850bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("      Default: 32 (green)");
34950bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println();
35050bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("  --warn-color: ANSI color code to use for warnings.");
35150bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("      Default: 33 (yellow)");
35250bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println();
35350bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("  --fail-color: ANSI color code to use for failures.");
35450bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println("      Default: 31 (red)");
35550bd7c43bee5854a7a824265ec224c58c67c698bjsharpe@google.com        System.out.println();
356dc0120df8603b26adfd4ddfbeac422ff99a002b5jessewilson@google.com        System.out.println("  --ansi: use ANSI escape sequences to remove intermediate output.");
3570942355a74d759fb2e50a002b6b0b93430f07d72bdc@google.com        System.out.println();
358d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --expectations <file>: include the specified file when looking for");
359d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      action expectations. The file should include qualified action names");
360d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      and the corresponding expected output.");
361d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + expectationFiles);
362d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
3633dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("  --indent: amount to indent action result output. Can be set to ''");
364d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      (aka empty string) to simplify output parsing.");
365d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: '" + indent + "'");
366d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
367d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --javac-arg <argument>: include the specified argument when invoking");
368d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      javac. Examples: --javac-arg -Xmaxerrs --javac-arg 1");
369d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
370126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("  --first-monitor-port <port>: the port on the host (and possibly target)");
371126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("      used to traffic control messages between vogar and forked processes.");
372126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("      Use this to avoid port conflicts when running multiple vogar instances");
373126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("      concurrently. Vogar will use up to N ports starting with this one,");
374126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println("      where N is the number of processors on the host (" + NUM_PROCESSORS + "). ");
375126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        System.out.println();
37634688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com        System.out.println("  --open-bugs-command <command>: a command that will take bug IDs as parameters");
37734688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com        System.out.println("      and return those bugs that are still open. For example, if bugs 123 and");
37834688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com        System.out.println("      789 are both open, the command should echo those values:");
37934688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com        System.out.println("         $ ~/bin/bug-command 123 456 789");
38034688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com        System.out.println("         123");
38134688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com        System.out.println("         789");
38234688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com        System.out.println();
383d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("CONFIG FILE");
384d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
385d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  User-defined default arguments can be specified in ~/.vogarconfig. See");
386d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println("  .vogarconfig.example for an example.");
387d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        System.out.println();
388d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
389d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
390d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean parseArgs(String[] args) {
391d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        List<String> actionsAndTargetArgs;
392d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
393d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        // extract arguments from config file
3948918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com        String[] configArgs = optionParser.readFile(configFile);
395d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
396d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        // config file args are added first so that in a conflict, the currently supplied
397d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        // arguments win.
398d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com        actionsAndTargetArgs = optionParser.parse(configArgs);
3998918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com        if (!actionsAndTargetArgs.isEmpty()) {
4008918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            throw new RuntimeException(
4018918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com                    "actions or targets given in .vogarconfig: " + actionsAndTargetArgs);
4028918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com        }
403d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com
404d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        try {
405d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com            actionsAndTargetArgs.addAll(optionParser.parse(args));
406d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } catch (RuntimeException e) {
407d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println(e.getMessage());
408d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
409d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
410d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
4114cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        if (runTag != null && tagName != null) {
4124cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            System.out.println("Cannot use both --run-tag and --tag options");
4134cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            return false;
4144cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        }
4154cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
4164cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        if (runTag != null) {
4174cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            String oldTag = tagName;
4184cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            String[] runTagArgs;
4198918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            if (tagDir == null) {
4204ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com                tagDir = new File(vogarDir, "/tags");
4218918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            }
4224cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            try {
4234cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                runTagArgs = new Tag(tagDir, runTag, false).getArgs();
4244cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                System.out.println("Executing Vogar with additional arguments from tag \""
4254cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                        + runTag + "\":");
426c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                System.out.println(Strings.join(" ", (Object[]) runTagArgs));
4274cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            } catch (FileNotFoundException e) {
428fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com                System.out.println("Tag \"" + runTag + "\" doesn't exist");
429fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com                System.out.println("Existing tags are: "
430c68971a68a4f7fe5a58ca0f59161bb44fcf2833djessewilson@google.com                        + Strings.join(", ", (Object[]) Tag.getAllTags(tagDir)));
4314cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                return false;
4324cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            }
433d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com            // rollback changes already made by the optionParser to insert tag arguments
4344cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            optionParser.reset();
435d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com            actionsAndTargetArgs = optionParser.parse(configArgs);
4364cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // runTags options are applied first so that the current command's arguments win if
4374cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // there is a conflict
438d806c4c900e08bf04e07b5c564f2f61d8c490731jsharpe@google.com            actionsAndTargetArgs.addAll(optionParser.parse(runTagArgs));
4394cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // tag is the only argument we don't allow to be supplied by the run tag
4404cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            tagName = oldTag;
4414cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            actionsAndTargetArgs.addAll(optionParser.parse(args));
4424cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        }
4434cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
444d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
445d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // Semantic error validation
446d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
447d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
448d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (javaHome != null && !new File(javaHome, "/bin/java").exists()) {
449d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Invalid java home: " + javaHome);
450d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
451d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
4527850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
453d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // check vm option consistency
454595d8fd07fcad6d6661466b4b22905e5e82eb857jessewilson@google.com        if (!mode.acceptsVmArgs() && !vmArgs.isEmpty()) {
455d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("VM args " + vmArgs + " should not be specified for mode " + mode);
456d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
457d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
458d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
459d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (xmlReportsDirectory != null && !xmlReportsDirectory.isDirectory()) {
460d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Invalid XML reports directory: " + xmlReportsDirectory);
461d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
462d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
463d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
464d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (!clean) {
465d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            cleanBefore = false;
466d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            cleanAfter = false;
467d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
4687850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
469d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
470d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // Post-processing arguments
471d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
472d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
473d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // disable timeout when debugging
474d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (debugPort != null) {
475d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            timeoutSeconds = 0;
476d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
477d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
478126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        if (firstMonitorPort == -1) {
479126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com            firstMonitorPort = mode.isHost() ? 8788 : 8787;
480126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com        }
481126b86dba3853c165e2d2f46e3cdffd7b2bb2f5bjessewilson@google.com
48234b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com        if (profileFile == null) {
48334b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com            profileFile = new File(profileBinary ? "java.hprof" : "java.hprof.txt");
48434b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com        }
48534b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com
486d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // separate the actions and the target args
487d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        int index = 0;
488d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        for (; index < actionsAndTargetArgs.size(); index++) {
489d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            String arg = actionsAndTargetArgs.get(index);
490d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            if (arg.equals("--")) {
491d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                index++;
492d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                break;
4937850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
4947850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
495d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            File file = new File(arg);
496d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            if (file.exists()) {
497d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                if (arg.endsWith(".java") || file.isDirectory()) {
498995a215ce56a98ed522888b0fdc286cd612c0218jessewilson@google.com                    actionFiles.add(file.getAbsoluteFile());
499d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                } else {
500d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                    System.out.println("Expected a .jar file, .java file, directory, "
501d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                            + "package name or classname, but was: " + arg);
502d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                    return false;
503d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                }
504d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            } else {
505d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                actionClassesAndPackages.add(arg);
5067850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
507d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
508d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
509d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        targetArgs.addAll(actionsAndTargetArgs.subList(index, actionsAndTargetArgs.size()));
5107850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
511d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (actionFiles.isEmpty() && actionClassesAndPackages.isEmpty()) {
512d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("No actions provided.");
513d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
5147850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
5157850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
516595d8fd07fcad6d6661466b4b22905e5e82eb857jessewilson@google.com        if (!mode.acceptsVmArgs() && !targetArgs.isEmpty()) {
517d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Target args " + targetArgs + " should not be specified for mode " + mode);
518d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
519d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
5207850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
5214cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        if (tagName != null) {
5228918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            if (tagDir == null) {
5234ac80fd21b440a8e9debe995e73c71e0fed8735cjsharpe@google.com                tagDir = new File(vogarDir, "/tags");
5248918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            }
5258918b5cafd482363a48e0bc9ae0114028cda7e79jsharpe@google.com            new Tag(tagDir, tagName, tagOverwrite).saveArgs(args);
5264cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        }
5274cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
528d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        return true;
529d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
5307850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
53175a72cc4c645e7e038f381c936d3f521ac6c30adbdc@google.com    private boolean run() {
532d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        Driver driver = MiniGuice.inject(Driver.class, new Module());
53375a72cc4c645e7e038f381c936d3f521ac6c30adbdc@google.com        return driver.buildAndRun(actionFiles, actionClassesAndPackages);
5347850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
5357850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
5367850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    public static void main(String[] args) {
5377850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Vogar vogar = new Vogar();
538d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (!vogar.parseArgs(args)) {
539d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            vogar.printUsage();
5407850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return;
5417850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
54275a72cc4c645e7e038f381c936d3f521ac6c30adbdc@google.com        boolean allSuccess = vogar.run();
54375a72cc4c645e7e038f381c936d3f521ac6c30adbdc@google.com        System.exit(allSuccess ? 0 : 1);
5447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
545d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
546d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com    private class Module {
547b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com        @Provides @Singleton Console provideConsole() {
548b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            Console console = stream
549b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com                    ? new Console.StreamingConsole()
550b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com                    : new Console.MultiplexingConsole();
551b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            console.setUseColor(color, passColor, warnColor, failColor);
552b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            console.setAnsi(ansi);
553b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            console.setIndent(indent);
554b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            console.setVerbose(verbose);
555b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            return console;
556b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com        }
557b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com
558b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com        @Provides Log provideLog(Console console) {
559b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            return console;
560b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com        }
561b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com
562d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("additionalVmArgs") List<String> provideAdditionalVmArgs() {
563d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return vmArgs;
564d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
565d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
566b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com        @Provides @Named("deviceDir") File provideDeviceDir() {
567b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            return deviceDir;
568b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com        }
569b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com
570b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com        @Provides @Singleton AndroidSdk provideAndroidSdk(
571b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com                Log log, Mkdir mkdir, HostFileCache hostFileCache) {
572b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            AndroidSdk androidSdk = new AndroidSdk(log, mkdir);
573b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            // resolve the circular dependency between device file cache & android SDK manually
574b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            androidSdk.setCaches(hostFileCache, new DeviceFileCache(log, deviceDir, androidSdk));
575d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return androidSdk;
576d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
577d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
578d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("benchmark") boolean provideBenchmark() {
579d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return benchmark;
580d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
581d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
582d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("buildClasspath") Classpath provideBuildClasspath(
583d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                Provider<AndroidSdk> androidSdkProvider) {
584d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            Classpath result = Classpath.of(buildClasspath);
585d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            if (mode.requiresAndroidSdk()) {
586d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                result.addAll(androidSdkProvider.get().getAndroidClasses());
587d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            }
588d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return result;
589d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
590d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
591b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com        @Provides ClassFileIndex provideClassFileIndex(Log log, Mkdir mkdir) {
592b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            ClassFileIndex classFileIndex = new ClassFileIndex(log, mkdir, jarSearchDirs);
593d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            if (suggestClasspaths) {
594d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                classFileIndex.createIndex();
595d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            }
596d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return classFileIndex;
597d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
598d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
599d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides Classpath provideClasspath() {
600d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return Classpath.of(classpath);
601d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
602d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
603d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("cleanAfter") boolean provideCleanAfter() {
604d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return cleanAfter;
605d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
606d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
607d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("cleanBefore") boolean provideCleanBefore() {
608d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return cleanBefore;
609d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
610d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
611d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("compareToTag") String provideCompareToTag() {
612d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            // Automatically compare to a tag if we explicitly run it
613d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return (runTag != null && compareToTag == null) ? runTag : compareToTag;
614d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
615d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
616d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides Date provideDate() {
617d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return new Date();
618d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
619d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
620d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("debugPort") Integer provideDebugPort() {
621d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return debugPort;
622d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
623d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
6247f334e23f258c2b0086acb153ed897a173e07adcjessewilson@google.com        @Provides @Named("deviceUserHome") File deviceUserHome() {
6257f334e23f258c2b0086acb153ed897a173e07adcjessewilson@google.com            return new File(deviceDir, "user.home");
626d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
627d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
628d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides Environment provideEnvironment(Provider<EnvironmentHost> environmentHostProvider,
629d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                Provider<EnvironmentDevice> environmentDeviceProvider) {
630d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return mode.isHost()
631d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                    ? environmentHostProvider.get()
632d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                    : environmentDeviceProvider.get();
633d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
634d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
635d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com        @Provides @Singleton ExpectationStore provideExpectationStore(
636d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com                Console console, ExpectationStore.BugDatabase bugDatabase) throws IOException {
637b5c5c44d0c0a01c278cdac68ae23646682eb8ef7jessewilson@google.com            ExpectationStore result = ExpectationStore.parse(console, expectationFiles, mode);
638d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com            if (bugDatabase != null) {
639d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com                result.loadBugStatuses(bugDatabase);
64034688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com            }
64134688e44757e5f31838dee7d52106531791fcb43jessewilson@google.com            return result;
642d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
643d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
644d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("fastMode") boolean provideFastMode() {
645d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return benchmark;
646d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
647d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
648d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com        @Provides @Singleton ExpectationStore.BugDatabase provideBugDatabase(Log log) {
649d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com            return openBugsCommand != null
650d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com                    ? new CommandBugDatabase(log, openBugsCommand)
651d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com                    : null;
652d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com        }
653d35a3a007cfa6e5d4041af5f4aed19acc69af291jessewilson@google.com
654d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("firstMonitorPort") int provideFirstMonitorPort() {
655d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return firstMonitorPort;
656d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
657d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
658d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("hostBuild") boolean provideHostBuild() {
659d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return (Vogar.this.mode == ModeId.HOST);
660d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
661d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
662d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("invokeWith") String provideInvokeWith() {
663d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return invokeWith;
664d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
665d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
666d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("javacArgs") List<String> provideJavacArgs() {
667d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return javacArgs;
668d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
669d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
670d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("javaHome") File provideJavaHome() {
671d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return javaHome;
672d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
673d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
674d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("largeTimeoutSeconds") int provideLargeTimeoutSeconds() {
675d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return timeoutSeconds * LARGE_TIMEOUT_MULTIPLIER;
676d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
677d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
678d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Singleton @Named("localTemp") File provideLocalTemp() {
679d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return new File("/tmp/vogar/" + UUID.randomUUID());
680d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
681d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
682d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("numRunners") int provideNumRunners() {
683d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return (stream || Vogar.this.mode == ModeId.ACTIVITY)
684d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                    ? 1
685d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                    : NUM_PROCESSORS;
686d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
687d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
688d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides Mode provideMode(Provider<JavaVm> javaVmProvider,
689d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                Provider<HostDalvikVm> hostDalvikVmProvider,
690d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                Provider<DeviceDalvikVm> deviceDalvikVmProvider,
6911359051f7f2b5e928d5fbb0b621d5d4ddcd6cc31bdc@google.com                Provider<ActivityMode> activityModeProvider,
6921359051f7f2b5e928d5fbb0b621d5d4ddcd6cc31bdc@google.com                Provider<AppProcessMode> appProcessModeProvider) {
693d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            switch (Vogar.this.mode) {
694d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                case JVM:
695d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                    return javaVmProvider.get();
696d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                case HOST:
697d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                case SIM:
698d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                    return hostDalvikVmProvider.get();
699d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                case DEVICE:
700d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                    return deviceDalvikVmProvider.get();
701d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                case ACTIVITY:
702d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                    return activityModeProvider.get();
7031359051f7f2b5e928d5fbb0b621d5d4ddcd6cc31bdc@google.com                case APP_PROCESS:
7041359051f7f2b5e928d5fbb0b621d5d4ddcd6cc31bdc@google.com                    return appProcessModeProvider.get();
705d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com                default:
7061359051f7f2b5e928d5fbb0b621d5d4ddcd6cc31bdc@google.com                    throw new AssertionError("Unknown mode " + Vogar.this.mode);
707d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            }
708d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
709d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
710d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("recordResults") boolean provideRecordResults() {
711d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return recordResults;
712d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
713d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
714d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("resultsDir") File provideResultsDir() {
715d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return resultsDir == null ? new File(vogarDir, "results") : resultsDir;
716d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
717d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
718d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("runnerDir") File provideRunnerDir() {
719d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return new File(deviceDir, "run");
720d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
721d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
722d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("smallTimeoutSeconds") int provideSmallTimeoutSeconds() {
723d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return timeoutSeconds;
724d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
725d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
726d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("sourcepath") List<File> provideSourcepath() {
727d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return sourcepath;
728d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
729d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
730d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("useBootClasspath") boolean provideUseBootClasspath() {
731d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return useBootClasspath;
732d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
733d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
734d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("tagDir") File provideTagDir() {
735d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return tagDir != null ? tagDir : new File(vogarDir, "results/tags");
736d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
737d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
738d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("tagName") String provideTagName() {
739d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return tagName;
740d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
741d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
742d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("targetArgs") List<String> provideTargetArgs() {
743d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return targetArgs;
744d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
745d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
746d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("vogarTemp") File provideVogarTemp() {
747d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return vogarDir;
748d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
749d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com
750d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        @Provides @Named("xmlReportsDirectory") File provideXmlReportsDirectory() {
751d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com            return xmlReportsDirectory;
752d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com        }
7531bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
7541bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        @Provides @Named("profile") boolean provideProfile() {
7551bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com            return profile;
7561bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        }
7571bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
75834b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com        @Provides @Named("profileBinary") boolean provideProfileBinary() {
75934b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com            return profileBinary;
76034b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com        }
76134b70bff9faaac07abcffa193b05cfb52d6d9908bdc@google.com
7621bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        @Provides @Named("profileFile") File provideProfileFile() {
7631bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com            return profileFile;
7641bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        }
7651bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
7661bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        @Provides @Named("profileDepth") int provideProfileDepth() {
7671bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com            return profileDepth;
7681bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        }
7691bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
7701bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        @Provides @Named("profileInterval") int profileInterval() {
7711bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com            return profileInterval;
7721bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        }
7731bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com
7741bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        @Provides @Named("profileThreadGroup") boolean profileThreadGroup() {
7751bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com            return profileThreadGroup;
7761bdeb9dd8f1ab3f308c285729af007ae8970425bbdc@google.com        }
777d9085944c8b6d18628266347c59545abae03ab9cjessewilson@google.com    }
7787850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com}
779