blob: bb344d713359e02d67f577f461d62bef0dfb4118 [file] [log] [blame]
// Copyright (c) 2020, 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 org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class BackportedMethodListTest {
@Rule public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
enum Mode {
NO_LIBRARY,
LIBRARY,
LIBRARY_DESUGAR
}
@Parameterized.Parameters(name = "Mode: {0}")
public static Object[] data() {
return Mode.values();
}
private final Mode mode;
public BackportedMethodListTest(Mode mode) {
this.mode = mode;
}
private static class ListStringConsumer implements StringConsumer {
List<String> strings = new ArrayList<>();
boolean finished = false;
@Override
public void accept(String string, DiagnosticsHandler handler) {
strings.add(string);
}
@Override
public void finished(DiagnosticsHandler handler) {
finished = true;
}
}
private void checkContent(int apiLevel, List<String> backports) {
// Java 8 methods added at various API levels.
assertEquals(
apiLevel < AndroidApiLevel.K.getLevel(), backports.contains("java/lang/Byte#compare(BB)I"));
assertEquals(
apiLevel < AndroidApiLevel.N.getLevel(),
backports.contains("java/lang/Integer#hashCode(I)I"));
assertEquals(
apiLevel < AndroidApiLevel.O.getLevel(),
backports.contains("java/lang/Short#toUnsignedLong(S)J"));
// Java 9, 10 and 11 Optional methods which require Android N or library desugaring.
assertEquals(
mode == Mode.LIBRARY_DESUGAR || apiLevel >= AndroidApiLevel.N.getLevel(),
backports.contains(
"java/util/Optional#or(Ljava/util/function/Supplier;)Ljava/util/Optional;"));
assertEquals(
mode == Mode.LIBRARY_DESUGAR || apiLevel >= AndroidApiLevel.N.getLevel(),
backports.contains("java/util/OptionalInt#orElseThrow()I"));
assertEquals(
mode == Mode.LIBRARY_DESUGAR || apiLevel >= AndroidApiLevel.N.getLevel(),
backports.contains("java/util/OptionalLong#isEmpty()Z"));
// Java 9, 10 and 11 methods.
assertTrue(backports.contains("java/lang/StrictMath#multiplyExact(JI)J"));
assertTrue(backports.contains("java/util/List#copyOf(Ljava/util/Collection;)Ljava/util/List;"));
assertTrue(backports.contains("java/lang/Character#toString(I)Ljava/lang/String;"));
}
private void addLibraryDesugaring(BackportedMethodListCommand.Builder builder) {
builder
.addDesugaredLibraryConfiguration(
StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P.getLevel()));
}
@Test
public void testConsumer() throws Exception {
for (int apiLevel = 1; apiLevel < AndroidApiLevel.LATEST.getLevel(); apiLevel++) {
ListStringConsumer consumer = new ListStringConsumer();
BackportedMethodListCommand.Builder builder =
BackportedMethodListCommand.builder().setMinApiLevel(apiLevel).setConsumer(consumer);
if (mode == Mode.LIBRARY) {
builder.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P.getLevel()));
} else if (mode == Mode.LIBRARY_DESUGAR) {
addLibraryDesugaring(builder);
}
BackportedMethodList.run(builder.build());
assertTrue(consumer.finished);
checkContent(apiLevel, consumer.strings);
}
}
@Test
public void testFile() throws Exception {
for (int apiLevel = 1; apiLevel < AndroidApiLevel.LATEST.getLevel(); apiLevel++) {
Path output = temp.newFile().toPath();
BackportedMethodListCommand.Builder builder =
BackportedMethodListCommand.builder().setMinApiLevel(apiLevel).setOutputPath(output);
if (mode == Mode.LIBRARY) {
builder.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P.getLevel()));
} else if (mode == Mode.LIBRARY_DESUGAR) {
addLibraryDesugaring(builder);
}
BackportedMethodList.run(builder.build());
checkContent(apiLevel, Files.readAllLines(output));
}
}
@Test
public void testFullList() throws Exception {
Assume.assumeTrue(mode == Mode.NO_LIBRARY);
ListStringConsumer consumer = new ListStringConsumer();
// Not setting neither min API level not library should produce the full list.
BackportedMethodList.run(BackportedMethodListCommand.builder().setConsumer(consumer).build());
assertTrue(consumer.finished);
checkContent(1, consumer.strings);
}
@Test
public void requireLibraryForDesugar() {
Assume.assumeTrue(mode == Mode.LIBRARY_DESUGAR);
// Require library when a desugar configuration is passed.
try {
BackportedMethodList.run(
BackportedMethodListCommand.builder()
.addDesugaredLibraryConfiguration(
StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING))
.setConsumer(new ListStringConsumer())
.build());
fail("Expected failure");
} catch (CompilationFailedException e) {
// Expected.
}
}
}