blob: 99f9a71ae430ee51c421f4a97262393adb1941c7 [file] [log] [blame]
// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
// Base class for the runtime structure in the test parameters.
public abstract class TestRuntime {
// Enum describing the possible/supported CF runtimes.
public enum CfVm {
JDK8("jdk8", 52),
JDK9("jdk9", 53),
JDK10("jdk10", 54),
JDK11("jdk11", 55),
;
private final String name;
private final int classfileVersion;
CfVm(String name, int classfileVersion) {
this.name = name;
this.classfileVersion = classfileVersion;
}
public int getClassfileVersion() {
return classfileVersion;
}
public static CfVm first() {
return JDK8;
}
public static CfVm last() {
return JDK11;
}
public boolean lessThan(CfVm other) {
return this.ordinal() < other.ordinal();
}
public boolean lessThanOrEqual(CfVm other) {
return this.ordinal() <= other.ordinal();
}
@Override
public String toString() {
return name;
}
}
private static final Path JDK8_PATH = Paths.get(ToolHelper.THIRD_PARTY_DIR, "openjdk", "jdk8");
private static final Path JDK9_PATH =
Paths.get(ToolHelper.THIRD_PARTY_DIR, "openjdk", "openjdk-9.0.4");
private static final Path JDK11_PATH = Paths.get(ToolHelper.THIRD_PARTY_DIR, "openjdk", "jdk-11");
public static CfRuntime getCheckedInJdk8() {
Path home;
if (ToolHelper.isLinux()) {
home = JDK8_PATH.resolve("linux-x86");
} else if (ToolHelper.isMac()) {
home = JDK8_PATH.resolve("darwin-x86");
} else {
assert ToolHelper.isWindows();
return null;
}
return new CfRuntime(CfVm.JDK8, home);
}
public static CfRuntime getCheckedInJdk9() {
Path home;
if (ToolHelper.isLinux()) {
home = JDK9_PATH.resolve("linux");
} else if (ToolHelper.isMac()) {
home = JDK9_PATH.resolve("osx");
} else {
assert ToolHelper.isWindows();
home = JDK9_PATH.resolve("windows");
}
return new CfRuntime(CfVm.JDK9, home);
}
public static CfRuntime getCheckedInJdk11() {
Path home;
if (ToolHelper.isLinux()) {
home = JDK11_PATH.resolve("Linux");
} else if (ToolHelper.isMac()) {
home = Paths.get(JDK11_PATH.toString(), "Mac", "Contents", "Home");
} else {
assert ToolHelper.isWindows();
home = JDK11_PATH.resolve("Windows");
}
return new CfRuntime(CfVm.JDK11, home);
}
public static List<CfRuntime> getCheckedInCfRuntimes() {
CfRuntime[] jdks =
new CfRuntime[] {getCheckedInJdk8(), getCheckedInJdk9(), getCheckedInJdk11()};
Builder<CfRuntime> builder = ImmutableList.builder();
for (CfRuntime jdk : jdks) {
if (jdk != null) {
builder.add(jdk);
}
}
return builder.build();
}
private static List<DexRuntime> getCheckedInDexRuntimes() {
if (ToolHelper.isLinux()) {
return ListUtils.map(Arrays.asList(DexVm.Version.values()), DexRuntime::new);
}
assert ToolHelper.isMac() || ToolHelper.isWindows();
return ImmutableList.of();
}
// For compatibility with old tests not specifying a Java runtime
@Deprecated
public static TestRuntime getDefaultJavaRuntime() {
return getCheckedInJdk9();
}
public static List<TestRuntime> getCheckedInRuntimes() {
return ImmutableList.<TestRuntime>builder()
.addAll(getCheckedInCfRuntimes())
.addAll(getCheckedInDexRuntimes())
.build();
}
public static TestRuntime getSystemRuntime() {
String version = System.getProperty("java.version");
String home = System.getProperty("java.home");
if (version == null || version.isEmpty() || home == null || home.isEmpty()) {
throw new Unimplemented("Unable to create a system runtime");
}
if (version.startsWith("1.8.")) {
return new CfRuntime(CfVm.JDK8, Paths.get(home));
}
if (version.startsWith("9.")) {
return new CfRuntime(CfVm.JDK9, Paths.get(home));
}
if (version.startsWith("11.")) {
return new CfRuntime(CfVm.JDK11, Paths.get(home));
}
throw new Unimplemented("No support for JDK version: " + version);
}
public static class NoneRuntime extends TestRuntime {
private static final String NAME = "none";
private static final NoneRuntime INSTANCE = new NoneRuntime();
private NoneRuntime() {}
public static NoneRuntime getInstance() {
return INSTANCE;
}
@Override
public String name() {
return NAME;
}
@Override
public String toString() {
return NAME;
}
@Override
public boolean equals(Object other) {
return this == other;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
}
// Wrapper for the DEX runtimes.
public static class DexRuntime extends TestRuntime {
private final DexVm vm;
public DexRuntime(DexVm.Version version) {
this(DexVm.fromVersion(version));
}
public DexRuntime(DexVm vm) {
assert vm != null;
this.vm = vm;
}
@Override
public String name() {
return "dex-" + vm.getVersion().toString();
}
@Override
public boolean isDex() {
return true;
}
@Override
public DexRuntime asDex() {
return this;
}
public DexVm getVm() {
return vm;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof DexRuntime)) {
return false;
}
DexRuntime dexRuntime = (DexRuntime) other;
return vm == dexRuntime.vm;
}
@Override
public int hashCode() {
return vm.hashCode();
}
@Override
public String toString() {
return "dex-" + vm.getVersion().toString();
}
public AndroidApiLevel getMinApiLevel() {
return ToolHelper.getMinApiLevelForDexVm(vm);
}
}
// Wrapper for the CF runtimes.
public static class CfRuntime extends TestRuntime {
private final CfVm vm;
private final Path home;
public CfRuntime(CfVm vm, Path home) {
assert vm != null;
this.vm = vm;
this.home = home.toAbsolutePath();
}
@Override
public String name() {
return vm.name().toLowerCase();
}
public Path getJavaHome() {
return home;
}
public Path getJavaExecutable() {
return home.resolve("bin").resolve("java");
}
@Override
public boolean isCf() {
return true;
}
@Override
public CfRuntime asCf() {
return this;
}
public CfVm getVm() {
return vm;
}
@Override
public String toString() {
return vm.toString();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof CfRuntime)) {
return false;
}
CfRuntime cfRuntime = (CfRuntime) obj;
return vm == cfRuntime.vm && home.equals(cfRuntime.home);
}
@Override
public int hashCode() {
return Objects.hash(vm, home);
}
public boolean isNewerThan(CfVm version) {
return !vm.lessThanOrEqual(version);
}
public boolean isNewerThanOrEqual(CfVm version) {
return vm == version || !vm.lessThanOrEqual(version);
}
}
public boolean isDex() {
return false;
}
public boolean isCf() {
return false;
}
public DexRuntime asDex() {
return null;
}
public CfRuntime asCf() {
return null;
}
public Backend getBackend() {
if (isDex()) {
return Backend.DEX;
}
if (isCf()) {
return Backend.CF;
}
throw new Unreachable("Unexpected runtime without backend: " + this);
}
@Override
public abstract boolean equals(Object other);
@Override
public abstract int hashCode();
public abstract String name();
}