Vogar.java revision 3dafbce3b8d025f465ebf0a4c6d018c7dc31654e
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
197850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.File;
204cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.comimport java.io.FileNotFoundException;
217850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.IOException;
227850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.ArrayList;
237850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.LinkedHashSet;
247850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.List;
257850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.Set;
267850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.UUID;
27e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.comimport vogar.commands.AndroidSdk;
287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
297850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com/**
307850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com * Command line interface for running benchmarks and tests on dalvik.
317850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com */
327850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.compublic final class Vogar {
337850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
348c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com    private static final int LARGE_TIMEOUT_MULTIPLIER = 10;
358c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com
36d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<File> actionFiles = new ArrayList<File>();
37d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<String> actionClassesAndPackages = new ArrayList<String>();
38d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<String> targetArgs = new ArrayList<String>();
39fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com    private final OptionParser optionParser = new OptionParser(this);
40d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
41d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--expectations" })
42d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Set<File> expectationFiles = new LinkedHashSet<File>();
43d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    {
449f9a3ba8e244912c50140ba15ec583a8098dca41enh@google.com        expectationFiles.addAll(AndroidSdk.defaultExpectations());
45d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
467850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
47d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--mode" })
48d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private ModeId mode = ModeId.DEVICE;
497850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
50d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--timeout" })
51d296ba8af13d367b4a701ddeba405ee51caa05c1enh@google.com    private int timeoutSeconds = 1 * 60; // default is one minute;
527850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
53d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--monitor-timeout" })
54d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private long monitorTimeout = 30;
557850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
56d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--clean-before" })
57d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean cleanBefore = true;
587850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
59d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--clean-after" })
60d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean cleanAfter = true;
617850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
62d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--clean" })
63d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean clean = true;
647850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
65d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--xml-reports-directory" })
66d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private File xmlReportsDirectory;
677850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
68d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--indent" })
69d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private String indent = "  ";
707850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
71d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--verbose" })
72d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean verbose;
737850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
74d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--stream" })
75d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean stream = true;
767850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
77d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--color" })
78d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean color = true;
797850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
80d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--debug" })
81d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Integer debugPort;
82d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
83d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--device-runner-dir" })
8419f199189b177d36a56cd4fe6b51fa3b6fca83bcjessewilson@google.com    private File deviceRunnerDir = new File("/sdcard/vogar");
85d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
86d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--vm-arg" })
87d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<String> vmArgs = new ArrayList<String>();
88d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
89d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--java-home" })
90d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private File javaHome;
91d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
92d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--javac-arg" })
93d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<String> javacArgs = new ArrayList<String>();
94d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
9582131e6aba37e8b6f8ebbadbbe57fb5a78b4f743jessewilson@google.com    @Option(names = { "--use-bootclasspath" })
96d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean useBootClasspath = false;
97d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
98d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--build-classpath" })
99d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<File> buildClasspath = new ArrayList<File>();
100d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
101d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--classpath", "-cp" })
102d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<File> classpath = new ArrayList<File>();
103d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
104d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--sourcepath" })
105d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private List<File> sourcepath = new ArrayList<File>();
106d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
10741a680807eb80e63fbfe42c218c9e1da6615d867jsharpe@google.com    @Option(names = { "--device-cache" })
1082c67cf17be7262353493480d98fb88ad0f8fc320jsharpe@google.com    private boolean deviceCache = true;
10941a680807eb80e63fbfe42c218c9e1da6615d867jsharpe@google.com
1104cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    @Option(names = { "--tag-dir" })
1114cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private File tagDir = new File(System.getProperty("user.home", ".vogar/tags/") + "/.vogar/tags/");
1124cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
1134cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    @Option(names = { "--tag" })
1144cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private String tagName = null;
1154cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
1164cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    @Option(names = { "--run-tag" })
1174cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private String runTag = null;
1184cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
1194cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    @Option(names = { "--tag-overwrite" })
1204cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com    private boolean tagOverwrite = false;
1214cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
1223dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com    @Option(names = { "--suggest-classpaths" })
1233dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com    private boolean suggestClasspaths = false;
1243dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com
125d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Vogar() {}
126d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
127d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private void printUsage() {
128fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com        // have to reset fields so that "Default is: FOO" lines are accurate
129fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com        optionParser.reset();
130fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com
131d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("Usage: Vogar [options]... <actions>... [-- target args]...");
132d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
133d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  <actions>: .java files, directories, or class names.");
134d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      These should be JUnit tests, jtreg tests, Caliper benchmarks");
135d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      or executable Java classes.");
136d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
13772c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        System.out.println("      When passing in a JUnit test class, it may have \"#method_name\"");
13872c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        System.out.println("      appended to it, to specify a single test method.");
13972c9585a2c7535a2a847b8c316d28d875582dc09jsharpe@google.com        System.out.println();
140d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  [args]: arguments passed to the target process. This is only useful when");
141d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      the target process is a Caliper benchmark or main method.");
142d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
143d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("GENERAL OPTIONS");
144d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
145d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --mode <activity|device|sim|host>: specify which environment to run in.");
146d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      activity: runs in an Android application on a device or emulator");
147d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      device: runs in a Dalvik VM on a device or emulator");
148d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      sim: runs in a Dalvik VM on the local desktop.");
149d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      host: runs in a Java VM on the local desktop");
150d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + mode);
151d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
152d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean: synonym for --clean-before and --clean-after (default).");
153d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Disable with --no-clean if you want no files removed.");
154d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
155d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --stream: stream output as it is emitted.");
156d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
157d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --timeout <seconds>: maximum execution time of each action before the");
158d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      runner aborts it. Specifying zero seconds or using --debug will");
1598c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        System.out.println("      disable the execution timeout. Tests tagged with 'large' will time");
1608c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        System.out.println("      out in " + LARGE_TIMEOUT_MULTIPLIER + "x this timeout.");
161d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + timeoutSeconds);
162d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
163d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --xml-reports-directory <path>: directory to emit JUnit-style");
164d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      XML test results.");
165d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
166d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --classpath <jar file>: add the .jar to both build and execute classpaths.");
167d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
168ba0670d6c4481a866ae558d4e31f8004c709dd77jessewilson@google.com        System.out.println("  --use-bootclasspath: use the classpath as search path for bootstrap classes.");
169d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
170d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --build-classpath <element>: add the directory or .jar to the build");
171d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      classpath. Such classes are available as build dependencies, but");
172d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      not at runtime.");
173d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
174d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --sourcepath <directory>: add the directory to the build sourcepath.");
175d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
1764cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --tag-dir <directory>: directory in which to find tags.");
1774cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      Default is: " + tagDir);
1784cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
1794cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --tag <tag name>: creates a tag recording the arguments to this");
1804cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      invocation of Vogar so that it can be rerun later.");
1814cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
1824cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --run-tag <tag name>: runs Vogar with arguments as specified by the");
1834cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      tag. Any arguments supplied for this run will override those");
1844cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      supplied by the tag.");
1854cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
1864cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("  --tag-overwrite: allow --tag to overwrite an existing tag.");
1874cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println();
188d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --verbose: turn on persistent verbose output.");
189d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
190d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("TARGET OPTIONS");
191d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
192d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --debug <port>: enable Java debugging on the specified port.");
193d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      This port must be free both on the device and on the local");
194d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      system. Disables the timeout specified by --timeout-seconds.");
195d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
196d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --device-runner-dir <directory>: use the specified directory for");
197d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      on-device temporary files and code.");
198d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + deviceRunnerDir);
199d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
200d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --vm-arg <argument>: include the specified argument when spawning a");
201d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      virtual machine. Examples: -Xint:fast, -ea, -Xmx16M");
202d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
203d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --java-home <java_home>: execute the actions on the local workstation");
204d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      using the specified java home directory. This does not impact");
205d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      which javac gets used. When unset, java is used from the PATH.");
206d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
207d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("EXOTIC OPTIONS");
208d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
2092c67cf17be7262353493480d98fb88ad0f8fc320jsharpe@google.com        System.out.println("  --device-cache: keep copies of dexed files on the SD card so they");
21041a680807eb80e63fbfe42c218c9e1da6615d867jsharpe@google.com        System.out.println("      don't need to be pushed each time a test is run, improving");
2112c67cf17be7262353493480d98fb88ad0f8fc320jsharpe@google.com        System.out.println("      start times (default). Only affects device mode. Disable with");
2124cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        System.out.println("      --no-device-cache to save space on the SD card.");
21341a680807eb80e63fbfe42c218c9e1da6615d867jsharpe@google.com        System.out.println();
2143dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("  --suggest-classpaths: build an index of jar files under the");
2153dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("      directories given in VOGAR_JAR_PATH (a colon separated");
2163dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("      environment variable). If Vogar then fails due to missing");
2173dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("      classes or packages, it will use the index to diagnose the");
2183dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("      problem and suggest a fix.");
2193dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println();
2203dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("      Currently only looks for jars called exactly \"classes.jar\".");
2213dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println();
222d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean-before: remove working directories before building and");
223d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      running (default). Disable with --no-clean-before if you are");
224d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      using interactively with your own temporary input files.");
225d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
226d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean-after: remove temporary files after running (default).");
227d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Disable with --no-clean-after and use with --verbose if");
228d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      you'd like to manually re-run commands afterwards.");
229d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
230d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --color: format output in technicolor.");
231d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
232d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --expectations <file>: include the specified file when looking for");
233d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      action expectations. The file should include qualified action names");
234d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      and the corresponding expected output.");
235d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + expectationFiles);
236d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
2373dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        System.out.println("  --indent: amount to indent action result output. Can be set to ''");
238d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      (aka empty string) to simplify output parsing.");
239d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: '" + indent + "'");
240d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
241d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --javac-arg <argument>: include the specified argument when invoking");
242d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      javac. Examples: --javac-arg -Xmaxerrs --javac-arg 1");
243d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
244d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --monitor-timeout <seconds>: number of seconds to wait for the target");
245d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      process to launch. This can be used to prevent connection failures");
246d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      when dexopt is slow.");
247d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
248d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
249d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
250d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean parseArgs(String[] args) {
251d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        List<String> actionsAndTargetArgs;
252d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        try {
2534cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            actionsAndTargetArgs = optionParser.parse(args);
254d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } catch (RuntimeException e) {
255d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println(e.getMessage());
256d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
257d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
258d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
2594cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        if (runTag != null && tagName != null) {
2604cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            System.out.println("Cannot use both --run-tag and --tag options");
2614cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            return false;
2624cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        }
2634cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
2644cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        if (runTag != null) {
2654cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            String oldTag = tagName;
2664cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            String[] runTagArgs;
2674cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            try {
2684cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                runTagArgs = new Tag(tagDir, runTag, false).getArgs();
2694cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                System.out.println("Executing Vogar with additional arguments from tag \""
2704cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                        + runTag + "\":");
2714cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                System.out.println(Strings.join(runTagArgs, " "));
2724cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            } catch (FileNotFoundException e) {
273fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com                System.out.println("Tag \"" + runTag + "\" doesn't exist");
274fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com                System.out.println("Existing tags are: "
275fc358e65b59087a1fe4e17ff64e23eaf2922b72ejsharpe@google.com                        + Strings.join(Tag.getAllTags(tagDir), ", "));
2764cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                return false;
2774cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            }
2784cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // rollback changes already made by the optionParser
2794cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            optionParser.reset();
2804cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // runTags options are applied first so that the current command's arguments win if
2814cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // there is a conflict
2824cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            actionsAndTargetArgs = optionParser.parse(runTagArgs);
2834cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            // tag is the only argument we don't allow to be supplied by the run tag
2844cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            tagName = oldTag;
2854cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            actionsAndTargetArgs.addAll(optionParser.parse(args));
2864cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        }
2874cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
288d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
289d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // Semantic error validation
290d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
291d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
292d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (javaHome != null && !new File(javaHome, "/bin/java").exists()) {
293d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Invalid java home: " + javaHome);
294d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
295d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
2967850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
297d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // check vm option consistency
298595d8fd07fcad6d6661466b4b22905e5e82eb857jessewilson@google.com        if (!mode.acceptsVmArgs() && !vmArgs.isEmpty()) {
299d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("VM args " + vmArgs + " should not be specified for mode " + mode);
300d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
301d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
302d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
303d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (xmlReportsDirectory != null && !xmlReportsDirectory.isDirectory()) {
304d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Invalid XML reports directory: " + xmlReportsDirectory);
305d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
306d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
307d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
308d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (!clean) {
309d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            cleanBefore = false;
310d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            cleanAfter = false;
311d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
3127850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
313d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
314d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // Post-processing arguments
315d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
316d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
317d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // disable timeout when debugging
318d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (debugPort != null) {
319d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            timeoutSeconds = 0;
320d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
321d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
322d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // separate the actions and the target args
323d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        int index = 0;
324d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        for (; index < actionsAndTargetArgs.size(); index++) {
325d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            String arg = actionsAndTargetArgs.get(index);
326d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            if (arg.equals("--")) {
327d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                index++;
328d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                break;
3297850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
3307850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
331d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            File file = new File(arg);
332d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            if (file.exists()) {
333d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                if (arg.endsWith(".java") || file.isDirectory()) {
334995a215ce56a98ed522888b0fdc286cd612c0218jessewilson@google.com                    actionFiles.add(file.getAbsoluteFile());
335d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                } else {
336d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                    System.out.println("Expected a .jar file, .java file, directory, "
337d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                            + "package name or classname, but was: " + arg);
338d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                    return false;
339d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                }
340d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            } else {
341d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                actionClassesAndPackages.add(arg);
3427850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
343d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
344d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
345d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        targetArgs.addAll(actionsAndTargetArgs.subList(index, actionsAndTargetArgs.size()));
3467850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
347d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (actionFiles.isEmpty() && actionClassesAndPackages.isEmpty()) {
348d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("No actions provided.");
349d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
3507850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
3517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
352595d8fd07fcad6d6661466b4b22905e5e82eb857jessewilson@google.com        if (!mode.acceptsVmArgs() && !targetArgs.isEmpty()) {
353d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Target args " + targetArgs + " should not be specified for mode " + mode);
354d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
355d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
3567850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3574cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        if (tagName != null) {
3584cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            Tag tagToSave = new Tag(tagDir, tagName, tagOverwrite);
3594cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            try {
3604cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                tagToSave.saveArgs(args);
3614cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            } catch (FileNotFoundException e) {
3624cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                System.out.println(e.getMessage());
3634cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com                return false;
3644cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com            }
3654cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com        }
3664cb68042e7513b3f9444a17d91eb0d92480a74b4jsharpe@google.com
367d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        return true;
368d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
3697850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3707850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    private void run() {
371d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setColor(color);
372d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setIndent(indent);
373d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setStream(stream);
374d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setVerbose(verbose);
375d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
3763dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        ClassFileIndex classFileIndex = new ClassFileIndex();
3773dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        if (suggestClasspaths) {
3783dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com            classFileIndex.createIndex();
3793dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com        }
3803dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com
381d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        int monitorPort = mode.isHost() ? 8788 : 8787;
382d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Mode.Options modeOptions = new Mode.Options(Classpath.of(buildClasspath), sourcepath,
383d296ba8af13d367b4a701ddeba405ee51caa05c1enh@google.com                javacArgs, javaHome, monitorPort, timeoutSeconds, useBootClasspath, Classpath.of(classpath));
384d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
385d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        AndroidSdk androidSdk = null;
386d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (mode.requiresAndroidSdk()) {
387d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            androidSdk = AndroidSdk.getFromPath();
38841a680807eb80e63fbfe42c218c9e1da6615d867jsharpe@google.com            androidSdk.setDeviceCache(deviceCache);
389d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            modeOptions.buildClasspath.addAll(androidSdk.getAndroidClasses());
390d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
391d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
392d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        File localTemp = new File("/tmp/vogar/" + UUID.randomUUID());
393d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Environment environment = mode.isHost()
394d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                ? new EnvironmentHost(cleanBefore, cleanAfter, debugPort, localTemp)
395d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                : new EnvironmentDevice(cleanBefore, cleanAfter, debugPort, monitorPort, localTemp,
396d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                        deviceRunnerDir, androidSdk);
397d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
398d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Vm.Options vmOptions = (mode.acceptsVmArgs())
399d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                ? new Vm.Options(vmArgs, targetArgs)
400d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                : null;
401957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com
4027850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Mode mode;
403d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (this.mode == ModeId.HOST) {
404d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            mode = new JavaVm(environment, modeOptions, vmOptions);
405d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } else if (this.mode == ModeId.SIM) {
406d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            mode = new HostDalvikVm(environment, modeOptions, vmOptions, androidSdk);
407d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } else if (this.mode == ModeId.DEVICE) {
408d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            mode = new DeviceDalvikVm(environment, modeOptions, vmOptions);
409d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } else if (this.mode == ModeId.ACTIVITY) {
410d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            mode = new ActivityMode(environment, modeOptions);
4117850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        } else {
412d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            throw new AssertionError();
4137850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
4147850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
415d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        HostMonitor monitor = new HostMonitor(monitorTimeout);
4167850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
4177850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        ExpectationStore expectationStore;
4187850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        try {
419d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            expectationStore = ExpectationStore.parse(expectationFiles);
4207850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        } catch (IOException e) {
4217850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("Problem loading expectations: " + e);
4227850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return;
4237850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
4247850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
425d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        XmlReportPrinter xmlReportPrinter = xmlReportsDirectory != null
426d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                ? new XmlReportPrinter(xmlReportsDirectory, expectationStore)
4277850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                : null;
4287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
4298c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com        int smallTimeoutSeconds = timeoutSeconds;
4307850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Driver driver = new Driver(
4317850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                localTemp,
4327850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                mode,
4337850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                expectationStore,
4347850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                xmlReportPrinter,
4357850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                monitor,
4367850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                monitorPort,
4378c03f5a6370cf6521384a268e12808e163ae4339jessewilson@google.com                smallTimeoutSeconds,
4383dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com                smallTimeoutSeconds * LARGE_TIMEOUT_MULTIPLIER,
4393dafbce3b8d025f465ebf0a4c6d018c7dc31654ejsharpe@google.com                classFileIndex);
4407850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
441d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        driver.buildAndRun(actionFiles, actionClassesAndPackages);
4427850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
4437850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
4447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    public static void main(String[] args) {
4457850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Vogar vogar = new Vogar();
446d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (!vogar.parseArgs(args)) {
447d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            vogar.printUsage();
4487850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return;
4497850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
4507850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        vogar.run();
4517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
452d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
453d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    enum ModeId {
454d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        DEVICE, HOST, ACTIVITY, SIM;
455d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
456d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        public boolean acceptsVmArgs() {
457d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return this != ACTIVITY;
458d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
459d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
460d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        public boolean isHost() {
461d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return this == ModeId.HOST || this == ModeId.SIM;
462d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
463d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
464d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        public boolean requiresAndroidSdk() {
465d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return this == DEVICE || this == ACTIVITY || this == SIM;
466d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
467d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
4687850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com}
469