blob: ef20a47000fd41c66c7550b1a7287132f1759ad7 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package vogar;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import vogar.android.ActivityMode;
import vogar.android.AndroidSdk;
import vogar.android.DeviceRuntime;
import vogar.android.HostRuntime;
import vogar.commands.Mkdir;
import vogar.commands.Rm;
import vogar.tasks.TaskQueue;
import vogar.util.Strings;
public final class Run {
/**
* A list of generic names that we avoid when naming generated files.
*/
private static final Set<String> BANNED_NAMES = new HashSet<String>();
private static final String JAR_URI_PREFIX = "jar:file:";
private static final String FILE_URL_PREFIX = "file:";
private static final String VOGAR_CLASS_RESOURCE_PATH = "/vogar/Vogar.class";
static {
BANNED_NAMES.add("classes");
BANNED_NAMES.add("javalib");
}
public final File xmlReportsDirectory;
public final File resultsDir;
public final boolean recordResults;
public final ExpectationStore expectationStore;
public final Date date;
public final String invokeWith;
public final File keystore;
public final Log log;
public final Classpath classpath;
public final Classpath buildClasspath;
public final Classpath resourceClasspath;
public final List<File> sourcepath;
public final Mkdir mkdir;
public final Rm rm;
public final int firstMonitorPort;
public final int timeoutSeconds;
public final boolean profile;
public final boolean profileBinary;
public final int profileDepth;
public final int profileInterval;
public final boolean profileThreadGroup;
public final File profileFile;
public final File javaHome;
public final Integer debugPort;
public final Language language;
public final List<String> javacArgs;
public final List<String> jackArgs;
public final boolean multidex;
public final boolean benchmark;
public final File runnerDir;
public final boolean cleanBefore;
public final boolean cleanAfter;
public final File localTemp;
public final int maxConcurrentActions;
public final File deviceUserHome;
public final Console console;
public final int smallTimeoutSeconds;
public final String vmCommand;
public final String dalvikCache;
public final List<String> additionalVmArgs;
public final List<String> targetArgs;
public final boolean useBootClasspath;
public final int largeTimeoutSeconds;
public final RetrievedFilesFilter retrievedFiles;
public final Driver driver;
public final Mode mode;
public final Target target;
public final AndroidSdk androidSdk;
public final XmlReportPrinter reportPrinter;
public final JarSuggestions jarSuggestions;
public final ClassFileIndex classFileIndex;
public final OutcomeStore outcomeStore;
public final TaskQueue taskQueue;
public final RunnerType runnerType;
public final boolean useJack;
public final boolean checkJni;
public final boolean debugging;
public final Md5Cache jackCache;
public Run(Vogar vogar, boolean useJack, Console console, Mkdir mkdir, AndroidSdk androidSdk,
Rm rm, Target target, File runnerDir)
throws IOException {
this.console = console;
this.localTemp = new File("/tmp/vogar/" + UUID.randomUUID());
this.log = console;
this.target = target;
this.useJack = useJack;
this.jackCache = useJack ? new Md5Cache(log, "jack", new HostFileCache(log, mkdir)) : null;
this.vmCommand = vogar.vmCommand;
this.dalvikCache = vogar.dalvikCache;
this.additionalVmArgs = vogar.vmArgs;
this.benchmark = vogar.benchmark;
this.cleanBefore = vogar.cleanBefore;
this.cleanAfter = vogar.cleanAfter;
this.date = new Date();
this.debugPort = vogar.debugPort;
this.runnerDir = runnerDir;
this.deviceUserHome = new File(runnerDir, "user.home");
this.mkdir = mkdir;
this.rm = rm;
this.firstMonitorPort = vogar.firstMonitorPort;
this.invokeWith = vogar.invokeWith;
this.language = vogar.language;
this.javacArgs = vogar.javacArgs;
this.jackArgs = vogar.jackArgs;
this.multidex = vogar.multidex;
this.javaHome = vogar.javaHome;
this.largeTimeoutSeconds = vogar.timeoutSeconds * Vogar.LARGE_TIMEOUT_MULTIPLIER;
this.maxConcurrentActions = (vogar.stream || vogar.modeId == ModeId.ACTIVITY)
? 1
: Vogar.NUM_PROCESSORS;
this.timeoutSeconds = vogar.timeoutSeconds;
this.smallTimeoutSeconds = vogar.timeoutSeconds;
this.sourcepath = vogar.sourcepath;
this.resourceClasspath = Classpath.of(vogar.resourceClasspath);
this.useBootClasspath = vogar.useBootClasspath;
this.targetArgs = vogar.targetArgs;
this.xmlReportsDirectory = vogar.xmlReportsDirectory;
this.profile = vogar.profile;
this.profileBinary = vogar.profileBinary;
this.profileFile = vogar.profileFile;
this.profileDepth = vogar.profileDepth;
this.profileInterval = vogar.profileInterval;
this.profileThreadGroup = vogar.profileThreadGroup;
this.recordResults = vogar.recordResults;
this.resultsDir = vogar.resultsDir == null
? new File(vogar.vogarDir, "results")
: vogar.resultsDir;
this.keystore = localFile("activity", "vogar.keystore");
this.classpath = Classpath.of(vogar.classpath);
this.classpath.addAll(vogarJar());
this.runnerType = vogar.runnerType;
this.androidSdk = androidSdk;
expectationStore = ExpectationStore.parse(
console, vogar.expectationFiles, vogar.modeId, vogar.variant);
if (vogar.openBugsCommand != null) {
expectationStore.loadBugStatuses(new CommandBugDatabase(log, vogar.openBugsCommand));
}
this.mode = createMode(vogar.modeId, vogar.variant);
this.buildClasspath = Classpath.of(vogar.buildClasspath);
if (androidSdk != null) {
buildClasspath.addAll(androidSdk.getCompilationClasspath());
}
this.classFileIndex = new ClassFileIndex(log, mkdir, vogar.jarSearchDirs);
if (vogar.suggestClasspaths) {
classFileIndex.createIndex();
}
this.retrievedFiles = new RetrievedFilesFilter(profile, profileFile);
this.reportPrinter = new XmlReportPrinter(xmlReportsDirectory, expectationStore, date);
this.jarSuggestions = new JarSuggestions();
this.outcomeStore = new OutcomeStore(log, mkdir, rm, resultsDir, recordResults,
expectationStore, date);
this.driver = new Driver(this);
this.taskQueue = new TaskQueue(console, maxConcurrentActions);
this.checkJni = vogar.checkJni;
this.debugging = (vogar.debugPort != null) || vogar.debugApp;
}
private Mode createMode(ModeId modeId, Variant variant) {
switch (modeId) {
case JVM:
return new JavaVm(this);
case HOST:
return new HostRuntime(this, modeId, variant);
case DEVICE:
case APP_PROCESS:
return new DeviceRuntime(this, modeId, variant, new Supplier<String>() {
@Override
public String get() {
return target.getDeviceUserName();
}
});
case ACTIVITY:
return new ActivityMode(this);
default:
throw new IllegalArgumentException("Unsupported mode: " + modeId);
}
}
public final File localFile(Object... path) {
return new File(localTemp + "/" + Strings.join("/", path));
}
private File vogarJar() {
URL jarUrl = Vogar.class.getResource(VOGAR_CLASS_RESOURCE_PATH);
if (jarUrl == null) {
// should we add an option for IDE users, to use a user-specified vogar.jar?
throw new IllegalStateException("Vogar cannot find its own .jar");
}
/*
* Parse a URI like jar:file:/Users/jessewilson/vogar/vogar.jar!/vogar/Vogar.class
* to yield a .jar file like /Users/jessewilson/vogar/vogar.jar.
*/
String url = jarUrl.toString();
int bang = url.indexOf("!");
if (url.startsWith(JAR_URI_PREFIX) && bang != -1) {
return new File(url.substring(JAR_URI_PREFIX.length(), bang));
} else if (url.startsWith(FILE_URL_PREFIX) && url.endsWith(VOGAR_CLASS_RESOURCE_PATH)) {
// Vogar is being run from a classes directory.
return new File(url.substring(FILE_URL_PREFIX.length(),
url.length() - VOGAR_CLASS_RESOURCE_PATH.length()));
} else {
throw new IllegalStateException("Vogar cannot find the .jar file in " + jarUrl);
}
}
public final File hostJar(Object nameOrAction) {
return localFile(nameOrAction, nameOrAction + ".jar");
}
public File hostJack(Object nameOrAction) {
return localFile(nameOrAction, nameOrAction + ".jack");
}
/**
* Returns a path for a Java tool such as java, javac, jar where
* the Java home is used if present, otherwise assumes it will
* come from the path.
*/
public String javaPath(String tool) {
return (javaHome == null)
? tool
: new File(new File(javaHome, "bin"), tool).getPath();
}
public File targetDexFile(String name) {
return new File(runnerDir, name + ".dex.jar");
}
public File localDexFile(String name) {
return localFile(name, name + ".dex.jar");
}
/**
* Returns a recognizable readable name for the given generated .jar file,
* appropriate for use in naming derived files.
*
* @param file a product of the android build system, such as
* "out/core-libart_intermediates/javalib.jar".
* @return a recognizable base name like "core-libart_intermediates".
*/
public String basenameOfJar(File file) {
String name = file.getName().replaceAll("(\\.jar|\\.jack)$", "");
while (BANNED_NAMES.contains(name)) {
file = file.getParentFile();
name = file.getName();
}
return name;
}
public File vogarTemp() {
return new File(runnerDir, "tmp");
}
public File dalvikCache() {
return new File(runnerDir.getParentFile(), dalvikCache);
}
/**
* Returns the directory where the VM stores its dexopt files.
*/
public String getAndroidDataPath() {
// The VM wants the parent directory of a directory named "dalvik-cache"
return dalvikCache().getParentFile().getPath();
}
/**
* Returns a parsed list of the --invoke-with command and its
* arguments, or an empty list if no --invoke-with was provided.
*/
public Iterable<String> invokeWith() {
if (invokeWith == null) {
return Collections.emptyList();
}
return Splitter.onPattern("\\s+").omitEmptyStrings().split(invokeWith);
}
}