Home | History | Annotate | Download | only in collect
      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")
     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 {
    131     public void testCreation_noArgs() {
    132       List<String> list = ImmutableList.of();
    133       assertEquals(Collections.emptyList(), list);
    134     }
    135 
    136     public void testCreation_oneElement() {
    137       List<String> list = ImmutableList.of("a");
    138       assertEquals(Collections.singletonList("a"), list);
    139     }
    140 
    141     public void testCreation_twoElements() {
    142       List<String> list = ImmutableList.of("a", "b");
    143       assertEquals(Lists.newArrayList("a", "b"), list);
    144     }
    145 
    146     public void testCreation_threeElements() {
    147       List<String> list = ImmutableList.of("a", "b", "c");
    148       assertEquals(Lists.newArrayList("a", "b", "c"), list);
    149     }
    150 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    224     public void testCreation_singletonNull() {
    225       try {
    226         ImmutableList.of((String) null);
    227         fail();
    228       } catch (NullPointerException expected) {
    229       }
    230     }
    231 
    232     public void testCreation_withNull() {
    233       try {
    234         ImmutableList.of("a", null, "b");
    235         fail();
    236       } catch (NullPointerException expected) {
    237       }
    238     }
    239 
    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 
    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 
    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 
    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 
    264     public void testCopyOf_nullArray() {
    265       try {
    266         ImmutableList.copyOf((String[]) null);
    267         fail();
    268       } catch(NullPointerException expected) {
    269       }
    270     }
    271 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    340     public void testCopyOf_iteratorNull() {
    341       try {
    342         ImmutableList.copyOf((Iterator<String>) null);
    343         fail();
    344       } catch(NullPointerException expected) {
    345       }
    346     }
    347 
    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
    366       public Iterator<String> iterator() {
    367         count++;
    368         return asList("a", "b", "a").iterator();
    369       }
    370     }
    371 
    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 
    378     public void testCopyOf_plainIterable_iteratesOnce() {
    379       CountingIterable iterable = new CountingIterable();
    380       ImmutableList.copyOf(iterable);
    381       assertEquals(1, iterable.count);
    382     }
    383 
    384     public void testCopyOf_shortcut_empty() {
    385       Collection<String> c = ImmutableList.of();
    386       assertSame(c, ImmutableList.copyOf(c));
    387     }
    388 
    389     public void testCopyOf_shortcut_singleton() {
    390       Collection<String> c = ImmutableList.of("a");
    391       assertSame(c, ImmutableList.copyOf(c));
    392     }
    393 
    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 
    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 
    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 
    487     private static ImmutableList<Integer> elements(Integer... elements) {
    488       return ImmutableList.copyOf(elements);
    489     }
    490 
    491     private static ImmutableList<ListFrobber> ops(ListFrobber... elements) {
    492       return ImmutableList.copyOf(elements);
    493     }
    494 
    495     public void testCopyOf_concurrentlyMutatedList() {
    496       runConcurrentlyMutatedTest(WrapWithIterable.NO_WRAP);
    497     }
    498 
    499     public void testCopyOf_concurrentlyMutatedIterable() {
    500       runConcurrentlyMutatedTest(WrapWithIterable.WRAP);
    501     }
    502 
    503     /** An operation to perform on a list. */
    504     interface ListFrobber {
    505       void perform(List<Integer> list);
    506     }
    507 
    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 
    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