Vogar.java revision 957bd524afd6837b003e9e9b82745ebc42d20ba0
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;
207850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.io.IOException;
217850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.ArrayList;
227850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.comimport java.util.Arrays;
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
347850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    private static class Options {
357850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
367850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private final List<File> actionFiles = new ArrayList<File>();
37400bee347dd7464ecc17dc24c82f59c59645ff44jessewilson@google.com        private final List<String> actionClassesAndPackages = new ArrayList<String>();
387850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private final List<String> targetArgs = new ArrayList<String>();
397850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
407850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--expectations" })
417850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private Set<File> expectationFiles = new LinkedHashSet<File>();
427850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        {
437850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            File[] files = new File("expectations").listFiles();
447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            if (files != null) {
457850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                expectationFiles.addAll(Arrays.asList(files));
467850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
477850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
487850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
497850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private static String MODE_DEVICE = "device";
507850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private static String MODE_HOST = "host";
517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private static String MODE_ACTIVITY = "activity";
527850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--mode" })
537850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private String mode = MODE_DEVICE;
547850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
557850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--timeout" })
567850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private long timeoutSeconds = 10 * 60; // default is ten minutes;
577850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
587850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--monitor-timeout" })
594a5aa9cf66d7e545f9fc5af176aac19938d85d4benh@google.com        private long monitorTimeout = 30;
607850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
617850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--clean-before" })
627850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private boolean cleanBefore = true;
637850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
647850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--clean-after" })
657850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private boolean cleanAfter = true;
667850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
677850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--clean" })
687850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private boolean clean = true;
697850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
707850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--xml-reports-directory" })
717850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private File xmlReportsDirectory;
727850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
737850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--indent" })
747850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private String indent = "  ";
757850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
767850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--verbose" })
777850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private boolean verbose;
787850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
797850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--stream" })
80561cf99ef23475ea2acff7c7d327ec322f139945enh@google.com        private boolean stream = true;
817850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
827850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--color" })
837850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private boolean color = true;
847850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
857850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--debug" })
867850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private Integer debugPort;
877850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
887850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--device-runner-dir" })
897850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private File deviceRunnerDir = new File("/sdcard/dalvikrunner");
907850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
917850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--vm-arg" })
927850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private List<String> vmArgs = new ArrayList<String>();
937850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
947850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--java-home" })
957850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private File javaHome;
967850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
977850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        @Option(names = { "--javac-arg" })
987850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private List<String> javacArgs = new ArrayList<String>();
997850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
100e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com        @Option(names = { "--build-classpath" })
101e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com        private List<File> buildClasspath = new ArrayList<File>();
1027850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
1032cf7c92695b084132cc262e4b7d8665a934e0f1bjessewilson@google.com        @Option(names = { "--classpath", "-cp" })
1042cf7c92695b084132cc262e4b7d8665a934e0f1bjessewilson@google.com        private List<File> classpath = new ArrayList<File>();
1052cf7c92695b084132cc262e4b7d8665a934e0f1bjessewilson@google.com
10687586e43e5f3315f7860330fbb1fa4d9ca910fdebdc@google.com        @Option(names = { "--sourcepath" })
10787586e43e5f3315f7860330fbb1fa4d9ca910fdebdc@google.com        private List<File> sourcepath = new ArrayList<File>();
10887586e43e5f3315f7860330fbb1fa4d9ca910fdebdc@google.com
1097850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private void printUsage() {
1102096505862236687504bedd70bd5cbde274f243bbdc@google.com            System.out.println("Usage: Vogar [options]... <actions>... [-- target args]...");
1117850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1122cf7c92695b084132cc262e4b7d8665a934e0f1bjessewilson@google.com            System.out.println("  <actions>: .java files, directories, or class names.");
1137850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      These should be JUnit tests, jtreg tests, Caliper benchmarks");
1147850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      or executable Java classes.");
1157850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1167850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  [args]: arguments passed to the target process. This is only useful when");
1177850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      the target process is a Caliper benchmark or main method.");
1187850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1197850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("GENERAL OPTIONS");
1207850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1217850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --mode <device|host|activity>: specify which environment to run the");
1227850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      actions in. Options are on the device VM, on the host VM, and on");
1237850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      device within an android.app.Activity.");
1247850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      Default is: " + mode);
1257850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1267850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --clean: synonym for --clean-before and --clean-after (default).");
1277850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      Disable with --no-clean if you want no files removed.");
1287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1297850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --stream: stream output as it is emitted.");
1307850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1317850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --timeout <seconds>: maximum execution time of each action before the");
1327850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      runner aborts it. Specifying zero seconds or using --debug will");
1337850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      disable the execution timeout.");
1347850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      Default is: " + timeoutSeconds);
1357850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1367850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --xml-reports-directory <path>: directory to emit JUnit-style");
1377850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      XML test results.");
1387850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1392cf7c92695b084132cc262e4b7d8665a934e0f1bjessewilson@google.com            System.out.println("  --classpath <jar file>: add the .jar to both build and execute classpaths.");
1402cf7c92695b084132cc262e4b7d8665a934e0f1bjessewilson@google.com            System.out.println();
141e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com            System.out.println("  --build-classpath <element>: add the directory or .jar to the build");
142e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com            System.out.println("      classpath. Such classes are available as build dependencies, but");
143e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com            System.out.println("      not at runtime.");
1447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
14587586e43e5f3315f7860330fbb1fa4d9ca910fdebdc@google.com            System.out.println("  --sourcepath <directory>: add the directory to the build sourcepath.");
14687586e43e5f3315f7860330fbb1fa4d9ca910fdebdc@google.com            System.out.println();
14788b369c017a9eeee0f074ff4be8506b8952c76e0elliott.n.hughes@gmail.com            System.out.println("  --verbose: turn on persistent verbose output.");
1487850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1497850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("TARGET OPTIONS");
1507850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --debug <port>: enable Java debugging on the specified port.");
1527850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      This port must be free both on the device and on the local");
1537850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      system. Disables the timeout specified by --timeout-seconds.");
1547850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1557850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --device-runner-dir <directory>: use the specified directory for");
1567850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      on-device temporary files and code.");
1577850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      Default is: " + deviceRunnerDir);
1587850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1597850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --vm-arg <argument>: include the specified argument when spawning a");
1607850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      virtual machine. Examples: -Xint:fast, -ea, -Xmx16M");
1617850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1627850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --java-home <java_home>: execute the actions on the local workstation");
1637850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      using the specified java home directory. This does not impact");
1647850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      which javac gets used. When unset, java is used from the PATH.");
1657850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1667850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("EXOTIC OPTIONS");
1677850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1687850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --clean-before: remove working directories before building and");
1697850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      running (default). Disable with --no-clean-before if you are");
1707850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      using interactively with your own temporary input files.");
1717850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1727850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --clean-after: remove temporary files after running (default).");
1737850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      Disable with --no-clean-after and use with --verbose if");
1747850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      you'd like to manually re-run commands afterwards.");
1757850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1767850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --color: format output in technicolor.");
1777850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1787850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --expectations <file>: include the specified file when looking for");
1797850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      action expectations. The file should include qualified action names");
1807850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      and the corresponding expected output.");
1817850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      Default is: " + expectationFiles);
1827850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1837850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --ident: amount to indent action result output. Can be set to ''");
1847850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      (aka empty string) to simplify output parsing.");
1857850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      Default is: '" + indent + "'");
1867850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1877850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --javac-arg <argument>: include the specified argument when invoking");
1887850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      javac. Examples: --javac-arg -Xmaxerrs --javac-arg 1");
1897850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1907850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("  --monitor-timeout <seconds>: number of seconds to wait for the target");
1917850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      process to launch. This can be used to prevent connection failures");
1927850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("      when dexopt is slow.");
1937850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println();
1947850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
1957850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
1967850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        private boolean parseArgs(String[] args) {
1977850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            List<String> actionsAndTargetArgs;
1987850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            try {
1997850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                actionsAndTargetArgs = new OptionParser(this).parse(args);
2007850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            } catch (RuntimeException e) {
2017850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                System.out.println(e.getMessage());
2027850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                return false;
2037850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2047850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2057850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            //
2067850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            // Semantic error validation
2077850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            //
2087850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2097850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            boolean device;
2107850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            boolean vm;
2117850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            if (mode.equals(MODE_DEVICE)) {
2127850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                device = true;
2137850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                vm = true;
2147850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            } else if (mode.equals(MODE_HOST)) {
2157850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                device = false;
2167850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                vm = true;
2177850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            } else if (mode.equals(MODE_ACTIVITY)) {
2187850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                device = true;
2197850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                vm = false;
2207850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            } else {
2217850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                System.out.println("Unknown mode: " + mode);
2227850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                return false;
2237850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2247850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2257850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
226957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com            if (javaHome != null && !new File(javaHome, "/bin/java").exists()) {
227957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                System.out.println("Invalid java home: " + javaHome);
228957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                return false;
2297850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2307850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2317850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            // check vm option consistency
2327850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            if (!vm) {
2337850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                if (!vmArgs.isEmpty()) {
2347850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                    System.out.println("vm args " + vmArgs + " should not be specified for mode " + mode);
2357850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                    return false;
2367850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                }
2377850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2387850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2397850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            if (xmlReportsDirectory != null && !xmlReportsDirectory.isDirectory()) {
2407850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                System.out.println("Invalid XML reports directory: " + xmlReportsDirectory);
2417850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                return false;
2427850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2437850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            if (!clean) {
2457850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                cleanBefore = false;
2467850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                cleanAfter = false;
2477850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2487850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2497850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            //
2507850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            // Post-processing arguments
2517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            //
2527850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2537850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            // disable timeout when debugging
2547850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            if (debugPort != null) {
2557850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                timeoutSeconds = 0;
2567850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2577850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2587850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            // separate the actions and the target args
2597850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            int index = 0;
2607850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            for (; index < actionsAndTargetArgs.size(); index++) {
2617850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                String arg = actionsAndTargetArgs.get(index);
2627850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                if (arg.equals("--")) {
2637850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                    index++;
2647850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                    break;
2657850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                }
2667850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2677850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                File file = new File(arg);
2687850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                if (file.exists()) {
2692cf7c92695b084132cc262e4b7d8665a934e0f1bjessewilson@google.com                    if (arg.endsWith(".java") || file.isDirectory()) {
2707850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                        actionFiles.add(file);
271400bee347dd7464ecc17dc24c82f59c59645ff44jessewilson@google.com                    } else {
2722096505862236687504bedd70bd5cbde274f243bbdc@google.com                        System.out.println("Expected a .jar file, .java file, directory, "
273400bee347dd7464ecc17dc24c82f59c59645ff44jessewilson@google.com                                + "package name or classname, but was: " + arg);
274400bee347dd7464ecc17dc24c82f59c59645ff44jessewilson@google.com                        return false;
2757850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                    }
2767850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                } else {
2772cf7c92695b084132cc262e4b7d8665a934e0f1bjessewilson@google.com                    actionClassesAndPackages.add(arg);
2787850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                }
2797850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2807850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2817850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            targetArgs.addAll(actionsAndTargetArgs.subList(index, actionsAndTargetArgs.size()));
2827850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
283400bee347dd7464ecc17dc24c82f59c59645ff44jessewilson@google.com            if (actionFiles.isEmpty() && actionClassesAndPackages.isEmpty()) {
2847850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                System.out.println("No actions provided.");
2857850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                return false;
2867850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2877850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2887850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            if (!targetArgs.isEmpty() && mode.equals(Options.MODE_ACTIVITY)) {
2897850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                System.out.println("Target args not supported with --mode activity");
2907850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                return false;
2917850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2927850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2937850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return true;
2947850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
2957850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
2967850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2977850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    private final Options options = new Options();
2987850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    private final File localTemp = new File("/tmp/dalvikrunner/" + UUID.randomUUID());
2997850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3007850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    private Vogar() {}
3017850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3027850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    private void run() {
303027ca289d7c7b21501a9d14e69f10735033f57a0elliott.n.hughes@gmail.com        Console.getInstance().setColor(options.color);
30488b369c017a9eeee0f074ff4be8506b8952c76e0elliott.n.hughes@gmail.com        Console.getInstance().setIndent(options.indent);
30588b369c017a9eeee0f074ff4be8506b8952c76e0elliott.n.hughes@gmail.com        Console.getInstance().setStream(options.stream);
30688b369c017a9eeee0f074ff4be8506b8952c76e0elliott.n.hughes@gmail.com        Console.getInstance().setVerbose(options.verbose);
3077850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
308957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com        boolean hostMode = options.mode.equals(Options.MODE_HOST);
309957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com        int monitorPort = (hostMode) ? 8788 : 8787;
310957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com        Mode.Options modeOptions = new Mode.Options(Classpath.of(options.buildClasspath),
311957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                    options.sourcepath,
312957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                    options.javacArgs,
313957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                    options.javaHome,
314957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                    monitorPort,
315957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                    Classpath.of(options.classpath));
316957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com
317957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com        boolean vmMode = hostMode || options.mode.equals(Options.MODE_DEVICE);
318957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com        Vm.Options vmOptions = (vmMode) ? new Vm.Options(options.vmArgs, options.targetArgs) : null;
319957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com
3207850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Mode mode;
321957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com        if (hostMode) {
322957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com            mode = new JavaVm(new EnvironmentHost(options.cleanBefore,
323957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                  options.cleanAfter,
324957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                  options.debugPort,
325957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                  localTemp),
326957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                              modeOptions,
327957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                              vmOptions);
3287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        } else {
329e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com            AndroidSdk androidSdk = AndroidSdk.getFromPath();
330957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com            modeOptions.buildClasspath.addAll(androidSdk.getAndroidClasses());
331957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com
332957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com            EnvironmentDevice environment = new EnvironmentDevice(options.cleanBefore,
333957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                                  options.cleanAfter,
334957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                                  options.debugPort,
335957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                                  monitorPort,
336957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                                  localTemp,
337957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                                  options.deviceRunnerDir,
338957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                                                                  androidSdk);
339957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com            if (vmMode) {
340957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                mode = new DeviceDalvikVm(environment, modeOptions, vmOptions);
341e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com            } else if (options.mode.equals(Options.MODE_ACTIVITY)) {
342957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com                mode = new ActivityMode(environment, modeOptions);
343e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com            } else {
344e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com                System.out.println("Unknown mode mode " + options.mode + ".");
345e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com                return;
346e956c912fdab19b9cc806b47288048fca9121546jessewilson@google.com            }
3477850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
3487850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3497850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        HostMonitor monitor = new HostMonitor(options.monitorTimeout);
3507850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        List<RunnerSpec> runnerSpecs = Arrays.asList(
3527850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                new JtregSpec(localTemp),
3537850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                new JUnitSpec(),
3547850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                new CaliperSpec(),
3557850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                new MainSpec());
3567850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3577850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        ExpectationStore expectationStore;
3587850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        try {
3597850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            expectationStore = ExpectationStore.parse(options.expectationFiles);
3607850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        } catch (IOException e) {
3617850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("Problem loading expectations: " + e);
3627850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return;
3637850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
3647850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3657850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        XmlReportPrinter xmlReportPrinter = options.xmlReportsDirectory != null
3667850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                ? new XmlReportPrinter(options.xmlReportsDirectory, expectationStore)
3677850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                : null;
3687850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3697850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Driver driver = new Driver(
3707850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                localTemp,
3717850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                mode,
3727850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                expectationStore,
3737850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                runnerSpecs,
3747850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                xmlReportPrinter,
3757850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                monitor,
3767850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                monitorPort,
3777850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                options.timeoutSeconds);
3787850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
379400bee347dd7464ecc17dc24c82f59c59645ff44jessewilson@google.com        driver.buildAndRun(options.actionFiles, options.actionClassesAndPackages);
3807850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
3817850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3827850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    public static void main(String[] args) {
3837850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Vogar vogar = new Vogar();
3847850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        if (!vogar.options.parseArgs(args)) {
3857850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            vogar.options.printUsage();
3867850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return;
3877850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
3887850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        vogar.run();
3897850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
3907850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com}
391