3789983e89
Reviewed-by: darcy, ihse
195 lines
9.3 KiB
Java
195 lines
9.3 KiB
Java
/*
|
|
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
import org.testng.annotations.DataProvider;
|
|
import org.testng.annotations.Test;
|
|
|
|
import java.math.BigInteger;
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.function.LongFunction;
|
|
import java.util.function.Function;
|
|
|
|
import static org.testng.Assert.assertEquals;
|
|
|
|
/**
|
|
* @test
|
|
* @run testng IntegralPrimitiveToString
|
|
* @summary test string conversions for primitive integral types.
|
|
* @author Mike Duigou
|
|
*/
|
|
public class IntegralPrimitiveToString {
|
|
|
|
@Test(dataProvider="numbers")
|
|
public <N extends Number> void testToString(String description,
|
|
Function<N, BigInteger> converter,
|
|
Function<N, BigInteger> unsignedConverter,
|
|
N[] values,
|
|
Stringifier<N>[] stringifiers) {
|
|
System.out.printf("%s : conversions: %d values: %d\n", description, stringifiers.length, values.length);
|
|
for( N value : values) {
|
|
BigInteger asBigInt = converter.apply(value);
|
|
BigInteger asUnsignedBigInt = unsignedConverter.apply(value);
|
|
for(Stringifier<N> stringifier : stringifiers) {
|
|
stringifier.assertMatchingToString(value, asBigInt, asUnsignedBigInt, description);
|
|
}
|
|
}
|
|
}
|
|
|
|
static class Stringifier<N extends Number> {
|
|
final boolean signed;
|
|
final int radix;
|
|
final Function<N,String> toString;
|
|
Stringifier(boolean signed, int radix, Function<N,String> toString) {
|
|
this.signed = signed;
|
|
this.radix = radix;
|
|
this.toString = toString;
|
|
}
|
|
|
|
public void assertMatchingToString(N value, BigInteger asSigned, BigInteger asUnsigned, String description) {
|
|
String expected = signed
|
|
? asSigned.toString(radix)
|
|
: asUnsigned.toString(radix);
|
|
|
|
String actual = toString.apply(value);
|
|
|
|
assertEquals(actual, expected, description + " conversion should be the same");
|
|
}
|
|
}
|
|
|
|
@DataProvider(name="numbers", parallel=true)
|
|
public Iterator<Object[]> testSetProvider() {
|
|
|
|
return Arrays.asList(
|
|
new Object[] { "Byte",
|
|
(Function<Byte,BigInteger>) b -> BigInteger.valueOf((long) b),
|
|
(Function<Byte,BigInteger>) b -> BigInteger.valueOf(Integer.toUnsignedLong((byte) b)),
|
|
numberProvider((LongFunction<Byte>) l -> Byte.valueOf((byte) l), Byte.SIZE),
|
|
new Stringifier[] {
|
|
new Stringifier<Byte>(true, 10, b -> b.toString()),
|
|
new Stringifier<Byte>(true, 10, b -> Byte.toString(b))
|
|
}
|
|
},
|
|
new Object[] { "Short",
|
|
(Function<Short,BigInteger>) s -> BigInteger.valueOf((long) s),
|
|
(Function<Short,BigInteger>) s -> BigInteger.valueOf(Integer.toUnsignedLong((short) s)),
|
|
numberProvider((LongFunction<Short>) l -> Short.valueOf((short) l), Short.SIZE),
|
|
new Stringifier[] {
|
|
new Stringifier<Short>(true, 10, s -> s.toString()),
|
|
new Stringifier<Short>(true, 10, s -> Short.toString( s))
|
|
}
|
|
},
|
|
new Object[] { "Integer",
|
|
(Function<Integer,BigInteger>) i -> BigInteger.valueOf((long) i),
|
|
(Function<Integer,BigInteger>) i -> BigInteger.valueOf(Integer.toUnsignedLong(i)),
|
|
numberProvider((LongFunction<Integer>) l -> Integer.valueOf((int) l), Integer.SIZE),
|
|
new Stringifier[] {
|
|
new Stringifier<Integer>(true, 10, i -> i.toString()),
|
|
new Stringifier<Integer>(true, 10, i -> Integer.toString(i)),
|
|
new Stringifier<Integer>(false, 2, Integer::toBinaryString),
|
|
new Stringifier<Integer>(false, 16, Integer::toHexString),
|
|
new Stringifier<Integer>(false, 8, Integer::toOctalString),
|
|
new Stringifier<Integer>(true, 2, i -> Integer.toString(i, 2)),
|
|
new Stringifier<Integer>(true, 8, i -> Integer.toString(i, 8)),
|
|
new Stringifier<Integer>(true, 10, i -> Integer.toString(i, 10)),
|
|
new Stringifier<Integer>(true, 16, i -> Integer.toString(i, 16)),
|
|
new Stringifier<Integer>(true, Character.MAX_RADIX, i -> Integer.toString(i, Character.MAX_RADIX)),
|
|
new Stringifier<Integer>(false, 10, i -> Integer.toUnsignedString(i)),
|
|
new Stringifier<Integer>(false, 2, i -> Integer.toUnsignedString(i, 2)),
|
|
new Stringifier<Integer>(false, 8, i -> Integer.toUnsignedString(i, 8)),
|
|
new Stringifier<Integer>(false, 10, i -> Integer.toUnsignedString(i, 10)),
|
|
new Stringifier<Integer>(false, 16, i -> Integer.toUnsignedString(i, 16)),
|
|
new Stringifier<Integer>(false, Character.MAX_RADIX, i -> Integer.toUnsignedString(i, Character.MAX_RADIX))
|
|
}
|
|
},
|
|
new Object[] { "Long",
|
|
(Function<Long, BigInteger>) BigInteger::valueOf,
|
|
(Function<Long, BigInteger>) l -> {
|
|
if (l >= 0) {
|
|
return BigInteger.valueOf((long) l);
|
|
} else {
|
|
int upper = (int)(l >>> 32);
|
|
int lower = (int) (long) l;
|
|
|
|
// return (upper << 32) + lower
|
|
return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
|
|
add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
|
|
}
|
|
},
|
|
numberProvider((LongFunction<Long>) Long::valueOf, Long.SIZE),
|
|
new Stringifier[] {
|
|
new Stringifier<Long>(true, 10, l -> l.toString()),
|
|
new Stringifier<Long>(true, 10, l -> Long.toString(l)),
|
|
new Stringifier<Long>(false, 2, Long::toBinaryString),
|
|
new Stringifier<Long>(false, 16, Long::toHexString),
|
|
new Stringifier<Long>(false, 8, Long::toOctalString),
|
|
new Stringifier<Long>(true, 2, l -> Long.toString(l, 2)),
|
|
new Stringifier<Long>(true, 8, l -> Long.toString(l, 8)),
|
|
new Stringifier<Long>(true, 10, l -> Long.toString(l, 10)),
|
|
new Stringifier<Long>(true, 16, l -> Long.toString(l, 16)),
|
|
new Stringifier<Long>(true, Character.MAX_RADIX, l -> Long.toString(l, Character.MAX_RADIX)),
|
|
new Stringifier<Long>(false, 10, Long::toUnsignedString),
|
|
new Stringifier<Long>(false, 2, l -> Long.toUnsignedString(l, 2)),
|
|
new Stringifier<Long>(false, 8, l-> Long.toUnsignedString(l, 8)),
|
|
new Stringifier<Long>(false, 10, l -> Long.toUnsignedString(l, 10)),
|
|
new Stringifier<Long>(false, 16, l -> Long.toUnsignedString(l, 16)),
|
|
new Stringifier<Long>(false, Character.MAX_RADIX, l -> Long.toUnsignedString(l, Character.MAX_RADIX))
|
|
}
|
|
}
|
|
).iterator();
|
|
}
|
|
private static final long[] SOME_PRIMES = {
|
|
3L, 5L, 7L, 11L, 13L, 17L, 19L, 23L, 29L, 31L, 37L, 41L, 43L, 47L, 53L,
|
|
59L, 61L, 71L, 73L, 79L, 83L, 89L, 97L, 101L, 103L, 107L, 109L, 113L,
|
|
5953L, 5981L, 5987L, 6007L, 6011L, 6029L, 6037L, 6043L, 6047L, 6053L,
|
|
16369L, 16381L, 16411L, 32749L, 32771L, 65521L, 65537L,
|
|
(long) Integer.MAX_VALUE };
|
|
|
|
public <N extends Number> N[] numberProvider(LongFunction<N> boxer, int bits, N... extras) {
|
|
List<N> numbers = new ArrayList<>();
|
|
|
|
for(int bitmag = 0; bitmag < bits; bitmag++) {
|
|
long value = 1L << bitmag;
|
|
numbers.add(boxer.apply(value));
|
|
numbers.add(boxer.apply(value - 1));
|
|
numbers.add(boxer.apply(value + 1));
|
|
numbers.add(boxer.apply(-value));
|
|
for(int divisor = 0; divisor < SOME_PRIMES.length && value < SOME_PRIMES[divisor]; divisor++) {
|
|
numbers.add(boxer.apply(value - SOME_PRIMES[divisor]));
|
|
numbers.add(boxer.apply(value + SOME_PRIMES[divisor]));
|
|
numbers.add(boxer.apply(value * SOME_PRIMES[divisor]));
|
|
numbers.add(boxer.apply(value / SOME_PRIMES[divisor]));
|
|
numbers.add(boxer.apply(value | SOME_PRIMES[divisor]));
|
|
numbers.add(boxer.apply(value & SOME_PRIMES[divisor]));
|
|
numbers.add(boxer.apply(value ^ SOME_PRIMES[divisor]));
|
|
}
|
|
}
|
|
|
|
numbers.addAll(Arrays.asList(extras));
|
|
|
|
return (N[]) numbers.toArray(new Number[numbers.size()]);
|
|
}
|
|
}
|