blob: f8a6ad80833489efd208dc0cb38c0a2bfb4f383b [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 com.android.tools.r8.desugar.backports;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.AndroidApiLevel;
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 LongBackportTest extends AbstractBackportTest {
@Parameters(name = "{0}")
public static Iterable<?> data() {
return getTestParameters()
.withAllRuntimesAndApiLevels()
.build();
}
public LongBackportTest(TestParameters parameters) {
super(parameters, Long.class, Main.class);
registerTarget(AndroidApiLevel.O, 47);
registerTarget(AndroidApiLevel.N, 11);
registerTarget(AndroidApiLevel.K, 7);
}
static final class Main extends MiniAssert {
private static final 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
};
public static void main(String[] args) {
testHashCode();
testCompare();
testMax();
testMin();
testSum();
testCompareUnsigned();
testDivideUnsigned();
testRemainderUnsigned();
testParseUnsignedLong();
testParseUnsignedLongWithRadix();
testToUnsignedString();
testToUnsignedStringWithRadix();
}
private static void testHashCode() {
for (long value : interestingValues) {
assertEquals(expectedHashCode(value), Long.hashCode(value));
}
}
private static void testCompare() {
assertTrue(Long.compare(1, 0) > 0);
assertTrue(Long.compare(0, 0) == 0);
assertTrue(Long.compare(0, 1) < 0);
assertTrue(Long.compare(Long.MIN_VALUE, Long.MAX_VALUE) < 0);
assertTrue(Long.compare(Long.MAX_VALUE, Long.MIN_VALUE) > 0);
assertTrue(Long.compare(Long.MIN_VALUE, Long.MIN_VALUE) == 0);
assertTrue(Long.compare(Long.MAX_VALUE, Long.MAX_VALUE) == 0);
}
private static void testMax() {
for (long x : interestingValues) {
for (long y : interestingValues) {
assertEquals(Math.max(x, y), Long.max(x, y));
}
}
}
private static void testMin() {
for (long x : interestingValues) {
for (long y : interestingValues) {
assertEquals(Math.min(x, y), Long.min(x, y));
}
}
}
private static void testSum() {
for (long x : interestingValues) {
for (long y : interestingValues) {
assertEquals(x + y, Long.sum(x, y));
}
}
}
private static void testCompareUnsigned() {
assertTrue(Long.compareUnsigned(0, 0) == 0);
assertTrue(Long.compareUnsigned(0, Long.MAX_VALUE) < 0);
assertTrue(Long.compareUnsigned(0, Long.MIN_VALUE) < 0);
assertTrue(Long.compareUnsigned(0, -1) < 0);
assertTrue(Long.compareUnsigned(Long.MAX_VALUE, 0) > 0);
assertTrue(Long.compareUnsigned(Long.MAX_VALUE, Long.MAX_VALUE) == 0);
assertTrue(Long.compareUnsigned(Long.MAX_VALUE, Long.MIN_VALUE) < 0);
assertTrue(Long.compareUnsigned(Long.MAX_VALUE, -1) < 0);
assertTrue(Long.compareUnsigned(Long.MIN_VALUE, 0) > 0);
assertTrue(Long.compareUnsigned(Long.MIN_VALUE, Long.MAX_VALUE) > 0);
assertTrue(Long.compareUnsigned(Long.MIN_VALUE, Long.MIN_VALUE) == 0);
assertTrue(Long.compareUnsigned(Long.MIN_VALUE, -1) < 0);
assertTrue(Long.compareUnsigned(-1, 0) > 0);
assertTrue(Long.compareUnsigned(-1, Long.MAX_VALUE) > 0);
assertTrue(Long.compareUnsigned(-1, Long.MIN_VALUE) > 0);
assertTrue(Long.compareUnsigned(-1, -1) == 0);
}
private static void testDivideUnsigned() {
for (long x : interestingValues) {
for (long y : interestingValues) {
if (y == 0L) continue;
BigInteger xUnsigned = unsignedLongToBigInteger(x);
BigInteger yUnsigned = unsignedLongToBigInteger(y);
long expected = xUnsigned.divide(yUnsigned).longValue();
assertEquals(expected, Long.divideUnsigned(x, y));
}
}
try {
throw new AssertionError(Long.divideUnsigned(1L, 0L));
} catch (ArithmeticException expected) {
}
}
private static void testRemainderUnsigned() {
for (long x : interestingValues) {
for (long y : interestingValues) {
if (y == 0L) continue;
BigInteger xUnsigned = unsignedLongToBigInteger(x);
BigInteger yUnsigned = unsignedLongToBigInteger(y);
long expected = xUnsigned.remainder(yUnsigned).longValue();
assertEquals(expected, Long.remainderUnsigned(x, y));
}
}
try {
throw new AssertionError(Long.remainderUnsigned(1L, 0L));
} catch (ArithmeticException expected) {
}
}
private static void testParseUnsignedLong() {
for (long value : interestingValues) {
String valueString = unsignedLongToBigInteger(value).toString();
assertEquals(value, Long.parseUnsignedLong(valueString));
assertEquals(value, Long.parseUnsignedLong("+" + valueString));
}
try {
throw new AssertionError(Long.parseUnsignedLong("18446744073709551616"));
} catch (NumberFormatException expected) {
}
try {
throw new AssertionError(Long.parseUnsignedLong(""));
} catch (NumberFormatException expected) {
}
try {
throw new AssertionError(Long.parseUnsignedLong("+"));
} catch (NumberFormatException expected) {
}
}
private static void testParseUnsignedLongWithRadix() {
for (long value : interestingValues) {
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
String valueString = unsignedLongToBigInteger(value).toString(radix);
assertEquals(value, Long.parseUnsignedLong(valueString, radix));
assertEquals(value, Long.parseUnsignedLong("+" + valueString, radix));
}
}
try {
throw new AssertionError(Long.parseUnsignedLong("0", Character.MIN_RADIX - 1));
} catch (IllegalArgumentException expected) {
}
try {
throw new AssertionError(Long.parseUnsignedLong("0", Character.MAX_RADIX + 1));
} catch (IllegalArgumentException expected) {
}
try {
throw new AssertionError(Long.parseUnsignedLong("", 16));
} catch (NumberFormatException expected) {
}
try {
throw new AssertionError(Long.parseUnsignedLong("+", 16));
} catch (NumberFormatException expected) {
}
BigInteger overflow = new BigInteger("18446744073709551616");
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
String overflowString = overflow.toString(radix);
try {
throw new AssertionError(Long.parseUnsignedLong(overflowString, radix));
} catch (NumberFormatException expected) {
}
}
}
private static void testToUnsignedString() {
for (long value : interestingValues) {
assertEquals(unsignedLongToBigInteger(value).toString(), Long.toUnsignedString(value));
}
}
private static void testToUnsignedStringWithRadix() {
for (long value : interestingValues) {
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
assertEquals(unsignedLongToBigInteger(value).toString(radix),
Long.toUnsignedString(value, radix));
}
// Invalid radix values are ignored and 10 is used.
assertEquals(unsignedLongToBigInteger(value).toString(),
Long.toUnsignedString(value, Character.MIN_RADIX - 1));
assertEquals(unsignedLongToBigInteger(value).toString(),
Long.toUnsignedString(value, Character.MAX_RADIX + 1));
}
}
@IgnoreInvokes
private static int expectedHashCode(long value) {
return Long.valueOf(value).hashCode();
}
private static BigInteger unsignedLongToBigInteger(long value) {
BigInteger bigInt = BigInteger.valueOf(value & 0x7fffffffffffffffL);
if (value < 0) {
bigInt = bigInt.setBit(Long.SIZE - 1);
}
return bigInt;
}
}
}