Vogar.java revision d0944e3ecda89a97ac35537e280b2776b53c25ec
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
34d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<File> actionFiles = new ArrayList<File>();
35d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<String> actionClassesAndPackages = new ArrayList<String>();
36d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private final List<String> targetArgs = new ArrayList<String>();
37d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
38d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--expectations" })
39d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Set<File> expectationFiles = new LinkedHashSet<File>();
40d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    {
41d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        File[] files = new File("expectations").listFiles();
42d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (files != null) {
43d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            expectationFiles.addAll(Arrays.asList(files));
447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
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" })
51d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private long timeoutSeconds = 10 * 60; // default is ten minutes;
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" })
84d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private File deviceRunnerDir = new File("/sdcard/dalvikrunner");
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
95d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    @Option(names = { "--use-boot-classpath" })
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
107d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private Vogar() {}
108d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
109d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private void printUsage() {
110d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("Usage: Vogar [options]... <actions>... [-- target args]...");
111d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
112d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  <actions>: .java files, directories, or class names.");
113d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      These should be JUnit tests, jtreg tests, Caliper benchmarks");
114d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      or executable Java classes.");
115d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
116d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  [args]: arguments passed to the target process. This is only useful when");
117d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      the target process is a Caliper benchmark or main method.");
118d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
119d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("GENERAL OPTIONS");
120d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
121d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --mode <activity|device|sim|host>: specify which environment to run in.");
122d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      activity: runs in an Android application on a device or emulator");
123d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      device: runs in a Dalvik VM on a device or emulator");
124d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      sim: runs in a Dalvik VM on the local desktop.");
125d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      host: runs in a Java VM on the local desktop");
126d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + mode);
127d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
128d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean: synonym for --clean-before and --clean-after (default).");
129d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Disable with --no-clean if you want no files removed.");
130d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
131d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --stream: stream output as it is emitted.");
132d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
133d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --timeout <seconds>: maximum execution time of each action before the");
134d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      runner aborts it. Specifying zero seconds or using --debug will");
135d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      disable the execution timeout.");
136d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + timeoutSeconds);
137d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
138d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --xml-reports-directory <path>: directory to emit JUnit-style");
139d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      XML test results.");
140d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
141d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --classpath <jar file>: add the .jar to both build and execute classpaths.");
142d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
143d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --use-boot-classpath: use the classpath as search path for bootstrap classes.");
144d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
145d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --build-classpath <element>: add the directory or .jar to the build");
146d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      classpath. Such classes are available as build dependencies, but");
147d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      not at runtime.");
148d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
149d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --sourcepath <directory>: add the directory to the build sourcepath.");
150d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
151d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --verbose: turn on persistent verbose output.");
152d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
153d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("TARGET OPTIONS");
154d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
155d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --debug <port>: enable Java debugging on the specified port.");
156d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      This port must be free both on the device and on the local");
157d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      system. Disables the timeout specified by --timeout-seconds.");
158d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
159d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --device-runner-dir <directory>: use the specified directory for");
160d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      on-device temporary files and code.");
161d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + deviceRunnerDir);
162d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
163d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --vm-arg <argument>: include the specified argument when spawning a");
164d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      virtual machine. Examples: -Xint:fast, -ea, -Xmx16M");
165d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
166d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --java-home <java_home>: execute the actions on the local workstation");
167d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      using the specified java home directory. This does not impact");
168d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      which javac gets used. When unset, java is used from the PATH.");
169d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
170d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("EXOTIC OPTIONS");
171d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
172d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean-before: remove working directories before building and");
173d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      running (default). Disable with --no-clean-before if you are");
174d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      using interactively with your own temporary input files.");
175d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
176d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --clean-after: remove temporary files after running (default).");
177d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Disable with --no-clean-after and use with --verbose if");
178d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      you'd like to manually re-run commands afterwards.");
179d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
180d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --color: format output in technicolor.");
181d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
182d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --expectations <file>: include the specified file when looking for");
183d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      action expectations. The file should include qualified action names");
184d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      and the corresponding expected output.");
185d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: " + expectationFiles);
186d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
187d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --ident: amount to indent action result output. Can be set to ''");
188d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      (aka empty string) to simplify output parsing.");
189d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      Default is: '" + indent + "'");
190d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
191d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --javac-arg <argument>: include the specified argument when invoking");
192d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      javac. Examples: --javac-arg -Xmaxerrs --javac-arg 1");
193d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
194d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("  --monitor-timeout <seconds>: number of seconds to wait for the target");
195d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      process to launch. This can be used to prevent connection failures");
196d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println("      when dexopt is slow.");
197d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        System.out.println();
198d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
199d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
200d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    private boolean parseArgs(String[] args) {
201d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        List<String> actionsAndTargetArgs;
202d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        try {
203d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            actionsAndTargetArgs = new OptionParser(this).parse(args);
204d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } catch (RuntimeException e) {
205d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println(e.getMessage());
206d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
207d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
208d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
209d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
210d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // Semantic error validation
211d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
212d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
213d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (javaHome != null && !new File(javaHome, "/bin/java").exists()) {
214d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Invalid java home: " + javaHome);
215d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
216d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
2177850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
218d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // check vm option consistency
219d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (mode.acceptsVmArgs() && !vmArgs.isEmpty()) {
220d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("VM args " + vmArgs + " should not be specified for mode " + mode);
221d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
222d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
223d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
224d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (xmlReportsDirectory != null && !xmlReportsDirectory.isDirectory()) {
225d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Invalid XML reports directory: " + xmlReportsDirectory);
226d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
227d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
228d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
229d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (!clean) {
230d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            cleanBefore = false;
231d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            cleanAfter = false;
232d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
2337850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
234d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
235d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // Post-processing arguments
236d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        //
237d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
238d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // disable timeout when debugging
239d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (debugPort != null) {
240d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            timeoutSeconds = 0;
241d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
242d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
243d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        // separate the actions and the target args
244d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        int index = 0;
245d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        for (; index < actionsAndTargetArgs.size(); index++) {
246d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            String arg = actionsAndTargetArgs.get(index);
247d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            if (arg.equals("--")) {
248d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                index++;
249d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                break;
2507850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
2517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
252d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            File file = new File(arg);
253d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            if (file.exists()) {
254d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                if (arg.endsWith(".java") || file.isDirectory()) {
255d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                    actionFiles.add(file);
256d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                } else {
257d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                    System.out.println("Expected a .jar file, .java file, directory, "
258d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                            + "package name or classname, but was: " + arg);
259d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                    return false;
260d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                }
261d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            } else {
262d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                actionClassesAndPackages.add(arg);
2637850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            }
264d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
265d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
266d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        targetArgs.addAll(actionsAndTargetArgs.subList(index, actionsAndTargetArgs.size()));
2677850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
268d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (actionFiles.isEmpty() && actionClassesAndPackages.isEmpty()) {
269d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("No actions provided.");
270d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
2717850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
2727850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
273d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (mode.acceptsVmArgs() && !targetArgs.isEmpty()) {
274d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            System.out.println("Target args " + targetArgs + " should not be specified for mode " + mode);
275d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return false;
276d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
2777850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
278d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        return true;
279d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
2807850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
2817850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    private void run() {
282d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setColor(color);
283d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setIndent(indent);
284d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setStream(stream);
285d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Console.getInstance().setVerbose(verbose);
286d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
287d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        int monitorPort = mode.isHost() ? 8788 : 8787;
288d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Mode.Options modeOptions = new Mode.Options(Classpath.of(buildClasspath), sourcepath,
289d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                javacArgs, javaHome, monitorPort, useBootClasspath, Classpath.of(classpath));
290d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
291d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        AndroidSdk androidSdk = null;
292d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (mode.requiresAndroidSdk()) {
293d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            androidSdk = AndroidSdk.getFromPath();
294d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            modeOptions.buildClasspath.addAll(androidSdk.getAndroidClasses());
295d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
296d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
297d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        File localTemp = new File("/tmp/vogar/" + UUID.randomUUID());
298d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Environment environment = mode.isHost()
299d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                ? new EnvironmentHost(cleanBefore, cleanAfter, debugPort, localTemp)
300d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                : new EnvironmentDevice(cleanBefore, cleanAfter, debugPort, monitorPort, localTemp,
301d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                        deviceRunnerDir, androidSdk);
302d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
303d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        Vm.Options vmOptions = (mode.acceptsVmArgs())
304d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                ? new Vm.Options(vmArgs, targetArgs)
305d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                : null;
306957bd524afd6837b003e9e9b82745ebc42d20ba0bdc@google.com
3077850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Mode mode;
308d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (this.mode == ModeId.HOST) {
309d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            mode = new JavaVm(environment, modeOptions, vmOptions);
310d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } else if (this.mode == ModeId.SIM) {
311d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            mode = new HostDalvikVm(environment, modeOptions, vmOptions, androidSdk);
312d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } else if (this.mode == ModeId.DEVICE) {
313d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            mode = new DeviceDalvikVm(environment, modeOptions, vmOptions);
314d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        } else if (this.mode == ModeId.ACTIVITY) {
315d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            mode = new ActivityMode(environment, modeOptions);
3167850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        } else {
317d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            throw new AssertionError();
3187850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
3197850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
320d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        HostMonitor monitor = new HostMonitor(monitorTimeout);
3217850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3227850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        List<RunnerSpec> runnerSpecs = Arrays.asList(
3237850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                new JtregSpec(localTemp),
3247850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                new JUnitSpec(),
3257850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                new CaliperSpec(),
3267850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                new MainSpec());
3277850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3287850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        ExpectationStore expectationStore;
3297850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        try {
330d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            expectationStore = ExpectationStore.parse(expectationFiles);
3317850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        } catch (IOException e) {
3327850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            System.out.println("Problem loading expectations: " + e);
3337850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return;
3347850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
3357850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
336d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        XmlReportPrinter xmlReportPrinter = xmlReportsDirectory != null
337d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                ? new XmlReportPrinter(xmlReportsDirectory, expectationStore)
3387850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                : null;
3397850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3407850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Driver driver = new Driver(
3417850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                localTemp,
3427850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                mode,
3437850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                expectationStore,
3447850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                runnerSpecs,
3457850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                xmlReportPrinter,
3467850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                monitor,
3477850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com                monitorPort,
348d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com                timeoutSeconds);
3497850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
350d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        driver.buildAndRun(actionFiles, actionClassesAndPackages);
3517850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
3527850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com
3537850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    public static void main(String[] args) {
3547850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        Vogar vogar = new Vogar();
355d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        if (!vogar.parseArgs(args)) {
356d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            vogar.printUsage();
3577850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com            return;
3587850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        }
3597850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com        vogar.run();
3607850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com    }
361d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
362d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    enum ModeId {
363d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        DEVICE, HOST, ACTIVITY, SIM;
364d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
365d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        public boolean acceptsVmArgs() {
366d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return this != ACTIVITY;
367d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
368d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
369d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        public boolean isHost() {
370d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return this == ModeId.HOST || this == ModeId.SIM;
371d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
372d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com
373d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        public boolean requiresAndroidSdk() {
374d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com            return this == DEVICE || this == ACTIVITY || this == SIM;
375d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com        }
376d0944e3ecda89a97ac35537e280b2776b53c25ecjessewilson@google.com    }
3777850f3f3da0099b76f09ed64d23e0a43ba4a5c76jessewilson@google.com}
378