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