• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package libcore.java.lang;
18 
19 import static org.junit.Assert.*;
20 
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.junit.runners.JUnit4;
24 
25 import java.lang.invoke.MethodHandle;
26 import java.lang.invoke.MethodHandles;
27 import java.lang.invoke.MethodType;
28 import java.util.Properties;
29 
30 @RunWith(JUnit4.class)
31 public class IntegerTest {
32     static final int[] INT_VALUES = {0, 1, 23, 456, 0x7fff_ffff, 0x8000_0000, 0xffff_ffff};
33 
34     static final long[] LONG_VALUES = {
35         0x1_0000_0000L, (long) Integer.MIN_VALUE - 1L, Long.MIN_VALUE, Long.MAX_VALUE
36     };
37 
38     @Test
testSystemProperties()39     public void testSystemProperties() {
40         Properties originalProperties = System.getProperties();
41         try {
42             Properties testProperties = new Properties();
43             testProperties.put("testIncInt", "notInt");
44             System.setProperties(testProperties);
45             assertNull("returned incorrect default Integer", Integer.getInteger("testIncInt"));
46             assertEquals(new Integer(4), Integer.getInteger("testIncInt", 4));
47             assertEquals(new Integer(4), Integer.getInteger("testIncInt", new Integer(4)));
48         } finally {
49             System.setProperties(originalProperties);
50         }
51     }
52 
53     @Test
testCompare()54     public void testCompare() throws Exception {
55         final int min = Integer.MIN_VALUE;
56         final int zero = 0;
57         final int max = Integer.MAX_VALUE;
58         assertTrue(Integer.compare(max, max) == 0);
59         assertTrue(Integer.compare(min, min) == 0);
60         assertTrue(Integer.compare(zero, zero) == 0);
61         assertTrue(Integer.compare(max, zero) > 0);
62         assertTrue(Integer.compare(max, min) > 0);
63         assertTrue(Integer.compare(zero, max) < 0);
64         assertTrue(Integer.compare(zero, min) > 0);
65         assertTrue(Integer.compare(min, zero) < 0);
66         assertTrue(Integer.compare(min, max) < 0);
67     }
68 
69     @Test
70     public void testParseInt() throws Exception {
71         assertEquals(0, Integer.parseInt("+0", 10));
72         assertEquals(473, Integer.parseInt("+473", 10));
73         assertEquals(255, Integer.parseInt("+FF", 16));
74         assertEquals(102, Integer.parseInt("+1100110", 2));
75         assertEquals(2147483647, Integer.parseInt("+2147483647", 10));
76         assertEquals(411787, Integer.parseInt("Kona", 27));
77         assertEquals(411787, Integer.parseInt("+Kona", 27));
78         assertEquals(-145, Integer.parseInt("-145", 10));
79 
80         // multiple sign chars
81         assertThrows(NumberFormatException.class, () -> Integer.parseInt("--1", 10));
82         assertThrows(NumberFormatException.class, () -> Integer.parseInt("++1", 10));
83 
84         // base too small
85         assertThrows(NumberFormatException.class, () -> Integer.parseInt("Kona", 10));
86     }
87 
88     @Test
testDecodeInt()89     public void testDecodeInt() throws Exception {
90         assertEquals(0, Integer.decode("+0").intValue());
91         assertEquals(473, Integer.decode("+473").intValue());
92         assertEquals(255, Integer.decode("+0xFF").intValue());
93         assertEquals(16, Integer.decode("+020").intValue());
94         assertEquals(2147483647, Integer.decode("+2147483647").intValue());
95         assertEquals(-73, Integer.decode("-73").intValue());
96         assertEquals(-255, Integer.decode("-0xFF").intValue());
97         assertEquals(255, Integer.decode("+#FF").intValue());
98         assertEquals(-255, Integer.decode("-#FF").intValue());
99 
100         assertThrows(NumberFormatException.class, () -> Integer.decode("--1"));
101         assertThrows(NumberFormatException.class, () -> Integer.decode("++1"));
102         assertThrows(NumberFormatException.class, () -> Integer.decode("-+1"));
103         assertThrows(NumberFormatException.class, () -> Integer.decode("Kona"));
104     }
105 
106     /*
107     public void testParsePositiveInt() throws Exception {
108       assertEquals(0, Integer.parsePositiveInt("0", 10));
109       assertEquals(473, Integer.parsePositiveInt("473", 10));
110       assertEquals(255, Integer.parsePositiveInt("FF", 16));
111 
112       try {
113         Integer.parsePositiveInt("-1", 10);
114         fail();
115       } catch (NumberFormatException e) {}
116 
117       try {
118         Integer.parsePositiveInt("+1", 10);
119         fail();
120       } catch (NumberFormatException e) {}
121 
122       try {
123         Integer.parsePositiveInt("+0", 16);
124         fail();
125       } catch (NumberFormatException e) {}
126     }
127     */
128 
129     @Test
testStaticHashCode()130     public void testStaticHashCode() {
131         assertEquals(Integer.valueOf(567).hashCode(), Integer.hashCode(567));
132     }
133 
134     @Test
testMax()135     public void testMax() {
136         int a = 567;
137         int b = 578;
138         assertEquals(Math.max(a, b), Integer.max(a, b));
139     }
140 
141     @Test
testMin()142     public void testMin() {
143         int a = 567;
144         int b = 578;
145         assertEquals(Math.min(a, b), Integer.min(a, b));
146     }
147 
148     @Test
testSum()149     public void testSum() {
150         int a = 567;
151         int b = 578;
152         assertEquals(a + b, Integer.sum(a, b));
153     }
154 
155     @Test
testBYTES()156     public void testBYTES() {
157         assertEquals(4, Integer.BYTES);
158     }
159 
160     @Test
testCompareUnsigned()161     public void testCompareUnsigned() {
162         for (int i = 0; i < INT_VALUES.length; ++i) {
163             for (int j = 0; j < INT_VALUES.length; ++j) {
164                 assertEquals(
165                         Integer.compare(i, j),
166                         Integer.compareUnsigned(INT_VALUES[i], INT_VALUES[j]));
167             }
168         }
169     }
170 
171     @Test
testDivideAndRemainderUnsigned()172     public void testDivideAndRemainderUnsigned() {
173         long[] vals = {1L, 23L, 456L, 0x7fff_ffffL, 0x8000_0000L, 0xffff_ffffL};
174 
175         for (long dividend : vals) {
176             for (long divisor : vals) {
177                 int uq = Integer.divideUnsigned((int) dividend, (int) divisor);
178                 int ur = Integer.remainderUnsigned((int) dividend, (int) divisor);
179                 assertEquals((int) (dividend / divisor), uq);
180                 assertEquals((int) (dividend % divisor), ur);
181                 assertEquals((int) dividend, uq * (int) divisor + ur);
182             }
183         }
184 
185         for (long dividend : vals) {
186             assertThrows(
187                     ArithmeticException.class, () -> Integer.divideUnsigned((int) dividend, 0));
188             assertThrows(
189                     ArithmeticException.class, () -> Integer.remainderUnsigned((int) dividend, 0));
190         }
191     }
192 
193     @Test
testParseUnsignedInt()194     public void testParseUnsignedInt() {
195         for (int value : INT_VALUES) {
196             // Special radices
197             assertEquals(value, Integer.parseUnsignedInt(Integer.toBinaryString(value), 2));
198             assertEquals(value, Integer.parseUnsignedInt(Integer.toOctalString(value), 8));
199             assertEquals(value, Integer.parseUnsignedInt(Integer.toUnsignedString(value)));
200             assertEquals(value, Integer.parseUnsignedInt(Integer.toHexString(value), 16));
201 
202             for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
203                 assertEquals(
204                         value,
205                         Integer.parseUnsignedInt(Integer.toUnsignedString(value, radix), radix));
206             }
207         }
208 
209         for (long longValue : LONG_VALUES) {
210             // Special radices
211             assertThrows(
212                     NumberFormatException.class,
213                     () -> Integer.parseUnsignedInt(Long.toBinaryString(longValue), 2));
214             assertThrows(
215                     NumberFormatException.class,
216                     () -> Integer.parseUnsignedInt(Long.toOctalString(longValue), 8));
217             assertThrows(
218                     NumberFormatException.class,
219                     () -> Integer.parseUnsignedInt(Long.toUnsignedString(longValue), 10));
220             assertThrows(
221                     NumberFormatException.class,
222                     () -> Integer.parseUnsignedInt(Long.toHexString(longValue), 16));
223             for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
224                 final int r = radix;
225                 assertThrows(
226                         NumberFormatException.class,
227                         () -> Integer.parseUnsignedInt(Long.toUnsignedString(longValue, r), r));
228             }
229         }
230 
231         assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt("-1"));
232         assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt("123", 2));
233         assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt(null));
234         assertThrows(
235                 NumberFormatException.class,
236                 () -> Integer.parseUnsignedInt("0", Character.MAX_RADIX + 1));
237         assertThrows(
238                 NumberFormatException.class,
239                 () -> Integer.parseUnsignedInt("0", Character.MIN_RADIX - 1));
240     }
241 
242     @Test
testParseUnsignedIntSubstring()243     public void testParseUnsignedIntSubstring() {
244         final String LEFT = "1";
245         final String RIGHT = "0";
246 
247         for (int ii = 0; ii < 8; ii = 2 * ii + 1) {
248             for (int jj = 0; jj < 8; jj = 2 * jj + 1) {
249                 final int i = ii; // final for use in lambdas
250                 final int j = jj; // final for use in lambdas
251                 final String leftPad = LEFT.repeat(i);
252                 final String rightPad = RIGHT.repeat(j);
253                 for (int value : INT_VALUES) {
254                     String binary = leftPad + Integer.toBinaryString(value) + rightPad;
255                     assertEquals(
256                             value, Integer.parseUnsignedInt(binary, i, binary.length() - j, 2));
257 
258                     String octal = leftPad + Integer.toOctalString(value) + rightPad;
259                     assertEquals(value, Integer.parseUnsignedInt(octal, i, octal.length() - j, 8));
260 
261                     String denary = leftPad + Integer.toUnsignedString(value) + rightPad;
262                     assertEquals(
263                             value, Integer.parseUnsignedInt(denary, i, denary.length() - j, 10));
264 
265                     String hex = leftPad + Integer.toHexString(value) + rightPad;
266                     assertEquals(value, Integer.parseUnsignedInt(hex, i, hex.length() - j, 16));
267 
268                     for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
269                         String arb = leftPad + Integer.toUnsignedString(value, radix) + rightPad;
270                         assertEquals(
271                                 value, Integer.parseUnsignedInt(arb, i, arb.length() - j, radix));
272                     }
273                 }
274 
275                 for (long large_value : LONG_VALUES) {
276                     {
277                         final String input = leftPad + Long.toBinaryString(large_value) + rightPad;
278                         assertThrows(
279                                 NumberFormatException.class,
280                                 () -> Integer.parseUnsignedInt(input, i, input.length() - j, 2));
281                     }
282                     {
283                         final String input = leftPad + Long.toOctalString(large_value) + rightPad;
284                         assertThrows(
285                                 NumberFormatException.class,
286                                 () -> Integer.parseUnsignedInt(input, i, input.length() - j, 8));
287                     }
288                     {
289                         final String input =
290                                 leftPad + Long.toUnsignedString(large_value) + rightPad;
291                         assertThrows(
292                                 NumberFormatException.class,
293                                 () -> Integer.parseUnsignedInt(input, i, input.length() - j, 10));
294                     }
295                     {
296                         final String input = leftPad + Long.toHexString(large_value) + rightPad;
297                         assertThrows(
298                                 NumberFormatException.class,
299                                 () -> Integer.parseUnsignedInt(input, i, input.length() - j, 16));
300                     }
301                     for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
302                         final int r = radix;
303                         String input =
304                                 leftPad + Long.toUnsignedString(large_value, radix) + rightPad;
305                         assertThrows(
306                                 NumberFormatException.class,
307                                 () -> Integer.parseUnsignedInt(input, i, input.length() - j, r));
308                     }
309                 }
310             }
311         }
312 
313         assertThrows(
314                 IndexOutOfBoundsException.class, () -> Integer.parseUnsignedInt("123", -1, 3, 10));
315         assertThrows(
316                 IndexOutOfBoundsException.class, () -> Integer.parseUnsignedInt("123", 4, 5, 10));
317         assertThrows(
318                 IndexOutOfBoundsException.class, () -> Integer.parseUnsignedInt("123", 2, 1, 10));
319         assertThrows(
320                 IndexOutOfBoundsException.class, () -> Integer.parseUnsignedInt("123", 2, 4, 10));
321         assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt("-1", 0, 2, 10));
322         assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt("123", 0, 3, 2));
323         assertThrows(
324                 NumberFormatException.class,
325                 () -> Integer.parseUnsignedInt("0", 0, 1, Character.MAX_RADIX + 1));
326         assertThrows(
327                 NumberFormatException.class,
328                 () -> Integer.parseUnsignedInt("0", 0, 1, Character.MIN_RADIX - 1));
329         assertThrows(NullPointerException.class, () -> Integer.parseUnsignedInt(null, 0, 1, 10));
330     }
331 
332     @Test
testToUnsignedLong()333     public void testToUnsignedLong() {
334         for (int val : INT_VALUES) {
335             long ul = Integer.toUnsignedLong(val);
336             assertEquals(0, ul >>> Integer.BYTES * 8);
337             assertEquals(val, (int) ul);
338         }
339     }
340 
341     @Test
testToUnsignedString()342     public void testToUnsignedString() {
343         for (int val : INT_VALUES) {
344             // Special radices
345             assertTrue(Integer.toUnsignedString(val, 2).equals(Integer.toBinaryString(val)));
346             assertTrue(Integer.toUnsignedString(val, 8).equals(Integer.toOctalString(val)));
347             assertTrue(Integer.toUnsignedString(val, 10).equals(Integer.toUnsignedString(val)));
348             assertTrue(Integer.toUnsignedString(val, 16).equals(Integer.toHexString(val)));
349 
350             for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
351                 assertTrue(
352                         Integer.toUnsignedString(val, radix)
353                                 .equals(Long.toString(Integer.toUnsignedLong(val), radix)));
354             }
355 
356             // Behavior is not defined by Java API specification if the radix falls outside of valid
357             // range, thus we don't test for such cases.
358         }
359     }
360 
361     @Test
testParseUnsignedIntSubstringForBackports()362     public void testParseUnsignedIntSubstringForBackports() {
363         // Rudimentary test to register coverage on older branches where we may see backports for
364         // OpenJDK 11 methods (b/191859202). NB using Integer_parseUnsignedInt rather than
365         // Integer.parseUnsignedInt.
366         assertEquals(
367                 0xaa55aa55,
368                 Integer_parseUnsignedInt("left10101010010101011010101001010101right", 4, 36, 2));
369         assertEquals(8003, Integer_parseUnsignedInt("left17503right", 4, 9, 8));
370         assertEquals(0xffff_ffff, Integer_parseUnsignedInt("left4294967295right", 4, 14, 10));
371         assertEquals(0x1234_5678, Integer_parseUnsignedInt("lefty12345678righty", 5, 13, 16));
372     }
373 
374     /**
375      * Parses an unsigned integer using a {@code MethodHandle} to invoke {@code
376      * Integer.parseUnsignedInt}.
377      *
378      * @param val the {@code CharSequence} to be parsed.
379      * @param start the starting index in {@code val}.
380      * @param end the ending ing index in {@code val}, exclusive.
381      * @param radix the radix to parse {@code val} with.
382      * @return the parsed unsigned integer.
383      */
Integer_parseUnsignedInt(CharSequence val, int start, int end, int radix)384     private static int Integer_parseUnsignedInt(CharSequence val, int start, int end, int radix) {
385         try {
386             MethodType parseUnsignedIntType =
387                     MethodType.methodType(
388                             int.class, CharSequence.class, int.class, int.class, int.class);
389             MethodHandle parseUnsignedInt =
390                     MethodHandles.lookup()
391                             .findStatic(Integer.class, "parseUnsignedInt", parseUnsignedIntType);
392             return (int) parseUnsignedInt.invokeExact(val, start, end, radix);
393         } catch (IndexOutOfBoundsException | NullPointerException | NumberFormatException e) {
394             // Expected exceptions from the target method during the tests here.
395             throw e;
396         } catch (Throwable t) {
397             // Everything else.
398             throw new RuntimeException(t);
399         }
400     }
401 }
402