• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 
15 package com.google.common.primitives;
16 
17 import static com.google.common.primitives.TestPlatform.reduceIterationsIfGwt;
18 import static com.google.common.testing.SerializableTester.reserialize;
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.annotations.GwtIncompatible;
23 import com.google.common.annotations.J2ktIncompatible;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.ObjectArrays;
26 import com.google.common.collect.testing.ListTestSuiteBuilder;
27 import com.google.common.collect.testing.SampleElements;
28 import com.google.common.collect.testing.TestListGenerator;
29 import com.google.common.collect.testing.features.CollectionFeature;
30 import com.google.common.collect.testing.features.CollectionSize;
31 import com.google.common.testing.EqualsTester;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Random;
39 import java.util.concurrent.atomic.AtomicLong;
40 import junit.framework.Test;
41 import junit.framework.TestCase;
42 import junit.framework.TestSuite;
43 
44 /** @author Kevin Bourrillion */
45 @GwtCompatible(emulated = true)
46 public class ImmutableLongArrayTest extends TestCase {
47   // Test all creation paths very lazily: by assuming asList() works
48 
testOf0()49   public void testOf0() {
50     assertThat(ImmutableLongArray.of().asList()).isEmpty();
51   }
52 
testOf1()53   public void testOf1() {
54     assertThat(ImmutableLongArray.of(0).asList()).containsExactly(0L);
55   }
56 
testOf2()57   public void testOf2() {
58     assertThat(ImmutableLongArray.of(0, 1).asList()).containsExactly(0L, 1L).inOrder();
59   }
60 
testOf3()61   public void testOf3() {
62     assertThat(ImmutableLongArray.of(0, 1, 3).asList()).containsExactly(0L, 1L, 3L).inOrder();
63   }
64 
testOf4()65   public void testOf4() {
66     assertThat(ImmutableLongArray.of(0, 1, 3, 6).asList())
67         .containsExactly(0L, 1L, 3L, 6L)
68         .inOrder();
69   }
70 
testOf5()71   public void testOf5() {
72     assertThat(ImmutableLongArray.of(0, 1, 3, 6, 10).asList())
73         .containsExactly(0L, 1L, 3L, 6L, 10L)
74         .inOrder();
75   }
76 
testOf6()77   public void testOf6() {
78     assertThat(ImmutableLongArray.of(0, 1, 3, 6, 10, 15).asList())
79         .containsExactly(0L, 1L, 3L, 6L, 10L, 15L)
80         .inOrder();
81   }
82 
testOf7()83   public void testOf7() {
84     assertThat(ImmutableLongArray.of(0, 1, 3, 6, 10, 15, 21).asList())
85         .containsExactly(0L, 1L, 3L, 6L, 10L, 15L, 21L)
86         .inOrder();
87   }
88 
testCopyOf_array_empty()89   public void testCopyOf_array_empty() {
90     /*
91      * We don't guarantee the same-as property, so we aren't obligated to test it. However, it's
92      * useful in testing - when two things are the same then one can't have bugs the other doesn't.
93      */
94     assertThat(ImmutableLongArray.copyOf(new long[0])).isSameInstanceAs(ImmutableLongArray.of());
95   }
96 
testCopyOf_array_nonempty()97   public void testCopyOf_array_nonempty() {
98     long[] array = new long[] {0, 1, 3};
99     ImmutableLongArray iia = ImmutableLongArray.copyOf(array);
100     array[2] = 2;
101     assertThat(iia.asList()).containsExactly(0L, 1L, 3L).inOrder();
102   }
103 
testCopyOf_iterable_notCollection_empty()104   public void testCopyOf_iterable_notCollection_empty() {
105     Iterable<Long> iterable = iterable(Collections.<Long>emptySet());
106     assertThat(ImmutableLongArray.copyOf(iterable)).isSameInstanceAs(ImmutableLongArray.of());
107   }
108 
testCopyOf_iterable_notCollection_nonempty()109   public void testCopyOf_iterable_notCollection_nonempty() {
110     List<Long> list = Arrays.asList(0L, 1L, 3L);
111     ImmutableLongArray iia = ImmutableLongArray.copyOf(iterable(list));
112     list.set(2, 2L);
113     assertThat(iia.asList()).containsExactly(0L, 1L, 3L).inOrder();
114   }
115 
testCopyOf_iterable_collection_empty()116   public void testCopyOf_iterable_collection_empty() {
117     Iterable<Long> iterable = Collections.emptySet();
118     assertThat(ImmutableLongArray.copyOf(iterable)).isSameInstanceAs(ImmutableLongArray.of());
119   }
120 
testCopyOf_iterable_collection_nonempty()121   public void testCopyOf_iterable_collection_nonempty() {
122     List<Long> list = Arrays.asList(0L, 1L, 3L);
123     ImmutableLongArray iia = ImmutableLongArray.copyOf((Iterable<Long>) list);
124     list.set(2, 2L);
125     assertThat(iia.asList()).containsExactly(0L, 1L, 3L).inOrder();
126   }
127 
testCopyOf_collection_empty()128   public void testCopyOf_collection_empty() {
129     Collection<Long> iterable = Collections.emptySet();
130     assertThat(ImmutableLongArray.copyOf(iterable)).isSameInstanceAs(ImmutableLongArray.of());
131   }
132 
testCopyOf_collection_nonempty()133   public void testCopyOf_collection_nonempty() {
134     List<Long> list = Arrays.asList(0L, 1L, 3L);
135     ImmutableLongArray iia = ImmutableLongArray.copyOf(list);
136     list.set(2, 2L);
137     assertThat(iia.asList()).containsExactly(0L, 1L, 3L).inOrder();
138   }
139 
testBuilder_presize_zero()140   public void testBuilder_presize_zero() {
141     ImmutableLongArray.Builder builder = ImmutableLongArray.builder(0);
142     builder.add(5L);
143     ImmutableLongArray array = builder.build();
144     assertThat(array.asList()).containsExactly(5L);
145   }
146 
testBuilder_presize_negative()147   public void testBuilder_presize_negative() {
148     try {
149       ImmutableLongArray.builder(-1);
150       fail();
151     } catch (IllegalArgumentException expected) {
152     }
153   }
154 
155   /**
156    * If there's a bug in builder growth, we wouldn't know how to expose it. So, brute force the hell
157    * out of it for a while and see what happens.
158    */
testBuilder_bruteForce()159   public void testBuilder_bruteForce() {
160     for (int i = 0; i < reduceIterationsIfGwt(100); i++) {
161       ImmutableLongArray.Builder builder = ImmutableLongArray.builder(RANDOM.nextInt(20));
162       AtomicLong counter = new AtomicLong(0);
163       while (counter.get() < 1000) {
164         BuilderOp op = BuilderOp.randomOp();
165         op.doIt(builder, counter);
166       }
167       ImmutableLongArray iia = builder.build();
168       for (int j = 0; j < iia.length(); j++) {
169         assertThat(iia.get(j)).isEqualTo((long) j);
170       }
171     }
172   }
173 
174   private enum BuilderOp {
175     ADD_ONE {
176       @Override
doIt(ImmutableLongArray.Builder builder, AtomicLong counter)177       void doIt(ImmutableLongArray.Builder builder, AtomicLong counter) {
178         builder.add(counter.getAndIncrement());
179       }
180     },
181     ADD_ARRAY {
182       @Override
doIt(ImmutableLongArray.Builder builder, AtomicLong counter)183       void doIt(ImmutableLongArray.Builder builder, AtomicLong counter) {
184         long[] array = new long[RANDOM.nextInt(10)];
185         for (int i = 0; i < array.length; i++) {
186           array[i] = counter.getAndIncrement();
187         }
188         builder.addAll(array);
189       }
190     },
191     ADD_COLLECTION {
192       @Override
doIt(ImmutableLongArray.Builder builder, AtomicLong counter)193       void doIt(ImmutableLongArray.Builder builder, AtomicLong counter) {
194         List<Long> list = new ArrayList<>();
195         long num = RANDOM.nextInt(10);
196         for (int i = 0; i < num; i++) {
197           list.add(counter.getAndIncrement());
198         }
199         builder.addAll(list);
200       }
201     },
202     ADD_ITERABLE {
203       @Override
doIt(ImmutableLongArray.Builder builder, AtomicLong counter)204       void doIt(ImmutableLongArray.Builder builder, AtomicLong counter) {
205         List<Long> list = new ArrayList<>();
206         long num = RANDOM.nextInt(10);
207         for (int i = 0; i < num; i++) {
208           list.add(counter.getAndIncrement());
209         }
210         builder.addAll(iterable(list));
211       }
212     },
213     ADD_IIA {
214       @Override
doIt(ImmutableLongArray.Builder builder, AtomicLong counter)215       void doIt(ImmutableLongArray.Builder builder, AtomicLong counter) {
216         long[] array = new long[RANDOM.nextInt(10)];
217         for (int i = 0; i < array.length; i++) {
218           array[i] = counter.getAndIncrement();
219         }
220         builder.addAll(ImmutableLongArray.copyOf(array));
221       }
222     },
223     ADD_LARGER_ARRAY {
224       @Override
doIt(ImmutableLongArray.Builder builder, AtomicLong counter)225       void doIt(ImmutableLongArray.Builder builder, AtomicLong counter) {
226         long[] array = new long[RANDOM.nextInt(200) + 200];
227         for (int i = 0; i < array.length; i++) {
228           array[i] = counter.getAndIncrement();
229         }
230         builder.addAll(array);
231       }
232     },
233     ;
234 
235     static final BuilderOp[] values = values();
236 
randomOp()237     static BuilderOp randomOp() {
238       return values[RANDOM.nextInt(values.length)];
239     }
240 
doIt(ImmutableLongArray.Builder builder, AtomicLong counter)241     abstract void doIt(ImmutableLongArray.Builder builder, AtomicLong counter);
242   }
243 
244   private static final Random RANDOM = new Random(42);
245 
testLength()246   public void testLength() {
247     assertThat(ImmutableLongArray.of().length()).isEqualTo(0);
248     assertThat(ImmutableLongArray.of(0).length()).isEqualTo(1);
249     assertThat(ImmutableLongArray.of(0, 1, 3).length()).isEqualTo(3);
250     assertThat(ImmutableLongArray.of(0, 1, 3).subArray(1, 1).length()).isEqualTo(0);
251     assertThat(ImmutableLongArray.of(0, 1, 3).subArray(1, 2).length()).isEqualTo(1);
252   }
253 
testIsEmpty()254   public void testIsEmpty() {
255     assertThat(ImmutableLongArray.of().isEmpty()).isTrue();
256     assertThat(ImmutableLongArray.of(0).isEmpty()).isFalse();
257     assertThat(ImmutableLongArray.of(0, 1, 3).isEmpty()).isFalse();
258     assertThat(ImmutableLongArray.of(0, 1, 3).subArray(1, 1).isEmpty()).isTrue();
259     assertThat(ImmutableLongArray.of(0, 1, 3).subArray(1, 2).isEmpty()).isFalse();
260   }
261 
testGet_good()262   public void testGet_good() {
263     ImmutableLongArray iia = ImmutableLongArray.of(0, 1, 3);
264     assertThat(iia.get(0)).isEqualTo(0L);
265     assertThat(iia.get(2)).isEqualTo(3L);
266     assertThat(iia.subArray(1, 3).get(1)).isEqualTo(3L);
267   }
268 
testGet_bad()269   public void testGet_bad() {
270     ImmutableLongArray iia = ImmutableLongArray.of(0, 1, 3);
271     try {
272       iia.get(-1);
273       fail();
274     } catch (IndexOutOfBoundsException expected) {
275     }
276     try {
277       iia.get(3);
278       fail();
279     } catch (IndexOutOfBoundsException expected) {
280     }
281 
282     iia = iia.subArray(1, 2);
283     try {
284       iia.get(-1);
285       fail();
286     } catch (IndexOutOfBoundsException expected) {
287     }
288   }
289 
testIndexOf()290   public void testIndexOf() {
291     ImmutableLongArray iia = ImmutableLongArray.of(1, 1, 2, 3, 5, 8);
292     assertThat(iia.indexOf(1)).isEqualTo(0);
293     assertThat(iia.indexOf(8)).isEqualTo(5);
294     assertThat(iia.indexOf(4)).isEqualTo(-1);
295     assertThat(ImmutableLongArray.of(13).indexOf(13)).isEqualTo(0);
296     assertThat(ImmutableLongArray.of().indexOf(21)).isEqualTo(-1);
297     assertThat(iia.subArray(1, 5).indexOf(1)).isEqualTo(0);
298   }
299 
testLastIndexOf()300   public void testLastIndexOf() {
301     ImmutableLongArray iia = ImmutableLongArray.of(1, 1, 2, 3, 5, 8);
302     assertThat(iia.lastIndexOf(1)).isEqualTo(1);
303     assertThat(iia.lastIndexOf(8)).isEqualTo(5);
304     assertThat(iia.lastIndexOf(4)).isEqualTo(-1);
305     assertThat(ImmutableLongArray.of(13).lastIndexOf(13)).isEqualTo(0);
306     assertThat(ImmutableLongArray.of().lastIndexOf(21)).isEqualTo(-1);
307     assertThat(iia.subArray(1, 5).lastIndexOf(1)).isEqualTo(0);
308   }
309 
testContains()310   public void testContains() {
311     ImmutableLongArray iia = ImmutableLongArray.of(1, 1, 2, 3, 5, 8);
312     assertThat(iia.contains(1)).isTrue();
313     assertThat(iia.contains(8)).isTrue();
314     assertThat(iia.contains(4)).isFalse();
315     assertThat(ImmutableLongArray.of(13).contains(13)).isTrue();
316     assertThat(ImmutableLongArray.of().contains(21)).isFalse();
317     assertThat(iia.subArray(1, 5).contains(1)).isTrue();
318   }
319 
testSubArray()320   public void testSubArray() {
321     ImmutableLongArray iia0 = ImmutableLongArray.of();
322     ImmutableLongArray iia1 = ImmutableLongArray.of(5);
323     ImmutableLongArray iia3 = ImmutableLongArray.of(5, 25, 125);
324 
325     assertThat(iia0.subArray(0, 0)).isSameInstanceAs(ImmutableLongArray.of());
326     assertThat(iia1.subArray(0, 0)).isSameInstanceAs(ImmutableLongArray.of());
327     assertThat(iia1.subArray(1, 1)).isSameInstanceAs(ImmutableLongArray.of());
328     assertThat(iia1.subArray(0, 1).asList()).containsExactly(5L);
329     assertThat(iia3.subArray(0, 2).asList()).containsExactly(5L, 25L).inOrder();
330     assertThat(iia3.subArray(1, 3).asList()).containsExactly(25L, 125L).inOrder();
331 
332     try {
333       iia3.subArray(-1, 1);
334       fail();
335     } catch (IndexOutOfBoundsException expected) {
336     }
337     try {
338       iia3.subArray(1, 4);
339       fail();
340     } catch (IndexOutOfBoundsException expected) {
341     }
342   }
343 
344   /*
345    * Whenever an implementation uses `instanceof` on a parameter instance, the test has to know that
346    * (so much for "black box") and try instances that both do and don't pass the check. The "don't"
347    * half of that is more awkward to arrange...
348    */
iterable(final Collection<T> collection)349   private static <T> Iterable<T> iterable(final Collection<T> collection) {
350     // return collection::iterator;
351     return new Iterable<T>() {
352       @Override
353       public Iterator<T> iterator() {
354         return collection.iterator();
355       }
356     };
357   }
358 
359   public void testEquals() {
360     new EqualsTester()
361         .addEqualityGroup(ImmutableLongArray.of())
362         .addEqualityGroup(
363             ImmutableLongArray.of(1, 2),
364             reserialize(ImmutableLongArray.of(1, 2)),
365             ImmutableLongArray.of(0, 1, 2, 3).subArray(1, 3))
366         .addEqualityGroup(ImmutableLongArray.of(1, 3))
367         .addEqualityGroup(ImmutableLongArray.of(1, 2, 3))
368         .testEquals();
369   }
370 
371   /**
372    * This is probably a weird and hacky way to test what we're really trying to test, but hey, it
373    * caught a bug.
374    */
375   public void testTrimmed() {
376     ImmutableLongArray iia = ImmutableLongArray.of(0, 1, 3);
377     assertDoesntActuallyTrim(iia);
378     assertDoesntActuallyTrim(iia.subArray(0, 3));
379     assertActuallyTrims(iia.subArray(0, 2));
380     assertActuallyTrims(iia.subArray(1, 3));
381 
382     ImmutableLongArray rightSized = ImmutableLongArray.builder(3).add(0).add(1).add(3).build();
383     assertDoesntActuallyTrim(rightSized);
384 
385     ImmutableLongArray overSized = ImmutableLongArray.builder(3).add(0).add(1).build();
386     assertActuallyTrims(overSized);
387 
388     ImmutableLongArray underSized = ImmutableLongArray.builder(2).add(0).add(1).add(3).build();
389     assertActuallyTrims(underSized);
390   }
391 
392   @J2ktIncompatible
393   @GwtIncompatible // SerializableTester
394   public void testSerialization() {
395     assertThat(reserialize(ImmutableLongArray.of())).isSameInstanceAs(ImmutableLongArray.of());
396     assertThat(reserialize(ImmutableLongArray.of(0, 1).subArray(1, 1)))
397         .isSameInstanceAs(ImmutableLongArray.of());
398 
399     ImmutableLongArray iia = ImmutableLongArray.of(0, 1, 3, 6).subArray(1, 3);
400     ImmutableLongArray iia2 = reserialize(iia);
401     assertThat(iia2).isEqualTo(iia);
402     assertDoesntActuallyTrim(iia2);
403   }
404 
405   private static void assertActuallyTrims(ImmutableLongArray iia) {
406     ImmutableLongArray trimmed = iia.trimmed();
407     assertThat(trimmed).isNotSameInstanceAs(iia);
408 
409     // Yes, this is apparently how you check array equality in Truth
410     assertThat(trimmed.toArray()).isEqualTo(iia.toArray());
411   }
412 
413   private static void assertDoesntActuallyTrim(ImmutableLongArray iia) {
414     assertThat(iia.trimmed()).isSameInstanceAs(iia);
415   }
416 
417   @J2ktIncompatible
418   @GwtIncompatible // suite
419   public static Test suite() {
420     List<ListTestSuiteBuilder<Long>> builders =
421         ImmutableList.of(
422             ListTestSuiteBuilder.using(new ImmutableLongArrayAsListGenerator())
423                 .named("ImmutableLongArray.asList"),
424             ListTestSuiteBuilder.using(new ImmutableLongArrayHeadSubListAsListGenerator())
425                 .named("ImmutableLongArray.asList, head subList"),
426             ListTestSuiteBuilder.using(new ImmutableLongArrayTailSubListAsListGenerator())
427                 .named("ImmutableLongArray.asList, tail subList"),
428             ListTestSuiteBuilder.using(new ImmutableLongArrayMiddleSubListAsListGenerator())
429                 .named("ImmutableLongArray.asList, middle subList"));
430 
431     TestSuite suite = new TestSuite();
432     for (ListTestSuiteBuilder<Long> builder : builders) {
433       suite.addTest(
434           builder
435               .withFeatures(
436                   CollectionSize.ZERO,
437                   CollectionSize.ONE,
438                   CollectionSize.SEVERAL,
439                   CollectionFeature.ALLOWS_NULL_QUERIES,
440                   CollectionFeature.RESTRICTS_ELEMENTS,
441                   CollectionFeature.KNOWN_ORDER,
442                   CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)
443               .createTestSuite());
444     }
445     suite.addTestSuite(ImmutableLongArrayTest.class);
446     return suite;
447   }
448 
449   @J2ktIncompatible
450   @GwtIncompatible // used only from suite
451   private static ImmutableLongArray makeArray(Long[] values) {
452     return ImmutableLongArray.copyOf(Arrays.asList(values));
453   }
454 
455   // Test generators.  To let the GWT test suite generator access them, they need to be public named
456   // classes with a public default constructor (not that we run these suites under GWT yet).
457 
458   @J2ktIncompatible
459   @GwtIncompatible // used only from suite
460   public static final class ImmutableLongArrayAsListGenerator extends TestLongListGenerator {
461     @Override
462     protected List<Long> create(Long[] elements) {
463       return makeArray(elements).asList();
464     }
465   }
466 
467   @J2ktIncompatible
468   @GwtIncompatible // used only from suite
469   public static final class ImmutableLongArrayHeadSubListAsListGenerator
470       extends TestLongListGenerator {
471     @Override
472     protected List<Long> create(Long[] elements) {
473       Long[] suffix = {Long.MIN_VALUE, Long.MAX_VALUE};
474       Long[] all = concat(elements, suffix);
475       return makeArray(all).subArray(0, elements.length).asList();
476     }
477   }
478 
479   @J2ktIncompatible
480   @GwtIncompatible // used only from suite
481   public static final class ImmutableLongArrayTailSubListAsListGenerator
482       extends TestLongListGenerator {
483     @Override
484     protected List<Long> create(Long[] elements) {
485       Long[] prefix = {86L, 99L};
486       Long[] all = concat(prefix, elements);
487       return makeArray(all).subArray(2, elements.length + 2).asList();
488     }
489   }
490 
491   @J2ktIncompatible
492   @GwtIncompatible // used only from suite
493   public static final class ImmutableLongArrayMiddleSubListAsListGenerator
494       extends TestLongListGenerator {
495     @Override
496     protected List<Long> create(Long[] elements) {
497       Long[] prefix = {Long.MIN_VALUE, Long.MAX_VALUE};
498       Long[] suffix = {86L, 99L};
499       Long[] all = concat(concat(prefix, elements), suffix);
500       return makeArray(all).subArray(2, elements.length + 2).asList();
501     }
502   }
503 
504   @J2ktIncompatible
505   @GwtIncompatible // used only from suite
506   private static Long[] concat(Long[] a, Long[] b) {
507     return ObjectArrays.concat(a, b, Long.class);
508   }
509 
510   @J2ktIncompatible
511   @GwtIncompatible // used only from suite
512   public abstract static class TestLongListGenerator implements TestListGenerator<Long> {
513     @Override
514     public SampleElements<Long> samples() {
515       return new SampleLongs();
516     }
517 
518     @Override
519     public List<Long> create(Object... elements) {
520       Long[] array = new Long[elements.length];
521       int i = 0;
522       for (Object e : elements) {
523         array[i++] = (Long) e;
524       }
525       return create(array);
526     }
527 
528     /**
529      * Creates a new collection containing the given elements; implement this method instead of
530      * {@link #create(Object...)}.
531      */
532     protected abstract List<Long> create(Long[] elements);
533 
534     @Override
535     public Long[] createArray(int length) {
536       return new Long[length];
537     }
538 
539     /** Returns the original element list, unchanged. */
540     @Override
541     public List<Long> order(List<Long> insertionOrder) {
542       return insertionOrder;
543     }
544   }
545 
546   @J2ktIncompatible
547   @GwtIncompatible // used only from suite
548   public static class SampleLongs extends SampleElements<Long> {
549     public SampleLongs() {
550       super(1L << 31, 1L << 33, 1L << 36, 1L << 40, 1L << 45);
551     }
552   }
553 }
554