• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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.collect;
18 
19 import static com.google.common.collect.Iterables.getOnlyElement;
20 import static com.google.common.collect.Iterables.unmodifiableIterable;
21 import static com.google.common.collect.Sets.newHashSet;
22 import static java.lang.reflect.Proxy.newProxyInstance;
23 import static java.util.Arrays.asList;
24 
25 import com.google.common.annotations.GwtCompatible;
26 import com.google.common.annotations.GwtIncompatible;
27 import com.google.common.collect.testing.Helpers;
28 import com.google.common.collect.testing.ListTestSuiteBuilder;
29 import com.google.common.collect.testing.MinimalCollection;
30 import com.google.common.collect.testing.MinimalIterable;
31 import com.google.common.collect.testing.TestStringListGenerator;
32 import com.google.common.collect.testing.features.CollectionFeature;
33 import com.google.common.collect.testing.features.CollectionSize;
34 import com.google.common.collect.testing.google.ListGenerators.BuilderAddAllListGenerator;
35 import com.google.common.collect.testing.google.ListGenerators.BuilderReversedListGenerator;
36 import com.google.common.collect.testing.google.ListGenerators.ImmutableListHeadSubListGenerator;
37 import com.google.common.collect.testing.google.ListGenerators.ImmutableListMiddleSubListGenerator;
38 import com.google.common.collect.testing.google.ListGenerators.ImmutableListOfGenerator;
39 import com.google.common.collect.testing.google.ListGenerators.ImmutableListTailSubListGenerator;
40 import com.google.common.collect.testing.google.ListGenerators.UnhashableElementsImmutableListGenerator;
41 import com.google.common.collect.testing.testers.ListHashCodeTester;
42 import com.google.common.testing.NullPointerTester;
43 import com.google.common.testing.SerializableTester;
44 
45 import junit.framework.Test;
46 import junit.framework.TestCase;
47 import junit.framework.TestSuite;
48 
49 import java.lang.reflect.InvocationHandler;
50 import java.lang.reflect.InvocationTargetException;
51 import java.lang.reflect.Method;
52 import java.util.Collection;
53 import java.util.Collections;
54 import java.util.Iterator;
55 import java.util.List;
56 import java.util.Set;
57 import java.util.concurrent.CopyOnWriteArrayList;
58 
59 /**
60  * Unit test for {@link ImmutableList}.
61  *
62  * @author Kevin Bourrillion
63  * @author George van den Driessche
64  * @author Jared Levy
65  */
66 @GwtCompatible(emulated = true)
67 public class ImmutableListTest extends TestCase {
68 
69   @GwtIncompatible("suite")
suite()70   public static Test suite() {
71     TestSuite suite = new TestSuite();
72     suite.addTest(ListTestSuiteBuilder.using(new ImmutableListOfGenerator())
73         .named("ImmutableList")
74         .withFeatures(CollectionSize.ANY,
75             CollectionFeature.ALLOWS_NULL_QUERIES)
76         .createTestSuite());
77     suite.addTest(ListTestSuiteBuilder.using(new BuilderAddAllListGenerator())
78         .named("ImmutableList, built with Builder.add")
79         .withFeatures(CollectionSize.ANY,
80             CollectionFeature.ALLOWS_NULL_QUERIES)
81         .createTestSuite());
82     suite.addTest(ListTestSuiteBuilder.using(new BuilderAddAllListGenerator())
83         .named("ImmutableList, built with Builder.addAll")
84         .withFeatures(CollectionSize.ANY,
85             CollectionFeature.ALLOWS_NULL_QUERIES)
86         .createTestSuite());
87     suite.addTest(ListTestSuiteBuilder.using(new BuilderReversedListGenerator())
88         .named("ImmutableList, reversed")
89         .withFeatures(CollectionSize.ANY,
90             CollectionFeature.ALLOWS_NULL_QUERIES)
91         .createTestSuite());
92     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
93           @Override protected List<String> create(String[] elements) {
94             return SerializableTester.reserialize(
95                 ImmutableList.copyOf(elements));
96           }
97         })
98         .named("ImmutableList, reserialized")
99         .withFeatures(CollectionSize.ANY,
100             CollectionFeature.ALLOWS_NULL_QUERIES)
101         .createTestSuite());
102     suite.addTest(ListTestSuiteBuilder.using(
103         new ImmutableListHeadSubListGenerator())
104         .named("ImmutableList, head subList")
105         .withFeatures(CollectionSize.ANY,
106             CollectionFeature.ALLOWS_NULL_QUERIES)
107         .createTestSuite());
108     suite.addTest(ListTestSuiteBuilder.using(
109         new ImmutableListTailSubListGenerator())
110         .named("ImmutableList, tail subList")
111         .withFeatures(CollectionSize.ANY,
112             CollectionFeature.ALLOWS_NULL_QUERIES)
113         .createTestSuite());
114     suite.addTest(ListTestSuiteBuilder.using(
115         new ImmutableListMiddleSubListGenerator())
116         .named("ImmutableList, middle subList")
117         .withFeatures(CollectionSize.ANY,
118             CollectionFeature.ALLOWS_NULL_QUERIES)
119         .createTestSuite());
120     suite.addTest(ListTestSuiteBuilder.using(
121         new UnhashableElementsImmutableListGenerator())
122         .suppressing(ListHashCodeTester.getHashCodeMethod())
123         .named("ImmutableList, unhashable values")
124         .withFeatures(CollectionSize.ANY,
125             CollectionFeature.ALLOWS_NULL_QUERIES)
126         .createTestSuite());
127     return suite;
128   }
129 
130   public static class CreationTests extends TestCase {
testCreation_noArgs()131     public void testCreation_noArgs() {
132       List<String> list = ImmutableList.of();
133       assertEquals(Collections.emptyList(), list);
134     }
135 
testCreation_oneElement()136     public void testCreation_oneElement() {
137       List<String> list = ImmutableList.of("a");
138       assertEquals(Collections.singletonList("a"), list);
139     }
140 
testCreation_twoElements()141     public void testCreation_twoElements() {
142       List<String> list = ImmutableList.of("a", "b");
143       assertEquals(Lists.newArrayList("a", "b"), list);
144     }
145 
testCreation_threeElements()146     public void testCreation_threeElements() {
147       List<String> list = ImmutableList.of("a", "b", "c");
148       assertEquals(Lists.newArrayList("a", "b", "c"), list);
149     }
150 
testCreation_fourElements()151     public void testCreation_fourElements() {
152       List<String> list = ImmutableList.of("a", "b", "c", "d");
153       assertEquals(Lists.newArrayList("a", "b", "c", "d"), list);
154     }
155 
testCreation_fiveElements()156     public void testCreation_fiveElements() {
157       List<String> list = ImmutableList.of("a", "b", "c", "d", "e");
158       assertEquals(Lists.newArrayList("a", "b", "c", "d", "e"), list);
159     }
160 
testCreation_sixElements()161     public void testCreation_sixElements() {
162       List<String> list = ImmutableList.of("a", "b", "c", "d", "e", "f");
163       assertEquals(Lists.newArrayList("a", "b", "c", "d", "e", "f"), list);
164     }
165 
testCreation_sevenElements()166     public void testCreation_sevenElements() {
167       List<String> list = ImmutableList.of("a", "b", "c", "d", "e", "f", "g");
168       assertEquals(Lists.newArrayList("a", "b", "c", "d", "e", "f", "g"), list);
169     }
170 
testCreation_eightElements()171     public void testCreation_eightElements() {
172       List<String> list = ImmutableList.of(
173           "a", "b", "c", "d", "e", "f", "g", "h");
174       assertEquals(Lists.newArrayList(
175           "a", "b", "c", "d", "e", "f", "g", "h"), list);
176     }
177 
testCreation_nineElements()178     public void testCreation_nineElements() {
179       List<String> list = ImmutableList.of(
180           "a", "b", "c", "d", "e", "f", "g", "h", "i");
181       assertEquals(Lists.newArrayList(
182           "a", "b", "c", "d", "e", "f", "g", "h", "i"), list);
183     }
184 
testCreation_tenElements()185     public void testCreation_tenElements() {
186       List<String> list = ImmutableList.of(
187           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j");
188       assertEquals(Lists.newArrayList(
189           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j"), list);
190     }
191 
testCreation_elevenElements()192     public void testCreation_elevenElements() {
193       List<String> list = ImmutableList.of(
194           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k");
195       assertEquals(Lists.newArrayList(
196           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"), list);
197     }
198 
199     // Varargs versions
200 
testCreation_twelveElements()201     public void testCreation_twelveElements() {
202       List<String> list = ImmutableList.of(
203           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l");
204       assertEquals(Lists.newArrayList(
205           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"), list);
206     }
207 
testCreation_thirteenElements()208     public void testCreation_thirteenElements() {
209       List<String> list = ImmutableList.of(
210           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m");
211       assertEquals(Lists.newArrayList(
212           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"),
213           list);
214     }
215 
testCreation_fourteenElements()216     public void testCreation_fourteenElements() {
217       List<String> list = ImmutableList.of(
218           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n");
219       assertEquals(Lists.newArrayList(
220           "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n"),
221           list);
222     }
223 
testCreation_singletonNull()224     public void testCreation_singletonNull() {
225       try {
226         ImmutableList.of((String) null);
227         fail();
228       } catch (NullPointerException expected) {
229       }
230     }
231 
testCreation_withNull()232     public void testCreation_withNull() {
233       try {
234         ImmutableList.of("a", null, "b");
235         fail();
236       } catch (NullPointerException expected) {
237       }
238     }
239 
testCreation_generic()240     public void testCreation_generic() {
241       List<String> a = ImmutableList.of("a");
242       // only verify that there is no compile warning
243       ImmutableList.of(a, a);
244     }
245 
testCreation_arrayOfArray()246     public void testCreation_arrayOfArray() {
247       String[] array = new String[] { "a" };
248       List<String[]> list = ImmutableList.<String[]>of(array);
249       assertEquals(Collections.singletonList(array), list);
250     }
251 
testCopyOf_emptyArray()252     public void testCopyOf_emptyArray() {
253       String[] array = new String[0];
254       List<String> list = ImmutableList.copyOf(array);
255       assertEquals(Collections.emptyList(), list);
256     }
257 
testCopyOf_arrayOfOneElement()258     public void testCopyOf_arrayOfOneElement() {
259       String[] array = new String[] { "a" };
260       List<String> list = ImmutableList.copyOf(array);
261       assertEquals(Collections.singletonList("a"), list);
262     }
263 
testCopyOf_nullArray()264     public void testCopyOf_nullArray() {
265       try {
266         ImmutableList.copyOf((String[]) null);
267         fail();
268       } catch(NullPointerException expected) {
269       }
270     }
271 
testCopyOf_arrayContainingOnlyNull()272     public void testCopyOf_arrayContainingOnlyNull() {
273       String[] array = new String[] { null };
274       try {
275         ImmutableList.copyOf(array);
276         fail();
277       } catch (NullPointerException expected) {
278       }
279     }
280 
testCopyOf_collection_empty()281     public void testCopyOf_collection_empty() {
282       // "<String>" is required to work around a javac 1.5 bug.
283       Collection<String> c = MinimalCollection.<String>of();
284       List<String> list = ImmutableList.copyOf(c);
285       assertEquals(Collections.emptyList(), list);
286     }
287 
testCopyOf_collection_oneElement()288     public void testCopyOf_collection_oneElement() {
289       Collection<String> c = MinimalCollection.of("a");
290       List<String> list = ImmutableList.copyOf(c);
291       assertEquals(Collections.singletonList("a"), list);
292     }
293 
testCopyOf_collection_general()294     public void testCopyOf_collection_general() {
295       Collection<String> c = MinimalCollection.of("a", "b", "a");
296       List<String> list = ImmutableList.copyOf(c);
297       assertEquals(asList("a", "b", "a"), list);
298       List<String> mutableList = asList("a", "b");
299       list = ImmutableList.copyOf(mutableList);
300       mutableList.set(0, "c");
301       assertEquals(asList("a", "b"), list);
302     }
303 
testCopyOf_collectionContainingNull()304     public void testCopyOf_collectionContainingNull() {
305       Collection<String> c = MinimalCollection.of("a", null, "b");
306       try {
307         ImmutableList.copyOf(c);
308         fail();
309       } catch (NullPointerException expected) {
310       }
311     }
312 
testCopyOf_iterator_empty()313     public void testCopyOf_iterator_empty() {
314       Iterator<String> iterator = Iterators.emptyIterator();
315       List<String> list = ImmutableList.copyOf(iterator);
316       assertEquals(Collections.emptyList(), list);
317     }
318 
testCopyOf_iterator_oneElement()319     public void testCopyOf_iterator_oneElement() {
320       Iterator<String> iterator = Iterators.singletonIterator("a");
321       List<String> list = ImmutableList.copyOf(iterator);
322       assertEquals(Collections.singletonList("a"), list);
323     }
324 
testCopyOf_iterator_general()325     public void testCopyOf_iterator_general() {
326       Iterator<String> iterator = asList("a", "b", "a").iterator();
327       List<String> list = ImmutableList.copyOf(iterator);
328       assertEquals(asList("a", "b", "a"), list);
329     }
330 
testCopyOf_iteratorContainingNull()331     public void testCopyOf_iteratorContainingNull() {
332       Iterator<String> iterator = asList("a", null, "b").iterator();
333       try {
334         ImmutableList.copyOf(iterator);
335         fail();
336       } catch (NullPointerException expected) {
337       }
338     }
339 
testCopyOf_iteratorNull()340     public void testCopyOf_iteratorNull() {
341       try {
342         ImmutableList.copyOf((Iterator<String>) null);
343         fail();
344       } catch(NullPointerException expected) {
345       }
346     }
347 
testCopyOf_concurrentlyMutating()348     public void testCopyOf_concurrentlyMutating() {
349       List<String> sample = Lists.newArrayList("a", "b", "c");
350       for (int delta : new int[] {-1, 0, 1}) {
351         for (int i = 0; i < sample.size(); i++) {
352           Collection<String> misleading =
353               Helpers.misleadingSizeCollection(delta);
354           List<String> expected = sample.subList(0, i);
355           misleading.addAll(expected);
356           assertEquals(expected, ImmutableList.copyOf(misleading));
357           assertEquals(expected,
358               ImmutableList.copyOf((Iterable<String>) misleading));
359         }
360       }
361     }
362 
363     private static class CountingIterable implements Iterable<String> {
364       int count = 0;
365       @Override
iterator()366       public Iterator<String> iterator() {
367         count++;
368         return asList("a", "b", "a").iterator();
369       }
370     }
371 
testCopyOf_plainIterable()372     public void testCopyOf_plainIterable() {
373       CountingIterable iterable = new CountingIterable();
374       List<String> list = ImmutableList.copyOf(iterable);
375       assertEquals(asList("a", "b", "a"), list);
376     }
377 
testCopyOf_plainIterable_iteratesOnce()378     public void testCopyOf_plainIterable_iteratesOnce() {
379       CountingIterable iterable = new CountingIterable();
380       ImmutableList.copyOf(iterable);
381       assertEquals(1, iterable.count);
382     }
383 
testCopyOf_shortcut_empty()384     public void testCopyOf_shortcut_empty() {
385       Collection<String> c = ImmutableList.of();
386       assertSame(c, ImmutableList.copyOf(c));
387     }
388 
testCopyOf_shortcut_singleton()389     public void testCopyOf_shortcut_singleton() {
390       Collection<String> c = ImmutableList.of("a");
391       assertSame(c, ImmutableList.copyOf(c));
392     }
393 
testCopyOf_shortcut_immutableList()394     public void testCopyOf_shortcut_immutableList() {
395       Collection<String> c = ImmutableList.of("a", "b", "c");
396       assertSame(c, ImmutableList.copyOf(c));
397     }
398   }
399 
400   @GwtIncompatible("reflection")
401   public static class ConcurrentTests extends TestCase {
402     enum WrapWithIterable { WRAP, NO_WRAP }
403 
runConcurrentlyMutatedTest( Collection<Integer> initialContents, Iterable<ListFrobber> actionsToPerformConcurrently, WrapWithIterable wrap)404     private static void runConcurrentlyMutatedTest(
405         Collection<Integer> initialContents,
406         Iterable<ListFrobber> actionsToPerformConcurrently,
407         WrapWithIterable wrap) {
408       ConcurrentlyMutatedList<Integer> concurrentlyMutatedList =
409           newConcurrentlyMutatedList(
410               initialContents, actionsToPerformConcurrently);
411 
412       Iterable<Integer> iterableToCopy = wrap == WrapWithIterable.WRAP
413           ? unmodifiableIterable(concurrentlyMutatedList)
414           : concurrentlyMutatedList;
415 
416       ImmutableList<Integer> copyOfIterable =
417           ImmutableList.copyOf(iterableToCopy);
418 
419       assertTrue(concurrentlyMutatedList.getAllStates()
420           .contains(copyOfIterable));
421 
422       // Check that it's a RegularImmutableList iff it is nonempty:
423       assertEquals(copyOfIterable.size() == 0, copyOfIterable.isEmpty());
424     }
425 
runConcurrentlyMutatedTest(WrapWithIterable wrap)426     private static void runConcurrentlyMutatedTest(WrapWithIterable wrap) {
427       /*
428        * TODO: Iterate over many array sizes and all possible operation lists,
429        * performing adds and removes in different ways.
430        */
431       runConcurrentlyMutatedTest(
432           elements(),
433           ops(add(1), add(2)),
434           wrap);
435 
436       runConcurrentlyMutatedTest(
437           elements(),
438           ops(add(1), nop()),
439           wrap);
440 
441       runConcurrentlyMutatedTest(
442           elements(),
443           ops(add(1), remove()),
444           wrap);
445 
446       runConcurrentlyMutatedTest(
447           elements(),
448           ops(nop(), add(1)),
449           wrap);
450 
451       runConcurrentlyMutatedTest(
452           elements(1),
453           ops(remove(), nop()),
454           wrap);
455 
456       runConcurrentlyMutatedTest(
457           elements(1),
458           ops(remove(), add(2)),
459           wrap);
460 
461       runConcurrentlyMutatedTest(
462           elements(1, 2),
463           ops(remove(), remove()),
464           wrap);
465 
466       runConcurrentlyMutatedTest(
467           elements(1, 2),
468           ops(remove(), nop()),
469           wrap);
470 
471       runConcurrentlyMutatedTest(
472           elements(1, 2),
473           ops(remove(), add(3)),
474           wrap);
475 
476       runConcurrentlyMutatedTest(
477           elements(1, 2),
478           ops(nop(), remove()),
479           wrap);
480 
481       runConcurrentlyMutatedTest(
482           elements(1, 2, 3),
483           ops(remove(), remove()),
484           wrap);
485     }
486 
elements(Integer... elements)487     private static ImmutableList<Integer> elements(Integer... elements) {
488       return ImmutableList.copyOf(elements);
489     }
490 
ops(ListFrobber... elements)491     private static ImmutableList<ListFrobber> ops(ListFrobber... elements) {
492       return ImmutableList.copyOf(elements);
493     }
494 
testCopyOf_concurrentlyMutatedList()495     public void testCopyOf_concurrentlyMutatedList() {
496       runConcurrentlyMutatedTest(WrapWithIterable.NO_WRAP);
497     }
498 
testCopyOf_concurrentlyMutatedIterable()499     public void testCopyOf_concurrentlyMutatedIterable() {
500       runConcurrentlyMutatedTest(WrapWithIterable.WRAP);
501     }
502 
503     /** An operation to perform on a list. */
504     interface ListFrobber {
perform(List<Integer> list)505       void perform(List<Integer> list);
506     }
507 
add(final int element)508     static final ListFrobber add(final int element) {
509       return new ListFrobber() {
510         @Override
511         public void perform(List<Integer> list) {
512           list.add(0, element);
513         }
514       };
515     }
516 
remove()517     static final ListFrobber remove() {
518       return new ListFrobber() {
519         @Override
520         public void perform(List<Integer> list) {
521           list.remove(0);
522         }
523       };
524     }
525 
526     static final ListFrobber nop() {
527       return new ListFrobber() {
528         @Override
529         public void perform(List<Integer> list) {
530         }
531       };
532     }
533 
534     /**
535      * A list that mutates itself after every call to each of its {@link List}
536      * methods.
537      */
538     interface ConcurrentlyMutatedList<E> extends List<E> {
539       /**
540        * The elements of a {@link ConcurrentlyMutatedList} are added and removed
541        * over time. This method returns every state that the list has passed
542        * through at some point.
543        */
544       Set<List<E>> getAllStates();
545     }
546 
547     /**
548      * Returns a {@link ConcurrentlyMutatedList} that performs the given
549      * operations as its concurrent modifications. The mutations occur in the
550      * same thread as the triggering method call.
551      */
552     private static ConcurrentlyMutatedList<Integer> newConcurrentlyMutatedList(
553         final Collection<Integer> initialContents,
554         final Iterable<ListFrobber> actionsToPerformConcurrently) {
555       InvocationHandler invocationHandler = new InvocationHandler() {
556         final CopyOnWriteArrayList<Integer> delegate =
557             new CopyOnWriteArrayList<Integer>(initialContents);
558 
559         final Method getAllStatesMethod = getOnlyElement(asList(
560             ConcurrentlyMutatedList.class.getDeclaredMethods()));
561 
562         final Iterator<ListFrobber> remainingActions =
563             actionsToPerformConcurrently.iterator();
564 
565         final Set<List<Integer>> allStates = newHashSet();
566 
567         @Override
568         public Object invoke(Object proxy, Method method,
569             Object[] args) throws Throwable {
570           return method.equals(getAllStatesMethod)
571               ? getAllStates()
572               : invokeListMethod(method, args);
573         }
574 
575         private Set<List<Integer>> getAllStates() {
576           return allStates;
577         }
578 
579         private Object invokeListMethod(Method method, Object[] args)
580             throws Throwable {
581           try {
582             Object returnValue = method.invoke(delegate, args);
583             mutateDelegate();
584             return returnValue;
585           } catch (InvocationTargetException e) {
586             throw e.getCause();
587           } catch (IllegalAccessException e) {
588             throw new AssertionError(e);
589           }
590         }
591 
592         private void mutateDelegate() {
593           allStates.add(ImmutableList.copyOf(delegate));
594           remainingActions.next().perform(delegate);
595           allStates.add(ImmutableList.copyOf(delegate));
596         }
597       };
598 
599       @SuppressWarnings("unchecked")
600       ConcurrentlyMutatedList<Integer> list =
601           (ConcurrentlyMutatedList<Integer>) newProxyInstance(
602               ImmutableListTest.CreationTests.class.getClassLoader(),
603               new Class[] {ConcurrentlyMutatedList.class}, invocationHandler);
604       return list;
605     }
606   }
607 
608   public static class BasicTests extends TestCase {
609 
610     @GwtIncompatible("NullPointerTester")
611     public void testNullPointers() throws Exception {
612       NullPointerTester tester = new NullPointerTester();
613       tester.testAllPublicStaticMethods(ImmutableList.class);
614       tester.testAllPublicInstanceMethods(ImmutableList.of(1, 2, 3));
615     }
616 
617     @GwtIncompatible("SerializableTester")
618     public void testSerialization_empty() {
619       Collection<String> c = ImmutableList.of();
620       assertSame(c, SerializableTester.reserialize(c));
621     }
622 
623     @GwtIncompatible("SerializableTester")
624     public void testSerialization_singleton() {
625       Collection<String> c = ImmutableList.of("a");
626       ImmutableList<String> copy = (SingletonImmutableList<String>)
627           SerializableTester.reserializeAndAssert(c);
628     }
629 
630     @GwtIncompatible("SerializableTester")
631     public void testSerialization_multiple() {
632       Collection<String> c = ImmutableList.of("a", "b", "c");
633       SerializableTester.reserializeAndAssert(c);
634     }
635 
636     public void testEquals_immutableList() {
637       Collection<String> c = ImmutableList.of("a", "b", "c");
638       assertTrue(c.equals(ImmutableList.of("a", "b", "c")));
639       assertFalse(c.equals(ImmutableList.of("a", "c", "b")));
640       assertFalse(c.equals(ImmutableList.of("a", "b")));
641       assertFalse(c.equals(ImmutableList.of("a", "b", "c", "d")));
642     }
643 
644     public void testBuilderAdd() {
645       ImmutableList<String> list = new ImmutableList.Builder<String>()
646           .add("a")
647           .add("b")
648           .add("a")
649           .add("c")
650           .build();
651       assertEquals(asList("a", "b", "a", "c"), list);
652     }
653 
654     public void testBuilderAdd_varargs() {
655       ImmutableList<String> list = new ImmutableList.Builder<String>()
656           .add("a", "b", "a", "c")
657           .build();
658       assertEquals(asList("a", "b", "a", "c"), list);
659     }
660 
661     public void testBuilderAddAll_iterable() {
662       List<String> a = asList("a", "b");
663       List<String> b = asList("c", "d");
664       ImmutableList<String> list = new ImmutableList.Builder<String>()
665           .addAll(a)
666           .addAll(b)
667           .build();
668       assertEquals(asList( "a", "b", "c", "d"), list);
669       b.set(0, "f");
670       assertEquals(asList( "a", "b", "c", "d"), list);
671     }
672 
673     public void testBuilderAddAll_iterator() {
674       List<String> a = asList("a", "b");
675       List<String> b = asList("c", "d");
676       ImmutableList<String> list = new ImmutableList.Builder<String>()
677           .addAll(a.iterator())
678           .addAll(b.iterator())
679           .build();
680       assertEquals(asList( "a", "b", "c", "d"), list);
681       b.set(0, "f");
682       assertEquals(asList( "a", "b", "c", "d"), list);
683     }
684 
685     public void testComplexBuilder() {
686       List<Integer> colorElem = asList(0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF);
687       ImmutableList.Builder<Integer> webSafeColorsBuilder
688           = ImmutableList.builder();
689       for (Integer red : colorElem) {
690         for (Integer green : colorElem) {
691           for (Integer blue : colorElem) {
692             webSafeColorsBuilder.add((red << 16) + (green << 8) + blue);
693           }
694         }
695       }
696       ImmutableList<Integer> webSafeColors = webSafeColorsBuilder.build();
697       assertEquals(216, webSafeColors.size());
698       Integer[] webSafeColorArray =
699           webSafeColors.toArray(new Integer[webSafeColors.size()]);
700       assertEquals(0x000000, (int) webSafeColorArray[0]);
701       assertEquals(0x000033, (int) webSafeColorArray[1]);
702       assertEquals(0x000066, (int) webSafeColorArray[2]);
703       assertEquals(0x003300, (int) webSafeColorArray[6]);
704       assertEquals(0x330000, (int) webSafeColorArray[36]);
705       assertEquals(0x000066, (int) webSafeColors.get(2));
706       assertEquals(0x003300, (int) webSafeColors.get(6));
707       ImmutableList<Integer> addedColor
708           = webSafeColorsBuilder.add(0x00BFFF).build();
709       assertEquals("Modifying the builder should not have changed any already"
710           + " built sets", 216, webSafeColors.size());
711       assertEquals("the new array should be one bigger than webSafeColors",
712           217, addedColor.size());
713       Integer[] appendColorArray =
714           addedColor.toArray(new Integer[addedColor.size()]);
715       assertEquals(0x00BFFF, (int) appendColorArray[216]);
716     }
717 
718     public void testBuilderAddHandlesNullsCorrectly() {
719       ImmutableList.Builder<String> builder = ImmutableList.builder();
720       try {
721         builder.add((String) null);
722         fail("expected NullPointerException");
723       } catch (NullPointerException expected) {
724       }
725 
726       try {
727         builder.add((String[]) null);
728         fail("expected NullPointerException");
729       } catch (NullPointerException expected) {
730       }
731 
732       try {
733         builder.add("a", null, "b");
734         fail("expected NullPointerException");
735       } catch (NullPointerException expected) {
736       }
737     }
738 
739     public void testBuilderAddAllHandlesNullsCorrectly() {
740       ImmutableList.Builder<String> builder = ImmutableList.builder();
741       try {
742         builder.addAll((Iterable<String>) null);
743         fail("expected NullPointerException");
744       } catch (NullPointerException expected) {
745       }
746 
747       try {
748         builder.addAll((Iterator<String>) null);
749         fail("expected NullPointerException");
750       } catch (NullPointerException expected) {
751       }
752 
753       builder = ImmutableList.builder();
754       List<String> listWithNulls = asList("a", null, "b");
755       try {
756         builder.addAll(listWithNulls);
757         fail("expected NullPointerException");
758       } catch (NullPointerException expected) {
759       }
760 
761       builder = ImmutableList.builder();
762       Iterator<String> iteratorWithNulls = asList("a", null, "b").iterator();
763       try {
764         builder.addAll(iteratorWithNulls);
765         fail("expected NullPointerException");
766       } catch (NullPointerException expected) {
767       }
768 
769       Iterable<String> iterableWithNulls = MinimalIterable.of("a", null, "b");
770       try {
771         builder.addAll(iterableWithNulls);
772         fail("expected NullPointerException");
773       } catch (NullPointerException expected) {
774       }
775     }
776 
777     public void testAsList() {
778       ImmutableList<String> list = ImmutableList.of("a", "b");
779       assertSame(list, list.asList());
780     }
781   }
782 }
783