1/*
2 * Copyright (C) 2008 The Guava Authors
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
17package com.google.common.primitives;
18
19import com.google.common.annotations.GwtCompatible;
20import com.google.common.annotations.GwtIncompatible;
21import com.google.common.base.Converter;
22import com.google.common.collect.testing.Helpers;
23import com.google.common.testing.NullPointerTester;
24import com.google.common.testing.SerializableTester;
25
26import junit.framework.TestCase;
27
28import java.util.Arrays;
29import java.util.Collection;
30import java.util.Collections;
31import java.util.Comparator;
32import java.util.List;
33import java.util.Random;
34
35/**
36 * Unit test for {@link Ints}.
37 *
38 * @author Kevin Bourrillion
39 */
40@GwtCompatible(emulated = true)
41@SuppressWarnings("cast") // redundant casts are intentional and harmless
42public class IntsTest extends TestCase {
43  private static final int[] EMPTY = {};
44  private static final int[] ARRAY1 = {(int) 1};
45  private static final int[] ARRAY234
46      = {(int) 2, (int) 3, (int) 4};
47
48  private static final int LEAST = Integer.MIN_VALUE;
49  private static final int GREATEST = Integer.MAX_VALUE;
50
51  private static final int[] VALUES =
52      { LEAST, (int) -1, (int) 0, (int) 1, GREATEST };
53
54  public void testHashCode() {
55    for (int value : VALUES) {
56      assertEquals(((Integer) value).hashCode(), Ints.hashCode(value));
57    }
58  }
59
60  public void testCheckedCast() {
61    for (int value : VALUES) {
62      assertEquals(value, Ints.checkedCast((long) value));
63    }
64    assertCastFails(GREATEST + 1L);
65    assertCastFails(LEAST - 1L);
66    assertCastFails(Long.MAX_VALUE);
67    assertCastFails(Long.MIN_VALUE);
68  }
69
70  public void testSaturatedCast() {
71    for (int value : VALUES) {
72      assertEquals(value, Ints.saturatedCast((long) value));
73    }
74    assertEquals(GREATEST, Ints.saturatedCast(GREATEST + 1L));
75    assertEquals(LEAST, Ints.saturatedCast(LEAST - 1L));
76    assertEquals(GREATEST, Ints.saturatedCast(Long.MAX_VALUE));
77    assertEquals(LEAST, Ints.saturatedCast(Long.MIN_VALUE));
78  }
79
80  private static void assertCastFails(long value) {
81    try {
82      Ints.checkedCast(value);
83      fail("Cast to int should have failed: " + value);
84    } catch (IllegalArgumentException ex) {
85      assertTrue(value + " not found in exception text: " + ex.getMessage(),
86          ex.getMessage().contains(String.valueOf(value)));
87    }
88  }
89
90  public void testCompare() {
91    for (int x : VALUES) {
92      for (int y : VALUES) {
93        // note: spec requires only that the sign is the same
94        assertEquals(x + ", " + y,
95                     Integer.valueOf(x).compareTo(y),
96                     Ints.compare(x, y));
97      }
98    }
99  }
100
101  public void testContains() {
102    assertFalse(Ints.contains(EMPTY, (int) 1));
103    assertFalse(Ints.contains(ARRAY1, (int) 2));
104    assertFalse(Ints.contains(ARRAY234, (int) 1));
105    assertTrue(Ints.contains(new int[] {(int) -1}, (int) -1));
106    assertTrue(Ints.contains(ARRAY234, (int) 2));
107    assertTrue(Ints.contains(ARRAY234, (int) 3));
108    assertTrue(Ints.contains(ARRAY234, (int) 4));
109  }
110
111  public void testIndexOf() {
112    assertEquals(-1, Ints.indexOf(EMPTY, (int) 1));
113    assertEquals(-1, Ints.indexOf(ARRAY1, (int) 2));
114    assertEquals(-1, Ints.indexOf(ARRAY234, (int) 1));
115    assertEquals(0, Ints.indexOf(
116        new int[] {(int) -1}, (int) -1));
117    assertEquals(0, Ints.indexOf(ARRAY234, (int) 2));
118    assertEquals(1, Ints.indexOf(ARRAY234, (int) 3));
119    assertEquals(2, Ints.indexOf(ARRAY234, (int) 4));
120    assertEquals(1, Ints.indexOf(
121        new int[] { (int) 2, (int) 3, (int) 2, (int) 3 },
122        (int) 3));
123  }
124
125  public void testIndexOf_arrayTarget() {
126    assertEquals(0, Ints.indexOf(EMPTY, EMPTY));
127    assertEquals(0, Ints.indexOf(ARRAY234, EMPTY));
128    assertEquals(-1, Ints.indexOf(EMPTY, ARRAY234));
129    assertEquals(-1, Ints.indexOf(ARRAY234, ARRAY1));
130    assertEquals(-1, Ints.indexOf(ARRAY1, ARRAY234));
131    assertEquals(0, Ints.indexOf(ARRAY1, ARRAY1));
132    assertEquals(0, Ints.indexOf(ARRAY234, ARRAY234));
133    assertEquals(0, Ints.indexOf(
134        ARRAY234, new int[] { (int) 2, (int) 3 }));
135    assertEquals(1, Ints.indexOf(
136        ARRAY234, new int[] { (int) 3, (int) 4 }));
137    assertEquals(1, Ints.indexOf(ARRAY234, new int[] { (int) 3 }));
138    assertEquals(2, Ints.indexOf(ARRAY234, new int[] { (int) 4 }));
139    assertEquals(1, Ints.indexOf(new int[] { (int) 2, (int) 3,
140        (int) 3, (int) 3, (int) 3 },
141        new int[] { (int) 3 }
142    ));
143    assertEquals(2, Ints.indexOf(
144        new int[] { (int) 2, (int) 3, (int) 2,
145            (int) 3, (int) 4, (int) 2, (int) 3},
146        new int[] { (int) 2, (int) 3, (int) 4}
147    ));
148    assertEquals(1, Ints.indexOf(
149        new int[] { (int) 2, (int) 2, (int) 3,
150            (int) 4, (int) 2, (int) 3, (int) 4},
151        new int[] { (int) 2, (int) 3, (int) 4}
152    ));
153    assertEquals(-1, Ints.indexOf(
154        new int[] { (int) 4, (int) 3, (int) 2},
155        new int[] { (int) 2, (int) 3, (int) 4}
156    ));
157  }
158
159  public void testLastIndexOf() {
160    assertEquals(-1, Ints.lastIndexOf(EMPTY, (int) 1));
161    assertEquals(-1, Ints.lastIndexOf(ARRAY1, (int) 2));
162    assertEquals(-1, Ints.lastIndexOf(ARRAY234, (int) 1));
163    assertEquals(0, Ints.lastIndexOf(
164        new int[] {(int) -1}, (int) -1));
165    assertEquals(0, Ints.lastIndexOf(ARRAY234, (int) 2));
166    assertEquals(1, Ints.lastIndexOf(ARRAY234, (int) 3));
167    assertEquals(2, Ints.lastIndexOf(ARRAY234, (int) 4));
168    assertEquals(3, Ints.lastIndexOf(
169        new int[] { (int) 2, (int) 3, (int) 2, (int) 3 },
170        (int) 3));
171  }
172
173  public void testMax_noArgs() {
174    try {
175      Ints.max();
176      fail();
177    } catch (IllegalArgumentException expected) {
178    }
179  }
180
181  public void testMax() {
182    assertEquals(LEAST, Ints.max(LEAST));
183    assertEquals(GREATEST, Ints.max(GREATEST));
184    assertEquals((int) 9, Ints.max(
185        (int) 8, (int) 6, (int) 7,
186        (int) 5, (int) 3, (int) 0, (int) 9));
187  }
188
189  public void testMin_noArgs() {
190    try {
191      Ints.min();
192      fail();
193    } catch (IllegalArgumentException expected) {
194    }
195  }
196
197  public void testMin() {
198    assertEquals(LEAST, Ints.min(LEAST));
199    assertEquals(GREATEST, Ints.min(GREATEST));
200    assertEquals((int) 0, Ints.min(
201        (int) 8, (int) 6, (int) 7,
202        (int) 5, (int) 3, (int) 0, (int) 9));
203  }
204
205  public void testConcat() {
206    assertTrue(Arrays.equals(EMPTY, Ints.concat()));
207    assertTrue(Arrays.equals(EMPTY, Ints.concat(EMPTY)));
208    assertTrue(Arrays.equals(EMPTY, Ints.concat(EMPTY, EMPTY, EMPTY)));
209    assertTrue(Arrays.equals(ARRAY1, Ints.concat(ARRAY1)));
210    assertNotSame(ARRAY1, Ints.concat(ARRAY1));
211    assertTrue(Arrays.equals(ARRAY1, Ints.concat(EMPTY, ARRAY1, EMPTY)));
212    assertTrue(Arrays.equals(
213        new int[] {(int) 1, (int) 1, (int) 1},
214        Ints.concat(ARRAY1, ARRAY1, ARRAY1)));
215    assertTrue(Arrays.equals(
216        new int[] {(int) 1, (int) 2, (int) 3, (int) 4},
217        Ints.concat(ARRAY1, ARRAY234)));
218  }
219
220  @GwtIncompatible("Ints.toByteArray")
221  public void testToByteArray() {
222    assertTrue(Arrays.equals(
223        new byte[] {0x12, 0x13, 0x14, 0x15}, Ints.toByteArray(0x12131415)));
224    assertTrue(Arrays.equals(
225        new byte[] {(byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC},
226        Ints.toByteArray(0xFFEEDDCC)));
227  }
228
229  @GwtIncompatible("Ints.fromByteArray")
230  public void testFromByteArray() {
231    assertEquals(0x12131415,
232        Ints.fromByteArray(new byte[] {0x12, 0x13, 0x14, 0x15, 0x33}));
233    assertEquals(0xFFEEDDCC, Ints.fromByteArray(
234        new byte[] {(byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC}));
235
236    try {
237      Ints.fromByteArray(new byte[Ints.BYTES - 1]);
238      fail();
239    } catch (IllegalArgumentException expected) {
240    }
241  }
242
243  @GwtIncompatible("Ints.fromBytes")
244  public void testFromBytes() {
245    assertEquals(0x12131415, Ints.fromBytes(
246        (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15));
247    assertEquals(0xFFEEDDCC, Ints.fromBytes(
248        (byte) 0xFF, (byte) 0xEE, (byte) 0xDD, (byte) 0xCC));
249  }
250
251  @GwtIncompatible("Ints.fromByteArray, Ints.toByteArray")
252  public void testByteArrayRoundTrips() {
253    Random r = new Random(5);
254    byte[] b = new byte[Ints.BYTES];
255
256    // total overkill, but, it takes 0.1 sec so why not...
257    for (int i = 0; i < 10000; i++) {
258      int num = r.nextInt();
259      assertEquals(num, Ints.fromByteArray(Ints.toByteArray(num)));
260
261      r.nextBytes(b);
262      assertTrue(Arrays.equals(b, Ints.toByteArray(Ints.fromByteArray(b))));
263    }
264  }
265
266  public void testEnsureCapacity() {
267    assertSame(EMPTY, Ints.ensureCapacity(EMPTY, 0, 1));
268    assertSame(ARRAY1, Ints.ensureCapacity(ARRAY1, 0, 1));
269    assertSame(ARRAY1, Ints.ensureCapacity(ARRAY1, 1, 1));
270    assertTrue(Arrays.equals(
271        new int[] {(int) 1, (int) 0, (int) 0},
272        Ints.ensureCapacity(ARRAY1, 2, 1)));
273  }
274
275  public void testEnsureCapacity_fail() {
276    try {
277      Ints.ensureCapacity(ARRAY1, -1, 1);
278      fail();
279    } catch (IllegalArgumentException expected) {
280    }
281    try {
282      // notice that this should even fail when no growth was needed
283      Ints.ensureCapacity(ARRAY1, 1, -1);
284      fail();
285    } catch (IllegalArgumentException expected) {
286    }
287  }
288
289  public void testJoin() {
290    assertEquals("", Ints.join(",", EMPTY));
291    assertEquals("1", Ints.join(",", ARRAY1));
292    assertEquals("1,2", Ints.join(",", (int) 1, (int) 2));
293    assertEquals("123",
294        Ints.join("", (int) 1, (int) 2, (int) 3));
295  }
296
297  public void testLexicographicalComparator() {
298    List<int[]> ordered = Arrays.asList(
299        new int[] {},
300        new int[] {LEAST},
301        new int[] {LEAST, LEAST},
302        new int[] {LEAST, (int) 1},
303        new int[] {(int) 1},
304        new int[] {(int) 1, LEAST},
305        new int[] {GREATEST, GREATEST - (int) 1},
306        new int[] {GREATEST, GREATEST},
307        new int[] {GREATEST, GREATEST, GREATEST});
308
309    Comparator<int[]> comparator = Ints.lexicographicalComparator();
310    Helpers.testComparator(comparator, ordered);
311  }
312
313  @GwtIncompatible("SerializableTester")
314  public void testLexicographicalComparatorSerializable() {
315    Comparator<int[]> comparator = Ints.lexicographicalComparator();
316    assertSame(comparator, SerializableTester.reserialize(comparator));
317  }
318
319  @GwtIncompatible("SerializableTester")
320  public void testStringConverterSerialization() {
321    SerializableTester.reserializeAndAssert(Ints.stringConverter());
322  }
323
324  public void testToArray() {
325    // need explicit type parameter to avoid javac warning!?
326    List<Integer> none = Arrays.<Integer>asList();
327    assertTrue(Arrays.equals(EMPTY, Ints.toArray(none)));
328
329    List<Integer> one = Arrays.asList((int) 1);
330    assertTrue(Arrays.equals(ARRAY1, Ints.toArray(one)));
331
332    int[] array = {(int) 0, (int) 1, (int) 0xdeadbeef};
333
334    List<Integer> three = Arrays.asList((int) 0, (int) 1, (int) 0xdeadbeef);
335    assertTrue(Arrays.equals(array, Ints.toArray(three)));
336
337    assertTrue(Arrays.equals(array, Ints.toArray(Ints.asList(array))));
338  }
339
340  public void testToArray_threadSafe() {
341    for (int delta : new int[] { +1, 0, -1 }) {
342      for (int i = 0; i < VALUES.length; i++) {
343        List<Integer> list = Ints.asList(VALUES).subList(0, i);
344        Collection<Integer> misleadingSize =
345            Helpers.misleadingSizeCollection(delta);
346        misleadingSize.addAll(list);
347        int[] arr = Ints.toArray(misleadingSize);
348        assertEquals(i, arr.length);
349        for (int j = 0; j < i; j++) {
350          assertEquals(VALUES[j], arr[j]);
351        }
352      }
353    }
354  }
355
356  public void testToArray_withNull() {
357    List<Integer> list = Arrays.asList((int) 0, (int) 1, null);
358    try {
359      Ints.toArray(list);
360      fail();
361    } catch (NullPointerException expected) {
362    }
363  }
364
365  public void testToArray_withConversion() {
366    int[] array = {0, 1, 2};
367
368    List<Byte> bytes = Arrays.asList((byte) 0, (byte) 1, (byte) 2);
369    List<Short> shorts = Arrays.asList((short) 0, (short) 1, (short) 2);
370    List<Integer> ints = Arrays.asList(0, 1, 2);
371    List<Float> floats = Arrays.asList((float) 0, (float) 1, (float) 2);
372    List<Long> longs = Arrays.asList((long) 0, (long) 1, (long) 2);
373    List<Double> doubles = Arrays.asList((double) 0, (double) 1, (double) 2);
374
375    assertTrue(Arrays.equals(array, Ints.toArray(bytes)));
376    assertTrue(Arrays.equals(array, Ints.toArray(shorts)));
377    assertTrue(Arrays.equals(array, Ints.toArray(ints)));
378    assertTrue(Arrays.equals(array, Ints.toArray(floats)));
379    assertTrue(Arrays.equals(array, Ints.toArray(longs)));
380    assertTrue(Arrays.equals(array, Ints.toArray(doubles)));
381  }
382
383  public void testAsList_isAView() {
384    int[] array = {(int) 0, (int) 1};
385    List<Integer> list = Ints.asList(array);
386    list.set(0, (int) 2);
387    assertTrue(Arrays.equals(new int[] {(int) 2, (int) 1}, array));
388    array[1] = (int) 3;
389    assertEquals(Arrays.asList((int) 2, (int) 3), list);
390  }
391
392  public void testAsList_toArray_roundTrip() {
393    int[] array = { (int) 0, (int) 1, (int) 2 };
394    List<Integer> list = Ints.asList(array);
395    int[] newArray = Ints.toArray(list);
396
397    // Make sure it returned a copy
398    list.set(0, (int) 4);
399    assertTrue(Arrays.equals(
400        new int[] { (int) 0, (int) 1, (int) 2 }, newArray));
401    newArray[1] = (int) 5;
402    assertEquals((int) 1, (int) list.get(1));
403  }
404
405  // This test stems from a real bug found by andrewk
406  public void testAsList_subList_toArray_roundTrip() {
407    int[] array = { (int) 0, (int) 1, (int) 2, (int) 3 };
408    List<Integer> list = Ints.asList(array);
409    assertTrue(Arrays.equals(new int[] { (int) 1, (int) 2 },
410        Ints.toArray(list.subList(1, 3))));
411    assertTrue(Arrays.equals(new int[] {},
412        Ints.toArray(list.subList(2, 2))));
413  }
414
415  public void testAsListEmpty() {
416    assertSame(Collections.emptyList(), Ints.asList(EMPTY));
417  }
418
419  @GwtIncompatible("NullPointerTester")
420  public void testNulls() {
421    new NullPointerTester().testAllPublicStaticMethods(Ints.class);
422  }
423
424  public void testStringConverter_convert() {
425    Converter<String, Integer> converter = Ints.stringConverter();
426    assertEquals((Integer) 1, converter.convert("1"));
427    assertEquals((Integer) 0, converter.convert("0"));
428    assertEquals((Integer) (-1), converter.convert("-1"));
429    assertEquals((Integer) 255, converter.convert("0xff"));
430    assertEquals((Integer) 255, converter.convert("0xFF"));
431    assertEquals((Integer) (-255), converter.convert("-0xFF"));
432    assertEquals((Integer) 255, converter.convert("#0000FF"));
433    assertEquals((Integer) 438, converter.convert("0666"));
434  }
435
436  public void testStringConverter_convertError() {
437    try {
438      Ints.stringConverter().convert("notanumber");
439      fail();
440    } catch (NumberFormatException expected) {
441    }
442  }
443
444  public void testStringConverter_nullConversions() {
445    assertNull(Ints.stringConverter().convert(null));
446    assertNull(Ints.stringConverter().reverse().convert(null));
447  }
448
449  public void testStringConverter_reverse() {
450    Converter<String, Integer> converter = Ints.stringConverter();
451    assertEquals("1", converter.reverse().convert(1));
452    assertEquals("0", converter.reverse().convert(0));
453    assertEquals("-1", converter.reverse().convert(-1));
454    assertEquals("255", converter.reverse().convert(0xff));
455    assertEquals("255", converter.reverse().convert(0xFF));
456    assertEquals("-255", converter.reverse().convert(-0xFF));
457    assertEquals("438", converter.reverse().convert(0666));
458  }
459
460  @GwtIncompatible("NullPointerTester")
461  public void testStringConverter_nullPointerTester() throws Exception {
462    NullPointerTester tester = new NullPointerTester();
463    tester.testAllPublicInstanceMethods(Ints.stringConverter());
464  }
465
466  public void testTryParse() {
467    tryParseAndAssertEquals(0, "0");
468    tryParseAndAssertEquals(0, "-0");
469    tryParseAndAssertEquals(1, "1");
470    tryParseAndAssertEquals(-1, "-1");
471    tryParseAndAssertEquals(8900, "8900");
472    tryParseAndAssertEquals(-8900, "-8900");
473    tryParseAndAssertEquals(GREATEST, Integer.toString(GREATEST));
474    tryParseAndAssertEquals(LEAST, Integer.toString(LEAST));
475    assertNull(Ints.tryParse(""));
476    assertNull(Ints.tryParse("-"));
477    assertNull(Ints.tryParse("+1"));
478    assertNull(Ints.tryParse("9999999999999999"));
479    assertNull("Max integer + 1",
480        Ints.tryParse(Long.toString(((long) GREATEST) + 1)));
481    assertNull("Max integer * 10",
482        Ints.tryParse(Long.toString(((long) GREATEST) * 10)));
483    assertNull("Min integer - 1",
484        Ints.tryParse(Long.toString(((long) LEAST) - 1)));
485    assertNull("Min integer * 10",
486        Ints.tryParse(Long.toString(((long) LEAST) * 10)));
487    assertNull("Max long", Ints.tryParse(Long.toString(Long.MAX_VALUE)));
488    assertNull("Min long", Ints.tryParse(Long.toString(Long.MIN_VALUE)));
489    assertNull(Ints.tryParse("\u0662\u06f3"));
490  }
491
492  /**
493   * Applies {@link Ints#tryParse(String)} to the given string and asserts that
494   * the result is as expected.
495   */
496  private static void tryParseAndAssertEquals(Integer expected, String value) {
497    assertEquals(expected, Ints.tryParse(value));
498  }
499}
500