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