Version 2.1.7-r1
Cherry-pick: Update backports for Android R
CL: https://r8-review.google
Clean and rename test for backports and min API levels.
CL: https://r8-review.googlesource.com/c/r8/+/51160
Update latest API level to R.
CL: https://r8-review.googlesource.com/c/r8/+/51141
Conflicts where resolved for the first and third cherry-pick.
Test code for the second cherry-pick was slightly modified due
to changes in the testing infrastructure.
Bug: 155694125
Change-Id: Ib4857c82d96bf4bceef378e02504fc5123d93086
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 8eec9bf..0dcfa7b 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "2.1.7";
+ public static final String LABEL = "2.1.7-r1";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index fd0e452..24dbf4c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -563,6 +563,9 @@
if (options.minApiLevel < AndroidApiLevel.O.getLevel()) {
initializeAndroidOMethodProviders(factory);
}
+ if (options.minApiLevel < AndroidApiLevel.R.getLevel()) {
+ initializeAndroidRMethodProviders(factory);
+ }
// The following providers are currently not implemented at any API level in Android.
// They however require the Optional/Stream class to be present, either through
@@ -1258,74 +1261,11 @@
method, BackportedMethods::StringMethods_joinIterable, "joinIterable"));
}
- private void initializeJava9MethodProviders(DexItemFactory factory) {
- // Math & StrictMath, which have some symmetric, binary-compatible APIs
- DexType[] mathTypes = {factory.mathType, factory.strictMathType};
- for (int i = 0; i < mathTypes.length; i++) {
- DexType type = mathTypes[i];
-
- // long {Math,StrictMath}.multiplyExact(long, int)
- DexString name = factory.createString("multiplyExact");
- DexProto proto = factory.createProto(factory.longType, factory.longType, factory.intType);
- DexMethod method = factory.createMethod(type, proto, name);
- addProvider(
- new MethodGenerator(
- method,
- BackportedMethods::MathMethods_multiplyExactLongInt,
- "multiplyExactLongInt"));
-
- // long {Math,StrictMath}.multiplyFull(int, int)
- name = factory.createString("multiplyFull");
- proto = factory.createProto(factory.longType, factory.intType, factory.intType);
- method = factory.createMethod(type, proto, name);
- addProvider(
- new MethodGenerator(
- method,
- BackportedMethods::MathMethods_multiplyFull));
-
- // long {Math,StrictMath}.multiplyHigh(long, long)
- name = factory.createString("multiplyHigh");
- proto = factory.createProto(factory.longType, factory.longType, factory.longType);
- method = factory.createMethod(type, proto, name);
- addProvider(
- new MethodGenerator(
- method,
- BackportedMethods::MathMethods_multiplyHigh));
-
- // long {Math,StrictMath}.floorDiv(long, int)
- name = factory.createString("floorDiv");
- proto = factory.createProto(factory.longType, factory.longType, factory.intType);
- method = factory.createMethod(type, proto, name);
- addProvider(
- new MethodGenerator(
- method, BackportedMethods::MathMethods_floorDivLongInt, "floorDivLongInt"));
-
- // int {Math,StrictMath}.floorMod(long, int)
- name = factory.createString("floorMod");
- proto = factory.createProto(factory.intType, factory.longType, factory.intType);
- method = factory.createMethod(type, proto, name);
- addProvider(
- new MethodGenerator(
- method, BackportedMethods::MathMethods_floorModLongInt, "floorModLongInt"));
- }
-
- // Byte
- DexType type = factory.boxedByteType;
-
- // int Byte.compareUnsigned(byte, byte)
- DexString name = factory.createString("compareUnsigned");
- DexProto proto = factory.createProto(factory.intType, factory.byteType, factory.byteType);
- DexMethod method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::ByteMethods_compareUnsigned));
-
- // Short
- type = factory.boxedShortType;
-
- // int Short.compareUnsigned(short, short)
- name = factory.createString("compareUnsigned");
- proto = factory.createProto(factory.intType, factory.shortType, factory.shortType);
- method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::ShortMethods_compareUnsigned));
+ private void initializeAndroidRMethodProviders(DexItemFactory factory) {
+ DexType type;
+ DexString name;
+ DexProto proto;
+ DexMethod method;
// Objects
type = factory.objectsType;
@@ -1436,6 +1376,70 @@
addProvider(new MethodGenerator(method, BackportedMethods::CollectionMethods_mapEntry));
}
+ private void initializeJava9MethodProviders(DexItemFactory factory) {
+ // Math & StrictMath, which have some symmetric, binary-compatible APIs
+ DexType[] mathTypes = {factory.mathType, factory.strictMathType};
+ for (int i = 0; i < mathTypes.length; i++) {
+ DexType type = mathTypes[i];
+
+ // long {Math,StrictMath}.multiplyExact(long, int)
+ DexString name = factory.createString("multiplyExact");
+ DexProto proto = factory.createProto(factory.longType, factory.longType, factory.intType);
+ DexMethod method = factory.createMethod(type, proto, name);
+ addProvider(
+ new MethodGenerator(
+ method,
+ BackportedMethods::MathMethods_multiplyExactLongInt,
+ "multiplyExactLongInt"));
+
+ // long {Math,StrictMath}.multiplyFull(int, int)
+ name = factory.createString("multiplyFull");
+ proto = factory.createProto(factory.longType, factory.intType, factory.intType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::MathMethods_multiplyFull));
+
+ // long {Math,StrictMath}.multiplyHigh(long, long)
+ name = factory.createString("multiplyHigh");
+ proto = factory.createProto(factory.longType, factory.longType, factory.longType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::MathMethods_multiplyHigh));
+
+ // long {Math,StrictMath}.floorDiv(long, int)
+ name = factory.createString("floorDiv");
+ proto = factory.createProto(factory.longType, factory.longType, factory.intType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(
+ new MethodGenerator(
+ method, BackportedMethods::MathMethods_floorDivLongInt, "floorDivLongInt"));
+
+ // int {Math,StrictMath}.floorMod(long, int)
+ name = factory.createString("floorMod");
+ proto = factory.createProto(factory.intType, factory.longType, factory.intType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(
+ new MethodGenerator(
+ method, BackportedMethods::MathMethods_floorModLongInt, "floorModLongInt"));
+ }
+
+ // Byte
+ DexType type = factory.boxedByteType;
+
+ // int Byte.compareUnsigned(byte, byte)
+ DexString name = factory.createString("compareUnsigned");
+ DexProto proto = factory.createProto(factory.intType, factory.byteType, factory.byteType);
+ DexMethod method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::ByteMethods_compareUnsigned));
+
+ // Short
+ type = factory.boxedShortType;
+
+ // int Short.compareUnsigned(short, short)
+ name = factory.createString("compareUnsigned");
+ proto = factory.createProto(factory.intType, factory.shortType, factory.shortType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::ShortMethods_compareUnsigned));
+ }
+
private void initializeJava10MethodProviders(DexItemFactory factory) {
// List
DexType type = factory.listType;
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
index 8c5c3b2..cbf6e2a 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
@@ -12,7 +12,7 @@
* Android API level description
*/
public enum AndroidApiLevel {
- R(30), // Speculative, this can change.
+ R(30),
Q(29),
P(28),
O_MR1(27),
@@ -43,7 +43,7 @@
B_1_1(2),
B(1);
- public static final AndroidApiLevel LATEST = Q;
+ public static final AndroidApiLevel LATEST = R;
public static final int magicApiLevelUsedByAndroidPlatformBuild = 10000;
diff --git a/src/main/java/com/android/tools/r8/utils/DexVersion.java b/src/main/java/com/android/tools/r8/utils/DexVersion.java
index 99098d8..e9557fa 100644
--- a/src/main/java/com/android/tools/r8/utils/DexVersion.java
+++ b/src/main/java/com/android/tools/r8/utils/DexVersion.java
@@ -38,6 +38,7 @@
public static DexVersion getDexVersion(AndroidApiLevel androidApiLevel) {
switch (androidApiLevel) {
+ case R:
case Q:
case P:
return DexVersion.V39;
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
index 190e7ee..d2dd4dc 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
@@ -28,7 +28,7 @@
import org.junit.Test;
abstract class AbstractBackportTest extends TestBase {
- private final TestParameters parameters;
+ protected final TestParameters parameters;
private final Class<?> targetClass;
private final Class<?> testClass;
private final Path testJar;
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java b/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
new file mode 100644
index 0000000..00c9bc3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
@@ -0,0 +1,163 @@
+// 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.desugar.backports;
+
+import static org.hamcrest.core.StringContains.containsString;
+
+import com.android.tools.r8.D8TestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ApiLevelBackportsTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ // NOTE: Most of the 'run' invocations below work only because the static configured APIs do not
+ // give rise to DEX file versions larger than what can be accepted by VM 9.0.0.
+ return getTestParameters().withDexRuntimesStartingFromIncluding(Version.V9_0_0).build();
+ }
+
+ public ApiLevelBackportsTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void backportSucceedsOnSupportedApiLevel() throws Exception {
+ testForD8()
+ .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+ .setMinApi(AndroidApiLevel.B)
+ .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
+ .assertSuccessWithOutputLines("4");
+ }
+
+ @Test
+ public void backportOfNonPresentMethodOnLatest() throws Exception {
+ testForD8()
+ .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+ .setMinApi(AndroidApiLevel.LATEST)
+ .compile()
+ .assertNoMessages()
+ .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
+ .assertSuccessWithOutputLines("4");
+ }
+
+ @Test
+ public void backportOfPresentMethodOnLatest() throws Exception {
+ D8TestRunResult result =
+ testForD8()
+ .addProgramClassFileData(transformTestListOf())
+ .setMinApi(AndroidApiLevel.LATEST)
+ .compile()
+ .assertNoMessages()
+ .run(parameters.getRuntime(), TestListOf.class);
+ if (runtimeHasListOf()) {
+ result.assertSuccessWithOutputLines("0");
+ } else {
+ result.assertFailureWithErrorThatMatches(
+ containsString("java.lang.NoSuchMethodError: No static method of()Ljava/util/List;"));
+ }
+ }
+
+ @Test
+ public void warningForFutureNonPlatformBuild() throws Exception {
+ testForD8()
+ .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+ .setMinApi(AndroidApiLevel.LATEST.getLevel() + 1)
+ .compile()
+ .assertOnlyWarnings()
+ .assertWarningMessageThatMatches(containsString("is not supported by this compiler"))
+ .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
+ .assertFailureWithErrorThatMatches(
+ containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
+ }
+
+ @Test
+ public void noWarningForPlatformBuild() throws Exception {
+ testForD8()
+ .addProgramClassFileData(transformTestMathMultiplyExactLongInt())
+ .setMinApi(AndroidApiLevel.magicApiLevelUsedByAndroidPlatformBuild)
+ .run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
+ .assertFailureWithErrorThatMatches(
+ containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
+ }
+
+ // Test class for using: List List.of()
+ // Introduced in Android R.
+
+ boolean runtimeHasListOf() {
+ return parameters
+ .getRuntime()
+ .asDex()
+ .getMinApiLevel()
+ .isGreaterThanOrEqualTo(AndroidApiLevel.R);
+ }
+
+ byte[] transformTestListOf() throws Exception {
+ return transformer(TestListOf.class)
+ .transformMethodInsnInMethod(
+ "main",
+ (opcode, owner, name, descriptor, isInterface, continuation) -> {
+ if (name.equals("List_of")) {
+ continuation.apply(opcode, "java/util/List", "of", descriptor, isInterface);
+ } else {
+ continuation.apply(opcode, owner, name, descriptor, isInterface);
+ }
+ })
+ .transform();
+ }
+
+ static class TestListOf {
+ public static List List_of() {
+ throw null;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(List_of().size());
+ }
+ }
+
+ // Test class for the method: long Math.multiplyExact(long, int)
+ // Not present on any currently known Android platforms.
+
+ boolean runtimeHasMathMultiplyExactLongInt() {
+ // NOTE: This may change with a future release.
+ return false;
+ }
+
+ byte[] transformTestMathMultiplyExactLongInt() throws Exception {
+ return transformer(TestMathMultiplyExactLongInt.class)
+ .transformMethodInsnInMethod(
+ "main",
+ (opcode, owner, name, descriptor, isInterface, continuation) -> {
+ if (name.equals("Math_multiplyExact")) {
+ continuation.apply(
+ opcode, "java/lang/Math", "multiplyExact", descriptor, isInterface);
+ } else {
+ continuation.apply(opcode, owner, name, descriptor, isInterface);
+ }
+ })
+ .transform();
+ }
+
+ static class TestMathMultiplyExactLongInt {
+ public static long Math_multiplyExact(long l, int i) {
+ throw null;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(Math_multiplyExact(2L, 2));
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava9Test.java
index 03843cc0..0d55065 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ListBackportJava9Test.java
@@ -5,13 +5,16 @@
package com.android.tools.r8.desugar.backports;
import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static org.hamcrest.CoreMatchers.containsString;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
+import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@@ -29,9 +32,10 @@
private static final Path TEST_JAR =
Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+ private static final String TEST_CLASS = "backport.ListBackportJava9Main";
public ListBackportJava9Test(TestParameters parameters) {
- super(parameters, List.class, TEST_JAR, "backport.ListBackportJava9Main");
+ super(parameters, List.class, TEST_JAR, TEST_CLASS);
// Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
// an actual API level, migrate these tests to ListBackportTest.
@@ -41,4 +45,20 @@
ignoreInvokes("set");
ignoreInvokes("size");
}
+
+ @Test
+ public void desugaringApiLevelR() throws Exception {
+ // TODO(154759404): This test should start to fail when testing on an Android R VM.
+ if (parameters.getRuntime().isDex()
+ && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.Q)) {
+ testForD8()
+ .setMinApi(AndroidApiLevel.R)
+ .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
+ .addProgramFiles(TEST_JAR)
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .run(parameters.getRuntime(), TEST_CLASS)
+ .assertFailureWithErrorThatMatches(containsString("java.lang.NoSuchMethodError"));
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava9Test.java
index fb39b49..27cb824 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/MapBackportJava9Test.java
@@ -4,18 +4,21 @@
package com.android.tools.r8.desugar.backports;
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static org.hamcrest.CoreMatchers.containsString;
+
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
+import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-
@RunWith(Parameterized.class)
public class MapBackportJava9Test extends AbstractBackportTest {
@Parameters(name = "{0}")
@@ -29,9 +32,10 @@
private static final Path TEST_JAR =
Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+ private static final String TEST_CLASS = "backport.MapBackportJava9Main";
public MapBackportJava9Test(TestParameters parameters) {
- super(parameters, Map.class, TEST_JAR, "backport.MapBackportJava9Main");
+ super(parameters, Map.class, TEST_JAR, TEST_CLASS);
// Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
// an actual API level, migrate these tests to MapBackportTest.
@@ -41,4 +45,20 @@
ignoreInvokes("put");
ignoreInvokes("size");
}
+
+ @Test
+ public void desugaringApiLevelR() throws Exception {
+ // TODO(154759404): This test should start to fail when testing on an Android R VM.
+ if (parameters.getRuntime().isDex()
+ && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.Q)) {
+ testForD8()
+ .setMinApi(AndroidApiLevel.R)
+ .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
+ .addProgramFiles(TEST_JAR)
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .run(parameters.getRuntime(), TEST_CLASS)
+ .assertFailureWithErrorThatMatches(containsString("java.lang.NoSuchMethodError"));
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/NoBackportForAndroidPlatform.java b/src/test/java/com/android/tools/r8/desugar/backports/NoBackportForAndroidPlatform.java
deleted file mode 100644
index 47081ab..0000000
--- a/src/test/java/com/android/tools/r8/desugar/backports/NoBackportForAndroidPlatform.java
+++ /dev/null
@@ -1,128 +0,0 @@
-// 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.desugar.backports;
-
-import static org.hamcrest.core.StringContains.containsString;
-
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.utils.AndroidApiLevel;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-
-@RunWith(Parameterized.class)
-public class NoBackportForAndroidPlatform extends TestBase implements Opcodes {
-
- private final TestParameters parameters;
-
- @Parameterized.Parameters(name = "{0}")
- public static TestParametersCollection data() {
- // The use of high API level will produce dex files with high DEX version, so only run on high
- // API level VMs.
- return getTestParameters()
- .withDexRuntimes()
- .withApiLevelsStartingAtIncluding(AndroidApiLevel.P)
- .build();
- }
-
- public NoBackportForAndroidPlatform(TestParameters parameters) {
- this.parameters = parameters;
- }
-
- @Test
- public void backportSucceedsOnSupportedApiLevel() throws Exception {
- testForD8()
- .addProgramClassFileData(mainWithMathMultiplyExactLongInt())
- .setMinApi(AndroidApiLevel.B)
- .run(parameters.getRuntime(), "Test")
- .assertSuccessWithOutputLines("4");
- }
-
- @Test
- public void warningForNonPlatformBuild() throws Exception {
- testForD8()
- .addProgramClassFileData(mainWithMathMultiplyExactLongInt())
- .setMinApi(30)
- .compile()
- .assertOnlyWarnings()
- .assertWarningMessageThatMatches(
- containsString("An API level of 30 is not supported by this compiler"))
- .run(parameters.getRuntime(), "Test")
- .assertFailureWithErrorThatMatches(
- containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
- }
-
- @Test
- public void noWarningForPlatformBuild() throws Exception {
- testForD8()
- .addProgramClassFileData(mainWithMathMultiplyExactLongInt())
- .setMinApi(AndroidApiLevel.magicApiLevelUsedByAndroidPlatformBuild)
- .run(parameters.getRuntime(), "Test")
- .assertFailureWithErrorThatMatches(
- containsString("java.lang.NoSuchMethodError: No static method multiplyExact(JI)J"));
- }
-
- // Code for:
- //
- // class Test {
- // public static void main(String[] args) {
- // // Call Math.multiplyExact(long, int), which is not in Android Q.
- // System.out.println(Math.multiplyExact(2L, 2));
- // }
- // }
- //
- private byte[] mainWithMathMultiplyExactLongInt() {
-
- ClassWriter classWriter = new ClassWriter(0);
- MethodVisitor methodVisitor;
-
- classWriter.visit(V1_8, ACC_SUPER, "Test", null, "java/lang/Object", null);
-
- classWriter.visitSource("Test.java", null);
-
- {
- methodVisitor = classWriter.visitMethod(0, "<init>", "()V", null, null);
- methodVisitor.visitCode();
- Label label0 = new Label();
- methodVisitor.visitLabel(label0);
- methodVisitor.visitLineNumber(1, label0);
- methodVisitor.visitVarInsn(ALOAD, 0);
- methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
- methodVisitor.visitInsn(RETURN);
- methodVisitor.visitMaxs(1, 1);
- methodVisitor.visitEnd();
- }
- {
- methodVisitor =
- classWriter.visitMethod(
- ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
- methodVisitor.visitCode();
- Label label0 = new Label();
- methodVisitor.visitLabel(label0);
- methodVisitor.visitLineNumber(3, label0);
- methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
- methodVisitor.visitLdcInsn(Long.valueOf(2L));
- methodVisitor.visitLdcInsn(Integer.valueOf(2));
- methodVisitor.visitMethodInsn(
- INVOKESTATIC, "java/lang/Math", "multiplyExact", "(JI)J", false);
- methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(J)V", false);
- Label label1 = new Label();
- methodVisitor.visitLabel(label1);
- methodVisitor.visitLineNumber(4, label1);
- methodVisitor.visitInsn(RETURN);
- methodVisitor.visitMaxs(5, 1);
- methodVisitor.visitEnd();
- }
- classWriter.visitEnd();
-
- return classWriter.toByteArray();
- }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java
index ef8b990..09aef1e 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java
@@ -4,17 +4,20 @@
package com.android.tools.r8.desugar.backports;
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static org.hamcrest.CoreMatchers.containsString;
+
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import java.nio.file.Path;
import java.nio.file.Paths;
+import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-
@RunWith(Parameterized.class)
public final class ObjectsBackportJava9Test extends AbstractBackportTest {
@Parameters(name = "{0}")
@@ -28,10 +31,27 @@
private static final Path TEST_JAR =
Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+ private static final String TEST_CLASS = "backport.ObjectsBackportJava9Main";
public ObjectsBackportJava9Test(TestParameters parameters) {
- super(parameters, Short.class, TEST_JAR, "backport.ObjectsBackportJava9Main");
+ super(parameters, Short.class, TEST_JAR, TEST_CLASS);
// Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
// an actual API level, migrate these tests to ObjectsBackportTest.
}
+
+ @Test
+ public void desugaringApiLevelR() throws Exception {
+ // TODO(154759404): This test should start to fail when testing on an Android R VM.
+ if (parameters.getRuntime().isDex()
+ && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.Q)) {
+ testForD8()
+ .setMinApi(AndroidApiLevel.R)
+ .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
+ .addProgramFiles(TEST_JAR)
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .run(parameters.getRuntime(), TEST_CLASS)
+ .assertFailureWithErrorThatMatches(containsString("java.lang.NoSuchMethodError"));
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava9Test.java
index 6947ff2..408b203 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/SetBackportJava9Test.java
@@ -4,18 +4,21 @@
package com.android.tools.r8.desugar.backports;
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static org.hamcrest.CoreMatchers.containsString;
+
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
+import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-
@RunWith(Parameterized.class)
public class SetBackportJava9Test extends AbstractBackportTest {
@Parameters(name = "{0}")
@@ -29,9 +32,10 @@
private static final Path TEST_JAR =
Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+ private static final String TEST_CLASS = "backport.SetBackportJava9Main";
public SetBackportJava9Test(TestParameters parameters) {
- super(parameters, Set.class, TEST_JAR, "backport.SetBackportJava9Main");
+ super(parameters, Set.class, TEST_JAR, TEST_CLASS);
// Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
// an actual API level, migrate these tests to SetBackportTest.
@@ -40,4 +44,20 @@
ignoreInvokes("contains");
ignoreInvokes("size");
}
+
+ @Test
+ public void desugaringApiLevelR() throws Exception {
+ // TODO(154759404): This test should start to fail when testing on an Android R VM.
+ if (parameters.getRuntime().isDex()
+ && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.Q)) {
+ testForD8()
+ .setMinApi(AndroidApiLevel.R)
+ .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
+ .addProgramFiles(TEST_JAR)
+ .setIncludeClassesChecksum(true)
+ .compile()
+ .run(parameters.getRuntime(), TEST_CLASS)
+ .assertFailureWithErrorThatMatches(containsString("java.lang.NoSuchMethodError"));
+ }
+ }
}