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