1 /* 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import org.testng.annotations.DataProvider; 25 import org.testng.annotations.Test; 26 27 import java.math.BigInteger; 28 import java.util.ArrayList; 29 import java.util.Iterator; 30 import java.util.Arrays; 31 import java.util.List; 32 import java.util.function.LongFunction; 33 import java.util.function.Function; 34 35 import static org.testng.Assert.assertEquals; 36 37 /** 38 * @test 39 * @run testng IntegralPrimitiveToString 40 * @summary test string conversions for primitive integral types. 41 * @author Mike Duigou 42 */ 43 public class IntegralPrimitiveToString { 44 45 @Test(dataProvider="numbers") 46 public <N extends Number> void testToString(String description, 47 Function<N, BigInteger> converter, 48 Function<N, BigInteger> unsignedConverter, 49 N[] values, 50 Stringifier<N>[] stringifiers) { 51 System.out.printf("%s : conversions: %d values: %d\n", description, stringifiers.length, values.length); 52 for( N value : values) { 53 BigInteger asBigInt = converter.apply(value); 54 BigInteger asUnsignedBigInt = unsignedConverter.apply(value); 55 for(Stringifier<N> stringifier : stringifiers) { 56 stringifier.assertMatchingToString(value, asBigInt, asUnsignedBigInt, description); 57 } 58 } 59 } 60 61 static class Stringifier<N extends Number> { 62 final boolean signed; 63 final int radix; 64 final Function<N,String> toString; 65 Stringifier(boolean signed, int radix, Function<N,String> toString) { 66 this.signed = signed; 67 this.radix = radix; 68 this.toString = toString; 69 } 70 71 public void assertMatchingToString(N value, BigInteger asSigned, BigInteger asUnsigned, String description) { 72 String expected = signed 73 ? asSigned.toString(radix) 74 : asUnsigned.toString(radix); 75 76 String actual = toString.apply(value); 77 78 assertEquals(actual, expected, description + " conversion should be the same"); 79 } 80 } 81 82 @DataProvider(name="numbers", parallel=true) 83 public Iterator<Object[]> testSetProvider() { 84 85 return Arrays.asList( 86 new Object[] { "Byte", 87 (Function<Byte,BigInteger>) b -> BigInteger.valueOf((long) b), 88 (Function<Byte,BigInteger>) b -> BigInteger.valueOf(Integer.toUnsignedLong((byte) b)), 89 numberProvider((LongFunction<Byte>) l -> Byte.valueOf((byte) l), Byte.SIZE), 90 new Stringifier[] { 91 new Stringifier<Byte>(true, 10, b -> b.toString()), 92 new Stringifier<Byte>(true, 10, b -> Byte.toString(b)) 93 } 94 }, 95 new Object[] { "Short", 96 (Function<Short,BigInteger>) s -> BigInteger.valueOf((long) s), 97 (Function<Short,BigInteger>) s -> BigInteger.valueOf(Integer.toUnsignedLong((short) s)), 98 numberProvider((LongFunction<Short>) l -> Short.valueOf((short) l), Short.SIZE), 99 new Stringifier[] { 100 new Stringifier<Short>(true, 10, s -> s.toString()), 101 new Stringifier<Short>(true, 10, s -> Short.toString( s)) 102 } 103 }, 104 new Object[] { "Integer", 105 (Function<Integer,BigInteger>) i -> BigInteger.valueOf((long) i), 106 (Function<Integer,BigInteger>) i -> BigInteger.valueOf(Integer.toUnsignedLong(i)), 107 numberProvider((LongFunction<Integer>) l -> Integer.valueOf((int) l), Integer.SIZE), 108 new Stringifier[] { 109 new Stringifier<Integer>(true, 10, i -> i.toString()), 110 new Stringifier<Integer>(true, 10, i -> Integer.toString(i)), 111 new Stringifier<Integer>(false, 2, Integer::toBinaryString), 112 new Stringifier<Integer>(false, 16, Integer::toHexString), 113 new Stringifier<Integer>(false, 8, Integer::toOctalString), 114 new Stringifier<Integer>(true, 2, i -> Integer.toString(i, 2)), 115 new Stringifier<Integer>(true, 8, i -> Integer.toString(i, 8)), 116 new Stringifier<Integer>(true, 10, i -> Integer.toString(i, 10)), 117 new Stringifier<Integer>(true, 16, i -> Integer.toString(i, 16)), 118 new Stringifier<Integer>(true, Character.MAX_RADIX, i -> Integer.toString(i, Character.MAX_RADIX)), 119 new Stringifier<Integer>(false, 10, i -> Integer.toUnsignedString(i)), 120 new Stringifier<Integer>(false, 2, i -> Integer.toUnsignedString(i, 2)), 121 new Stringifier<Integer>(false, 8, i -> Integer.toUnsignedString(i, 8)), 122 new Stringifier<Integer>(false, 10, i -> Integer.toUnsignedString(i, 10)), 123 new Stringifier<Integer>(false, 16, i -> Integer.toUnsignedString(i, 16)), 124 new Stringifier<Integer>(false, Character.MAX_RADIX, i -> Integer.toUnsignedString(i, Character.MAX_RADIX)) 125 } 126 }, 127 new Object[] { "Long", 128 (Function<Long, BigInteger>) BigInteger::valueOf, 129 (Function<Long, BigInteger>) l -> { 130 if (l >= 0) { 131 return BigInteger.valueOf((long) l); 132 } else { 133 int upper = (int)(l >>> 32); 134 int lower = (int) (long) l; 135 136 // return (upper << 32) + lower 137 return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32). 138 add(BigInteger.valueOf(Integer.toUnsignedLong(lower))); 139 } 140 }, 141 numberProvider((LongFunction<Long>) Long::valueOf, Long.SIZE), 142 new Stringifier[] { 143 new Stringifier<Long>(true, 10, l -> l.toString()), 144 new Stringifier<Long>(true, 10, l -> Long.toString(l)), 145 new Stringifier<Long>(false, 2, Long::toBinaryString), 146 new Stringifier<Long>(false, 16, Long::toHexString), 147 new Stringifier<Long>(false, 8, Long::toOctalString), 148 new Stringifier<Long>(true, 2, l -> Long.toString(l, 2)), 149 new Stringifier<Long>(true, 8, l -> Long.toString(l, 8)), 150 new Stringifier<Long>(true, 10, l -> Long.toString(l, 10)), 151 new Stringifier<Long>(true, 16, l -> Long.toString(l, 16)), 152 new Stringifier<Long>(true, Character.MAX_RADIX, l -> Long.toString(l, Character.MAX_RADIX)), 153 new Stringifier<Long>(false, 10, Long::toUnsignedString), 154 new Stringifier<Long>(false, 2, l -> Long.toUnsignedString(l, 2)), 155 new Stringifier<Long>(false, 8, l-> Long.toUnsignedString(l, 8)), 156 new Stringifier<Long>(false, 10, l -> Long.toUnsignedString(l, 10)), 157 new Stringifier<Long>(false, 16, l -> Long.toUnsignedString(l, 16)), 158 new Stringifier<Long>(false, Character.MAX_RADIX, l -> Long.toUnsignedString(l, Character.MAX_RADIX)) 159 } 160 } 161 ).iterator(); 162 } 163 private static final long[] SOME_PRIMES = { 164 3L, 5L, 7L, 11L, 13L, 17L, 19L, 23L, 29L, 31L, 37L, 41L, 43L, 47L, 53L, 165 59L, 61L, 71L, 73L, 79L, 83L, 89L, 97L, 101L, 103L, 107L, 109L, 113L, 166 5953L, 5981L, 5987L, 6007L, 6011L, 6029L, 6037L, 6043L, 6047L, 6053L, 167 16369L, 16381L, 16411L, 32749L, 32771L, 65521L, 65537L, 168 (long) Integer.MAX_VALUE }; 169 170 public <N extends Number> N[] numberProvider(LongFunction<N> boxer, int bits, N... extras) { 171 List<N> numbers = new ArrayList<>(); 172 173 for(int bitmag = 0; bitmag < bits; bitmag++) { 174 long value = 1L << bitmag; 175 numbers.add(boxer.apply(value)); 176 numbers.add(boxer.apply(value - 1)); 177 numbers.add(boxer.apply(value + 1)); 178 numbers.add(boxer.apply(-value)); 179 for(int divisor = 0; divisor < SOME_PRIMES.length && value < SOME_PRIMES[divisor]; divisor++) { 180 numbers.add(boxer.apply(value - SOME_PRIMES[divisor])); 181 numbers.add(boxer.apply(value + SOME_PRIMES[divisor])); 182 numbers.add(boxer.apply(value * SOME_PRIMES[divisor])); 183 numbers.add(boxer.apply(value / SOME_PRIMES[divisor])); 184 numbers.add(boxer.apply(value | SOME_PRIMES[divisor])); 185 numbers.add(boxer.apply(value & SOME_PRIMES[divisor])); 186 numbers.add(boxer.apply(value ^ SOME_PRIMES[divisor])); 187 } 188 } 189 190 numbers.addAll(Arrays.asList(extras)); 191 192 return (N[]) numbers.toArray(new Number[numbers.size()]); 193 } 194 }