|
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 } |