blob: b71e4aceb9dd9c8deb6ea071cf58b7fb239e373b [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 backport;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.desugar.backports.AbstractBackportTest;
import java.math.BigInteger;
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 TestBase.getTestParameters()
.withDexRuntimes()
.withCfRuntimesStartingFromIncluding(CfVm.JDK9)
.withAllApiLevelsAlsoForCf()
.build();
}
public StrictMathBackportJava9Test(TestParameters parameters) {
super(parameters, Math.class, StrictMathBackportJava9Main.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 StrictMathBackportTest.
}
public static class StrictMathBackportJava9Main {
public static void main(String[] args) {
testMultiplyExactLongInt();
testMultiplyFull();
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 testMultiplyFull() {
assertEquals(8L, StrictMath.multiplyFull(2, 4));
assertEquals(
4611686014132420609L, StrictMath.multiplyFull(Integer.MAX_VALUE, Integer.MAX_VALUE));
assertEquals(
-4611686016279904256L, StrictMath.multiplyFull(Integer.MAX_VALUE, Integer.MIN_VALUE));
assertEquals(
4611686018427387904L, StrictMath.multiplyFull(Integer.MIN_VALUE, Integer.MIN_VALUE));
}
public static void testMultiplyHigh() {
long[] interestingValues = {
Long.MIN_VALUE,
Long.MAX_VALUE,
Integer.MIN_VALUE,
Integer.MAX_VALUE,
Short.MIN_VALUE,
Short.MAX_VALUE,
Byte.MIN_VALUE,
Byte.MAX_VALUE,
0L,
-1L,
1L,
-42L,
42L
};
for (long x : interestingValues) {
for (long y : interestingValues) {
long expected =
BigInteger.valueOf(x).multiply(BigInteger.valueOf(y)).shiftRight(64).longValue();
assertEquals(expected, StrictMath.multiplyHigh(x, y));
}
}
}
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 + '>');
}
}
}
}