blob: cb64b6d5622d895c19bf9273799bd814ccc86e38 [file] [log] [blame]
// Copyright (c) 2021, 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 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 LongBackportJava9Test extends AbstractBackportTest {
@Parameters(name = "{0}")
public static Iterable<?> data() {
return TestBase.getTestParameters()
.withCfRuntimesStartingFromIncluding(CfVm.JDK9)
.withDexRuntimes()
.withAllApiLevelsAlsoForCf()
.build();
}
public LongBackportJava9Test(TestParameters parameters) {
super(parameters, Long.class, LongBackportJava9Main.class);
// Note: The methods in this test exist in android.jar from Android T. When R8 builds targeting
// Java 11 move these tests to LongBackportTest (out of examplesJava9).
ignoreInvokes("toString");
registerTarget(AndroidApiLevel.T, 17);
}
public static class LongBackportJava9Main {
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) {
testParseLongSubsequenceWithRadix();
testParseUnsignedLongSubsequenceWithRadix();
}
private static void testParseLongSubsequenceWithRadix() {
for (long value : interestingValues) {
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
for (String prefix : new String[] {"", "x", "xxx"}) {
for (String postfix : new String[] {"", "x", "xxx"}) {
String valueString = prefix + Long.toString(value, radix) + postfix;
int start = prefix.length();
int end = valueString.length() - postfix.length();
assertEquals(valueString, value, Long.parseLong(valueString, start, end, radix));
if (value > 0) {
valueString = prefix + "+" + Long.toString(value, radix) + postfix;
end++;
assertEquals(valueString, value, Long.parseLong(valueString, start, end, radix));
}
}
}
}
}
try {
throw new AssertionError(Long.parseLong("0", 0, 1, Character.MIN_RADIX - 1));
} catch (IllegalArgumentException expected) {
}
try {
throw new AssertionError(Long.parseLong("0", 0, 1, Character.MAX_RADIX + 1));
} catch (IllegalArgumentException expected) {
}
try {
throw new AssertionError(Long.parseLong("", 0, 0, 16));
} catch (NumberFormatException expected) {
}
try {
throw new AssertionError(Long.parseLong("-", 0, 1, 16));
} catch (NumberFormatException expected) {
}
try {
throw new AssertionError(Long.parseLong("+", 0, 1, 16));
} catch (NumberFormatException expected) {
}
try {
throw new AssertionError(Long.parseLong("+a", 0, 2, 10));
} catch (NumberFormatException expected) {
}
BigInteger overflow = new BigInteger("18446744073709551616");
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
for (String prefix : new String[] {"", "x", "xxx"}) {
for (String postfix : new String[] {"", "x", "xxx"}) {
String overflowString = prefix + overflow.toString(radix) + postfix;
int start = prefix.length();
int end = overflowString.length() - postfix.length();
try {
throw new AssertionError(Long.parseLong(overflowString, start, end, radix));
} catch (NumberFormatException expected) {
}
}
}
}
}
private static void testParseUnsignedLongSubsequenceWithRadix() {
for (long value : interestingValues) {
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
for (String prefix : new String[] {"", "x", "xxx"}) {
for (String postfix : new String[] {"", "x", "xxx"}) {
String valueString =
prefix + unsignedLongToBigInteger(value).toString(radix) + postfix;
int start = prefix.length();
int end = valueString.length() - postfix.length();
assertEquals(
valueString, value, Long.parseUnsignedLong(valueString, start, end, radix));
valueString =
prefix + "+" + unsignedLongToBigInteger(value).toString(radix) + postfix;
end++;
assertEquals(
valueString, value, Long.parseUnsignedLong(valueString, start, end, radix));
}
}
}
}
try {
throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MIN_RADIX - 1));
} catch (IllegalArgumentException expected) {
}
try {
throw new AssertionError(Long.parseUnsignedLong("0", 0, 1, Character.MAX_RADIX + 1));
} catch (IllegalArgumentException expected) {
}
try {
throw new AssertionError(Long.parseUnsignedLong("", 0, 0, 16));
} catch (NumberFormatException expected) {
}
try {
throw new AssertionError(Long.parseUnsignedLong("+", 0, 1, 16));
} catch (NumberFormatException expected) {
}
try {
throw new AssertionError(Long.parseUnsignedLong("+a", 0, 2, 10));
} catch (NumberFormatException expected) {
}
BigInteger overflow = new BigInteger("18446744073709551616");
for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
for (String prefix : new String[] {"", "x", "xxx", "+", "x+", "xxx+"}) {
for (String postfix : new String[] {"", "x", "xxx"}) {
String overflowString = prefix + overflow.toString(radix) + postfix;
int start = prefix.length();
int end = overflowString.length() - postfix.length();
try {
throw new AssertionError(Long.parseUnsignedLong(overflowString, start, end, radix));
} catch (NumberFormatException expected) {
}
}
}
}
}
private static BigInteger unsignedLongToBigInteger(long value) {
BigInteger bigInt = BigInteger.valueOf(value & 0x7fffffffffffffffL);
if (value < 0) {
bigInt = bigInt.setBit(Long.SIZE - 1);
}
return bigInt;
}
private static void assertEquals(String m, long expected, long actual) {
if (expected != actual) {
throw new AssertionError(m + " Expected <" + expected + "> but was <" + actual + '>');
}
}
}
}