blob: f0629883ebf306bff2e5da384c0417321635d6ef [file] [log] [blame]
// Copyright (c) 2017, 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 static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
import static com.android.tools.r8.utils.FileUtils.ZIP_EXTENSION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.OffOrAuto;
import com.android.tools.r8.utils.TestDescriptionWatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
public abstract class RunExamplesAndroidNTest<B> {
private static final String EXAMPLE_DIR = ToolHelper.EXAMPLES_ANDROID_N_BUILD_DIR;
abstract class TestRunner {
final String testName;
final String packageName;
final String mainClass;
final List<Consumer<InternalOptions>> optionConsumers = new ArrayList<>();
final List<UnaryOperator<B>> builderTransformations = new ArrayList<>();
TestRunner(String testName, String packageName, String mainClass) {
this.testName = testName;
this.packageName = packageName;
this.mainClass = mainClass;
}
TestRunner withOptionConsumer(Consumer<InternalOptions> consumer) {
optionConsumers.add(consumer);
return this;
}
TestRunner withInterfaceMethodDesugaring(OffOrAuto behavior) {
return withOptionConsumer(o -> o.interfaceMethodDesugaring = behavior);
}
TestRunner withBuilderTransformation(UnaryOperator<B> builderTransformation) {
builderTransformations.add(builderTransformation);
return this;
}
void combinedOptionConsumer(InternalOptions options) {
for (Consumer<InternalOptions> consumer : optionConsumers) {
consumer.accept(options);
}
}
void run() throws Throwable {
String qualifiedMainClass = packageName + "." + mainClass;
Path inputFile = Paths.get(EXAMPLE_DIR, packageName + JAR_EXTENSION);
Path out = temp.getRoot().toPath().resolve(testName + ZIP_EXTENSION);
build(inputFile, out);
if (!ToolHelper.artSupported() && !ToolHelper.dealsWithGoldenFiles()) {
return;
}
boolean expectedToFail = false;
if (failsOn.containsKey(ToolHelper.getDexVm())
&& failsOn.get(ToolHelper.getDexVm()).contains(testName)) {
expectedToFail = true;
thrown.expect(Throwable.class);
}
String output = ToolHelper.runArtNoVerificationErrors(out.toString(), qualifiedMainClass);
if (!expectedToFail) {
ProcessResult javaResult = ToolHelper.runJava(inputFile, qualifiedMainClass);
assertEquals("JVM run failed", javaResult.exitCode, 0);
assertTrue(
"JVM output does not match art output.\n\tjvm: "
+ javaResult.stdout
+ "\n\tart: "
+ output,
output.equals(javaResult.stdout));
}
}
abstract TestRunner withMinApiLevel(int minApiLevel);
TestRunner withKeepAll() {
return this;
}
abstract void build(Path inputFile, Path out) throws Throwable;
}
private static Map<DexVm.Version, List<String>> failsOn =
ImmutableMap.of(
DexVm.Version.V4_4_4,
ImmutableList.of(),
DexVm.Version.V5_1_1,
ImmutableList.of(),
DexVm.Version.V6_0_1,
ImmutableList.of(),
DexVm.Version.V7_0_0,
ImmutableList.of(),
DexVm.Version.DEFAULT,
ImmutableList.of());
@Rule public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
@Rule public ExpectedException thrown = ExpectedException.none();
@Rule public TestDescriptionWatcher watcher = new TestDescriptionWatcher();
@Test
public void staticInterfaceMethods() throws Throwable {
test("staticinterfacemethods", "interfacemethods", "StaticInterfaceMethods")
.withMinApiLevel(AndroidApiLevel.K.getLevel())
.withInterfaceMethodDesugaring(OffOrAuto.Auto)
.withKeepAll()
.run();
}
@Test(expected = CompilationFailedException.class)
public void staticInterfaceMethodsErrorDueToMinSdk() throws Throwable {
test("staticinterfacemethods-error-due-to-min-sdk", "interfacemethods",
"StaticInterfaceMethods")
.withInterfaceMethodDesugaring(OffOrAuto.Off)
.withKeepAll()
.run();
}
@Test
public void defaultMethods() throws Throwable {
test("defaultmethods", "interfacemethods", "DefaultMethods")
.withMinApiLevel(AndroidApiLevel.K.getLevel())
.withInterfaceMethodDesugaring(OffOrAuto.Auto)
.withKeepAll()
.run();
}
@Test(expected = CompilationFailedException.class)
public void defaultMethodsErrorDueToMinSdk() throws Throwable {
test("defaultmethods-error-due-to-min-sdk", "interfacemethods",
"DefaultMethods")
.withInterfaceMethodDesugaring(OffOrAuto.Off)
.withKeepAll()
.run();
}
abstract TestRunner test(String testName, String packageName, String mainClass);
}