Math/StrictMath JDK Tests
- Add JDK tests for Math/StrictMath
- Add support for multiplyExact,
floorDiv, floorMod with longxint
parameters.
- Add Java 9 tests for the 3 new methods
- Fix BackportedMethodRewriter to support
Backported methods calling each other
Bug:136717060
Change-Id: I2ae7dad3fd9ddfde496203f08c81211bb68d17e6
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 430c38a..7a830e8 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
@@ -6,7 +6,6 @@
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
@@ -141,6 +140,7 @@
if (holders.isEmpty()) {
return;
}
+ // Compute referencing classes ignoring references in-between utility classes.
Set<DexProgramClass> referencingClasses = Sets.newConcurrentHashSet();
for (DexType holder : holders) {
DexClass definitionFor = appView.definitionFor(holder);
@@ -152,15 +152,22 @@
referencingClasses.add(definitionFor.asProgramClass());
}
}
+
MethodAccessFlags flags = MethodAccessFlags.fromSharedAccessFlags(
Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNTHETIC, false);
ClassAccessFlags classAccessFlags =
ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC);
-
- for (MethodProvider provider : methodProviders.values()) {
+ // Generate the utility classes in a loop since utility classes can require the
+ // the creation of other utility classes.
+ // Function multiplyExact(long int) calls multiplyExact(long long) for example.
+ while (!methodProviders.isEmpty()) {
+ DexMethod key = methodProviders.keySet().iterator().next();
+ MethodProvider provider = methodProviders.get(key);
+ methodProviders.remove(key);
assert provider.requiresGenerationOfCode();
DexMethod method = provider.provideMethod(factory);
- // The utility class could have been synthesized, e.g., running R8 then D8.
+ // The utility class could have been synthesized, e.g., running R8 then D8,
+ // or if already processed in this while loop.
if (appView.definitionFor(method.holder) != null) {
continue;
}
@@ -189,12 +196,13 @@
factory.getSkipNameValidationForTesting(),
referencingClasses);
code.setUpContext(utilityClass);
- AppInfo appInfo = appView.appInfo();
boolean addToMainDexList =
- referencingClasses.stream().anyMatch(clazz -> appInfo.isInMainDexList(clazz.type));
- appInfo.addSynthesizedClass(utilityClass);
- converter.optimizeSynthesizedClass(utilityClass, executorService);
+ referencingClasses.stream()
+ .anyMatch(clazz -> appView.appInfo().isInMainDexList(clazz.type));
+ appView.appInfo().addSynthesizedClass(utilityClass);
builder.addSynthesizedClass(utilityClass, addToMainDexList);
+ // The following may add elements to methodsProviders.
+ converter.optimizeSynthesizedClass(utilityClass, executorService);
}
}
@@ -231,6 +239,9 @@
if (!options.canUseJava9UnsignedOperations()) {
initializeJava9UnsignedOperations(factory);
}
+ if (!options.canUseJava9SignedOperations()) {
+ initializeJava9SignedOperations(factory);
+ }
// interface method desugaring also toggles library emulation.
if (options.isInterfaceMethodDesugaringEnabled()) {
initializeRetargetCoreLibraryMembers(appView);
@@ -528,7 +539,7 @@
proto = factory.createProto(factory.intType, factory.intType, factory.intType);
addProvider(new MethodGenerator(clazz, method, proto, MathMethods::new, "floorDivInt"));
- // long {Math,StrictMath}.floorDiv(long)
+ // long {Math,StrictMath}.floorDiv(long, long)
method = factory.createString("floorDiv");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
addProvider(new MethodGenerator(clazz, method, proto, MathMethods::new, "floorDivLong"));
@@ -538,7 +549,7 @@
proto = factory.createProto(factory.intType, factory.intType, factory.intType);
addProvider(new MethodGenerator(clazz, method, proto, MathMethods::new, "floorModInt"));
- // long {Math,StrictMath}.floorMod(long)
+ // long {Math,StrictMath}.floorMod(long, long)
method = factory.createString("floorMod");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
addProvider(new MethodGenerator(clazz, method, proto, MathMethods::new, "floorModLong"));
@@ -549,7 +560,7 @@
addProvider(
new MethodGenerator(clazz, method, proto, MathMethods::new, "multiplyExactInt"));
- // long {Math,StrictMath}.multiplyExact(long)
+ // long {Math,StrictMath}.multiplyExact(long, long)
method = factory.createString("multiplyExact");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
addProvider(
@@ -677,8 +688,9 @@
// int Integer.parseUnsignedInt(String value, int radix)
method = factory.createString("parseUnsignedInt");
proto = factory.createProto(factory.intType, factory.stringType, factory.intType);
- addProvider(new MethodGenerator(clazz, method, proto, IntegerMethods::new,
- "parseUnsignedIntWithRadix"));
+ addProvider(
+ new MethodGenerator(
+ clazz, method, proto, IntegerMethods::new, "parseUnsignedIntWithRadix"));
// String Integer.toUnsignedString(int value)
method = factory.createString("toUnsignedString");
@@ -688,8 +700,9 @@
// String Integer.toUnsignedString(int value, int radix)
method = factory.createString("toUnsignedString");
proto = factory.createProto(factory.stringType, factory.intType, factory.intType);
- addProvider(new MethodGenerator(clazz, method, proto, IntegerMethods::new,
- "toUnsignedStringWithRadix"));
+ addProvider(
+ new MethodGenerator(
+ clazz, method, proto, IntegerMethods::new, "toUnsignedStringWithRadix"));
// Long
clazz = factory.boxedLongDescriptor;
@@ -717,8 +730,9 @@
// long Long.parseUnsignedLong(String value, int radix)
method = factory.createString("parseUnsignedLong");
proto = factory.createProto(factory.longType, factory.stringType, factory.intType);
- addProvider(new MethodGenerator(clazz, method, proto, LongMethods::new,
- "parseUnsignedLongWithRadix"));
+ addProvider(
+ new MethodGenerator(
+ clazz, method, proto, LongMethods::new, "parseUnsignedLongWithRadix"));
// String Long.toUnsignedString(long value)
method = factory.createString("toUnsignedString");
@@ -728,8 +742,8 @@
// String Long.toUnsignedString(long value, int radix)
method = factory.createString("toUnsignedString");
proto = factory.createProto(factory.stringType, factory.longType, factory.intType);
- addProvider(new MethodGenerator(clazz, method, proto, LongMethods::new,
- "toUnsignedStringWithRadix"));
+ addProvider(
+ new MethodGenerator(clazz, method, proto, LongMethods::new, "toUnsignedStringWithRadix"));
// String
clazz = factory.stringDescriptor;
@@ -747,6 +761,29 @@
addProvider(new MethodGenerator(clazz, method, proto, StringMethods::new, "joinIterable"));
}
+ private void initializeJava9SignedOperations(DexItemFactory factory) {
+ DexString[] mathClasses = {factory.mathDescriptor, factory.strictMathDescriptor};
+ for (DexString mathClass : mathClasses) {
+ DexString clazz = mathClass;
+
+ // long {Math,StrictMath}.multiplyExact(long, int)
+ DexString method = factory.createString("multiplyExact");
+ DexProto proto = factory.createProto(factory.longType, factory.longType, factory.intType);
+ addProvider(
+ new MethodGenerator(clazz, method, proto, MathMethods::new, "multiplyExactLongInt"));
+
+ // long {Math,StrictMath}.floorDiv(long, int)
+ method = factory.createString("floorDiv");
+ proto = factory.createProto(factory.longType, factory.longType, factory.intType);
+ addProvider(new MethodGenerator(clazz, method, proto, MathMethods::new, "floorDivLongInt"));
+
+ // int {Math,StrictMath}.floorMod(long, int)
+ method = factory.createString("floorMod");
+ proto = factory.createProto(factory.intType, factory.longType, factory.intType);
+ addProvider(new MethodGenerator(clazz, method, proto, MathMethods::new, "floorModLongInt"));
+ }
+ }
+
private void initializeJava9UnsignedOperations(DexItemFactory factory) {
// Byte
DexString clazz = factory.boxedByteDescriptor;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/MathMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/MathMethods.java
index fc5458f..394823f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/MathMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/MathMethods.java
@@ -72,6 +72,10 @@
return signum < 0L ? div - 1L : div;
}
+ public static long floorDivLongInt(long dividend, int divisor) {
+ return Math.floorDiv(dividend, (long) divisor);
+ }
+
public static int floorModInt(int dividend, int divisor) {
int rem = dividend % divisor;
if (rem == 0) {
@@ -98,6 +102,10 @@
return signum > 0L ? rem : rem + divisor;
}
+ public static int floorModLongInt(long dividend, int divisor) {
+ return (int) Math.floorMod(dividend, (long) divisor);
+ }
+
public static int incrementExactInt(int value) {
if (value == Integer.MAX_VALUE) {
throw new ArithmeticException();
@@ -149,6 +157,10 @@
throw new ArithmeticException();
}
+ public static long multiplyExactLongInt(long x, int y) {
+ return Math.multiplyExact(x, (long) y);
+ }
+
public static int negateExactInt(int value) {
if (value == Integer.MIN_VALUE) {
throw new ArithmeticException();
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 81ace3c..731fcfa 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1002,6 +1002,11 @@
return false;
}
+ public boolean canUseJava9SignedOperations() {
+ assert isGeneratingDex();
+ return false;
+ }
+
public boolean canUsePrivateInterfaceMethods() {
return isGeneratingClassFiles() || hasMinApi(AndroidApiLevel.N);
}
diff --git a/src/test/examplesJava9/backport/MathBackportJava9Main.java b/src/test/examplesJava9/backport/MathBackportJava9Main.java
new file mode 100644
index 0000000..5eefb65
--- /dev/null
+++ b/src/test/examplesJava9/backport/MathBackportJava9Main.java
@@ -0,0 +1,67 @@
+// 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 backport;
+
+public class MathBackportJava9Main {
+
+ public static void main(String[] args) {
+ testMultiplyExactLongInt();
+ testFloorDivLongInt();
+ testFloorModLongInt();
+ }
+
+ public static void testMultiplyExactLongInt() {
+ assertEquals(8L, Math.multiplyExact(2L, 4));
+ assertEquals(Long.MAX_VALUE, Math.multiplyExact(Long.MAX_VALUE, 1));
+ assertEquals(Long.MIN_VALUE, Math.multiplyExact(Long.MIN_VALUE / 2L, 2));
+ try {
+ throw new AssertionError(Math.multiplyExact(Long.MAX_VALUE, 2));
+ } catch (ArithmeticException expected) {
+ }
+ try {
+ throw new AssertionError(Math.multiplyExact(Long.MIN_VALUE, 2));
+ } catch (ArithmeticException expected) {
+ }
+ }
+
+ public static void testFloorDivLongInt() {
+ assertEquals(1L, Math.floorDiv(4L, 4));
+ assertEquals(1L, Math.floorDiv(-4L, -4));
+ assertEquals(-1L, Math.floorDiv(-4L, 4));
+ assertEquals(-1L, Math.floorDiv(4L, -4));
+
+ assertEquals(1L, Math.floorDiv(4L, 3));
+ assertEquals(1L, Math.floorDiv(-4L, -3));
+ assertEquals(-2L, Math.floorDiv(-4L, 3));
+ assertEquals(-2L, Math.floorDiv(4L, -3));
+
+ // Spec edge case: result is actually MAX_VALUE+1 which becomes MIN_VALUE.
+ assertEquals(Long.MIN_VALUE, Math.floorDiv(Long.MIN_VALUE, -1));
+ }
+
+ public static void testFloorModLongInt() {
+ assertEquals(0, Math.floorMod(4L, 4));
+ assertEquals(0, Math.floorMod(-4L, -4));
+ assertEquals(0, Math.floorMod(-4L, 4));
+ assertEquals(0, Math.floorMod(4L, -4));
+
+ assertEquals(1, Math.floorMod(4L, 3));
+ assertEquals(-1, Math.floorMod(-4L, -3));
+ assertEquals(2, Math.floorMod(-4L, 3));
+ assertEquals(-2, Math.floorMod(4L, -3));
+ }
+
+ private static void assertEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected <" + expected + "> but was <" + actual + '>');
+ }
+ }
+
+ private static void assertEquals(long expected, long actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected <" + expected + "> but was <" + actual + '>');
+ }
+ }
+}
diff --git a/src/test/examplesJava9/backport/StrictMathBackportJava9Main.java b/src/test/examplesJava9/backport/StrictMathBackportJava9Main.java
new file mode 100644
index 0000000..b711539
--- /dev/null
+++ b/src/test/examplesJava9/backport/StrictMathBackportJava9Main.java
@@ -0,0 +1,67 @@
+// 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 backport;
+
+public class StrictMathBackportJava9Main {
+
+ public static void main(String[] args) {
+ testMultiplyExactLongInt();
+ testFloorDivLongInt();
+ testFloorModLongInt();
+ }
+
+ public static void testMultiplyExactLongInt() {
+ assertEquals(8L, StrictMath.multiplyExact(2L, 4));
+ assertEquals(Long.MAX_VALUE, StrictMath.multiplyExact(Long.MAX_VALUE, 1));
+ assertEquals(Long.MIN_VALUE, StrictMath.multiplyExact(Long.MIN_VALUE / 2L, 2));
+ try {
+ throw new AssertionError(StrictMath.multiplyExact(Long.MAX_VALUE, 2));
+ } catch (ArithmeticException expected) {
+ }
+ try {
+ throw new AssertionError(StrictMath.multiplyExact(Long.MIN_VALUE, 2));
+ } catch (ArithmeticException expected) {
+ }
+ }
+
+ public static void testFloorDivLongInt() {
+ assertEquals(1L, StrictMath.floorDiv(4L, 4));
+ assertEquals(1L, StrictMath.floorDiv(-4L, -4));
+ assertEquals(-1L, StrictMath.floorDiv(-4L, 4));
+ assertEquals(-1L, StrictMath.floorDiv(4L, -4));
+
+ assertEquals(1L, StrictMath.floorDiv(4L, 3));
+ assertEquals(1L, StrictMath.floorDiv(-4L, -3));
+ assertEquals(-2L, StrictMath.floorDiv(-4L, 3));
+ assertEquals(-2L, StrictMath.floorDiv(4L, -3));
+
+ // Spec edge case: result is actually MAX_VALUE+1 which becomes MIN_VALUE.
+ assertEquals(Long.MIN_VALUE, StrictMath.floorDiv(Long.MIN_VALUE, -1));
+ }
+
+ public static void testFloorModLongInt() {
+ assertEquals(0, StrictMath.floorMod(4L, 4));
+ assertEquals(0, StrictMath.floorMod(-4L, -4));
+ assertEquals(0, StrictMath.floorMod(-4L, 4));
+ assertEquals(0, StrictMath.floorMod(4L, -4));
+
+ assertEquals(1, StrictMath.floorMod(4L, 3));
+ assertEquals(-1, StrictMath.floorMod(-4L, -3));
+ assertEquals(2, StrictMath.floorMod(-4L, 3));
+ assertEquals(-2, StrictMath.floorMod(4L, -3));
+ }
+
+ private static void assertEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected <" + expected + "> but was <" + actual + '>');
+ }
+ }
+
+ private static void assertEquals(long expected, long actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected <" + expected + "> but was <" + actual + '>');
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 03e199e..62ada86 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -107,6 +107,7 @@
public static final String GENERATED_PROTO_BUILD_DIR = GENERATED_TEST_BUILD_DIR + "proto/";
public static final String SMALI_DIR = TESTS_DIR + "smali/";
public static final String SMALI_BUILD_DIR = TESTS_BUILD_DIR + "smali/";
+ public static final String JAVA_CLASSES_DIR = BUILD_DIR + "classes/java/";
public static final String LINE_SEPARATOR = StringUtils.LINE_SEPARATOR;
public static final String CLASSPATH_SEPARATOR = File.pathSeparator;
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/MathBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/MathBackportJava9Test.java
new file mode 100644
index 0000000..27e34ab
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/MathBackportJava9Test.java
@@ -0,0 +1,31 @@
+// 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.desugar.backports;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public final class MathBackportJava9Test extends AbstractBackportTest {
+ @Parameters(name = "{0}")
+ public static Iterable<?> data() {
+ return getTestParameters().withDexRuntimes().build();
+ }
+
+ private static final Path TEST_JAR =
+ Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+
+ public MathBackportJava9Test(TestParameters parameters) {
+ super(parameters, Math.class, TEST_JAR, "backport.MathBackportJava9Main");
+ // TODO Once shipped in an actual API level, migrate to MathBackportTest
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/StrictMathBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/StrictMathBackportJava9Test.java
new file mode 100644
index 0000000..f4274c0
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/StrictMathBackportJava9Test.java
@@ -0,0 +1,31 @@
+// 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.desugar.backports;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public final class StrictMathBackportJava9Test extends AbstractBackportTest {
+ @Parameters(name = "{0}")
+ public static Iterable<?> data() {
+ return getTestParameters().withDexRuntimes().build();
+ }
+
+ private static final Path TEST_JAR =
+ Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+
+ public StrictMathBackportJava9Test(TestParameters parameters) {
+ super(parameters, Math.class, TEST_JAR, "backport.StrictMathBackportJava9Main");
+ // TODO Once shipped in an actual API level, migrate to MathBackportTest
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11MathTests.java b/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11MathTests.java
new file mode 100644
index 0000000..6e4aa4e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11MathTests.java
@@ -0,0 +1,111 @@
+// 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.desugar.corelib.corelibjdktests;
+
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class Jdk11MathTests extends TestBase {
+
+ private static final Path JDK_11_MATH_TESTS_DIR =
+ Paths.get(ToolHelper.JAVA_CLASSES_DIR + "jdk11MathTests");
+ private static final Path JDK_11_STRICT_MATH_TESTS_DIR =
+ Paths.get(ToolHelper.JAVA_CLASSES_DIR + "jdk11StrictMathTests");
+ private static final String DIVMOD = "DivModTests";
+ private static final String EXACTARITH = "ExactArithTests";
+ private static final String CLASS_SUFFIX = ".class";
+ private static final Path[] JDK_11_MATH_TEST_CLASS_FILES =
+ new Path[] {
+ JDK_11_MATH_TESTS_DIR.resolve(DIVMOD + CLASS_SUFFIX),
+ JDK_11_MATH_TESTS_DIR.resolve(EXACTARITH + CLASS_SUFFIX)
+ };
+ private static final Path[] JDK_11_STRICT_MATH_TEST_CLASS_FILES =
+ new Path[] {JDK_11_STRICT_MATH_TESTS_DIR.resolve(EXACTARITH + CLASS_SUFFIX)};
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withCfRuntime(CfVm.JDK11).build();
+ }
+
+ public Jdk11MathTests(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testD8MathExactArith() throws Exception {
+ Assume.assumeTrue(parameters.isDexRuntime());
+ testForD8()
+ .addProgramFiles(JDK_11_MATH_TEST_CLASS_FILES)
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), EXACTARITH)
+ .assertSuccessWithOutput("");
+ }
+
+ @Test
+ public void testD8MathDivMod() throws Exception {
+ Assume.assumeTrue(parameters.isDexRuntime());
+ testForD8()
+ .addProgramFiles(JDK_11_MATH_TEST_CLASS_FILES)
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), DIVMOD)
+ .assertSuccessWithOutput("");
+ }
+
+ @Test
+ public void testD8StrictMathExactArith() throws Exception {
+ Assume.assumeTrue(parameters.isDexRuntime());
+ testForD8()
+ .addProgramFiles(JDK_11_STRICT_MATH_TEST_CLASS_FILES)
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), EXACTARITH)
+ .assertSuccessWithOutput("");
+ }
+
+ @Test
+ public void testR8MathExactArith() throws Exception {
+ testForR8(parameters.getBackend())
+ .addKeepMainRule(DIVMOD)
+ .addKeepMainRule(EXACTARITH)
+ .addProgramFiles(JDK_11_MATH_TEST_CLASS_FILES)
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), EXACTARITH)
+ .assertSuccessWithOutput("");
+ }
+
+ @Test
+ public void testR8MathDivMod() throws Exception {
+ testForR8(parameters.getBackend())
+ .addKeepMainRule(DIVMOD)
+ .addKeepMainRule(EXACTARITH)
+ .addProgramFiles(JDK_11_MATH_TEST_CLASS_FILES)
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), DIVMOD)
+ .assertSuccessWithOutput("");
+ }
+
+ @Test
+ public void testR8StrictMathExactArith() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramFiles(JDK_11_STRICT_MATH_TEST_CLASS_FILES)
+ .addKeepMainRule(EXACTARITH)
+ .setMinApi(parameters.getRuntime())
+ .run(parameters.getRuntime(), EXACTARITH)
+ .assertSuccessWithOutput("");
+ }
+}