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.base.Preconditions.checkNotNull;
     20 import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
     21 import static java.util.Arrays.asList;
     22 import static java.util.Collections.singletonList;
     23 import static org.junit.contrib.truth.Truth.ASSERT;
     24 
     25 import com.google.common.annotations.GwtCompatible;
     26 import com.google.common.annotations.GwtIncompatible;
     27 import com.google.common.base.Function;
     28 import com.google.common.base.Functions;
     29 import com.google.common.collect.testing.IteratorTester;
     30 import com.google.common.collect.testing.ListTestSuiteBuilder;
     31 import com.google.common.collect.testing.SampleElements;
     32 import com.google.common.collect.testing.TestListGenerator;
     33 import com.google.common.collect.testing.TestStringListGenerator;
     34 import com.google.common.collect.testing.features.CollectionFeature;
     35 import com.google.common.collect.testing.features.CollectionSize;
     36 import com.google.common.collect.testing.features.ListFeature;
     37 import com.google.common.testing.NullPointerTester;
     38 import com.google.common.testing.SerializableTester;
     39 
     40 import junit.framework.Test;
     41 import junit.framework.TestCase;
     42 import junit.framework.TestSuite;
     43 
     44 import org.easymock.EasyMock;
     45 
     46 import java.io.Serializable;
     47 import java.util.ArrayList;
     48 import java.util.Collection;
     49 import java.util.Collections;
     50 import java.util.Iterator;
     51 import java.util.LinkedList;
     52 import java.util.List;
     53 import java.util.ListIterator;
     54 import java.util.NoSuchElementException;
     55 import java.util.RandomAccess;
     56 
     57 /**
     58  * Unit test for {@code Lists}.
     59  *
     60  * @author Kevin Bourrillion
     61  * @author Mike Bostock
     62  * @author Jared Levy
     63  */
     64 @GwtCompatible(emulated = true)
     65 public class ListsTest extends TestCase {
     66 
     67   private static final Collection<Integer> SOME_COLLECTION
     68       = asList(0, 1, 1);
     69 
     70   private static final Iterable<Integer> SOME_ITERABLE = new SomeIterable();
     71 
     72   private static class SomeIterable implements Iterable<Integer>, Serializable {
     73     @Override
     74     public Iterator<Integer> iterator() {
     75       return SOME_COLLECTION.iterator();
     76     }
     77     private static final long serialVersionUID = 0;
     78   }
     79 
     80   private static final List<Integer> SOME_LIST
     81       = Lists.newArrayList(1, 2, 3, 4);
     82 
     83   private static final List<Integer> SOME_SEQUENTIAL_LIST
     84       = Lists.newLinkedList(asList(1, 2, 3, 4));
     85 
     86   private static final List<String> SOME_STRING_LIST
     87       = asList("1", "2", "3", "4");
     88 
     89   private static final Function<Number, String> SOME_FUNCTION
     90       = new SomeFunction();
     91 
     92   private static class SomeFunction
     93       implements Function<Number, String>, Serializable {
     94     @Override
     95     public String apply(Number n) {
     96       return String.valueOf(n);
     97     }
     98     private static final long serialVersionUID = 0;
     99   }
    100 
    101   @GwtIncompatible("suite")
    102   public static Test suite() {
    103     TestSuite suite = new TestSuite();
    104     suite.addTestSuite(ListsTest.class);
    105 
    106     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    107           @Override protected List<String> create(String[] elements) {
    108             String[] rest = new String[elements.length - 1];
    109             Platform.unsafeArrayCopy(elements, 1, rest, 0, elements.length - 1);
    110             return Lists.asList(elements[0], rest);
    111           }
    112         })
    113         .named("Lists.asList, 2 parameter")
    114         .withFeatures(CollectionSize.SEVERAL, CollectionSize.ONE,
    115             CollectionFeature.ALLOWS_NULL_VALUES)
    116         .createTestSuite());
    117 
    118     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    119           @Override protected List<String> create(String[] elements) {
    120             String[] rest = new String[elements.length - 2];
    121             Platform.unsafeArrayCopy(elements, 2, rest, 0, elements.length - 2);
    122             return Lists.asList(elements[0], elements[1], rest);
    123           }
    124         })
    125         .named("Lists.asList, 3 parameter")
    126         .withFeatures(CollectionSize.SEVERAL,
    127             CollectionFeature.ALLOWS_NULL_VALUES)
    128         .createTestSuite());
    129 
    130     final Function<String, String> removeFirst
    131         = new Function<String, String>() {
    132             @Override
    133             public String apply(String from) {
    134               return (from.length() == 0) ? from : from.substring(1);
    135             }
    136           };
    137 
    138     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    139           @Override protected List<String> create(String[] elements) {
    140             List<String> fromList = Lists.newArrayList();
    141             for (String element : elements) {
    142               fromList.add("q" + checkNotNull(element));
    143             }
    144             return Lists.transform(fromList, removeFirst);
    145           }
    146         })
    147         .named("Lists.transform, random access, no nulls")
    148         .withFeatures(CollectionSize.ANY,
    149             ListFeature.REMOVE_OPERATIONS,
    150             CollectionFeature.ALLOWS_NULL_QUERIES)
    151         .createTestSuite());
    152 
    153     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    154           @Override protected List<String> create(String[] elements) {
    155             List<String> fromList = Lists.newLinkedList();
    156             for (String element : elements) {
    157               fromList.add("q" + checkNotNull(element));
    158             }
    159             return Lists.transform(fromList, removeFirst);
    160           }
    161         })
    162         .named("Lists.transform, sequential access, no nulls")
    163         .withFeatures(CollectionSize.ANY,
    164             ListFeature.REMOVE_OPERATIONS,
    165             CollectionFeature.ALLOWS_NULL_QUERIES)
    166         .createTestSuite());
    167 
    168     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    169           @Override protected List<String> create(String[] elements) {
    170             List<String> fromList = Lists.newArrayList(elements);
    171             return Lists.transform(fromList, Functions.<String>identity());
    172           }
    173         })
    174         .named("Lists.transform, random access, nulls")
    175         .withFeatures(CollectionSize.ANY,
    176             ListFeature.REMOVE_OPERATIONS,
    177             CollectionFeature.ALLOWS_NULL_VALUES)
    178         .createTestSuite());
    179 
    180     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    181           @Override protected List<String> create(String[] elements) {
    182             List<String> fromList =
    183                 Lists.newLinkedList(asList(elements));
    184             return Lists.transform(fromList, Functions.<String>identity());
    185           }
    186         })
    187         .named("Lists.transform, sequential access, nulls")
    188         .withFeatures(CollectionSize.ANY,
    189             ListFeature.REMOVE_OPERATIONS,
    190             CollectionFeature.ALLOWS_NULL_VALUES)
    191         .createTestSuite());
    192 
    193     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    194       @Override protected List<String> create(String[] elements) {
    195         List<String> list = Lists.newArrayList();
    196         for (int i = elements.length - 1; i >= 0; i--)
    197           list.add(elements[i]);
    198         return Lists.reverse(list);
    199       }
    200     }).named("Lists.reverse[ArrayList]").withFeatures(CollectionSize.ANY,
    201         CollectionFeature.ALLOWS_NULL_VALUES, ListFeature.GENERAL_PURPOSE)
    202         .createTestSuite());
    203 
    204     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    205       @Override protected List<String> create(String[] elements) {
    206         String[] reverseElements = new String[elements.length];
    207         for (int i = elements.length - 1, j = 0; i >= 0; i--, j++)
    208           reverseElements[j] = elements[i];
    209         return Lists.reverse(asList(reverseElements));
    210       }
    211     }).named("Lists.reverse[Arrays.asList]").withFeatures(CollectionSize.ANY,
    212         CollectionFeature.ALLOWS_NULL_VALUES, ListFeature.SUPPORTS_SET)
    213         .createTestSuite());
    214 
    215     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    216       @Override protected List<String> create(String[] elements) {
    217         List<String> list = Lists.newLinkedList();
    218         for (int i = elements.length - 1; i >= 0; i--)
    219           list.add(elements[i]);
    220         return Lists.reverse(list);
    221       }
    222     }).named("Lists.reverse[LinkedList]").withFeatures(CollectionSize.ANY,
    223         CollectionFeature.ALLOWS_NULL_VALUES, ListFeature.GENERAL_PURPOSE)
    224         .createTestSuite());
    225 
    226     suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
    227       @Override protected List<String> create(String[] elements) {
    228         ImmutableList.Builder<String> builder = ImmutableList.builder();
    229         for (int i = elements.length - 1; i >= 0; i--)
    230           builder.add(elements[i]);
    231         return Lists.reverse(builder.build());
    232       }
    233     }).named("Lists.reverse[ImmutableList]").withFeatures(CollectionSize.ANY,
    234         CollectionFeature.ALLOWS_NULL_QUERIES)
    235         .createTestSuite());
    236 
    237     suite.addTest(
    238         ListTestSuiteBuilder.using(new TestListGenerator<Character>() {
    239           @Override public List<Character> create(Object... elements) {
    240             char[] chars = new char[elements.length];
    241             for (int i = 0; i < elements.length; i++)
    242               chars[i] = (Character) elements[i];
    243             return Lists.charactersOf(String.copyValueOf(chars));
    244           }
    245 
    246           @Override public Character[] createArray(int length) {
    247             return new Character[length];
    248           }
    249 
    250           @Override public Iterable<Character> order(
    251               List<Character> insertionOrder) {
    252             return ImmutableList.copyOf(insertionOrder);
    253           }
    254 
    255           @Override public SampleElements<Character> samples() {
    256             return new SampleElements<Character>('a', 'b', 'c', 'd', 'e');
    257           }
    258         }).named("Lists.charactersOf[String]").withFeatures(
    259             CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES)
    260             .createTestSuite());
    261 
    262     suite.addTest(
    263         ListTestSuiteBuilder.using(new TestListGenerator<Character>() {
    264           @Override public List<Character> create(Object... elements) {
    265             char[] chars = new char[elements.length];
    266             for (int i = 0; i < elements.length; i++)
    267               chars[i] = (Character) elements[i];
    268             StringBuilder str = new StringBuilder();
    269             str.append(chars);
    270             return Lists.charactersOf(str);
    271           }
    272 
    273           @Override public Character[] createArray(int length) {
    274             return new Character[length];
    275           }
    276 
    277           @Override public Iterable<Character> order(
    278               List<Character> insertionOrder) {
    279             return ImmutableList.copyOf(insertionOrder);
    280           }
    281 
    282           @Override public SampleElements<Character> samples() {
    283             return new SampleElements<Character>('a', 'b', 'c', 'd', 'e');
    284           }
    285         }).named("Lists.charactersOf[CharSequence]").withFeatures(
    286             CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES)
    287             .createTestSuite());
    288 
    289     return suite;
    290   }
    291 
    292   public void testCharactersOfIsView() {
    293     StringBuilder builder = new StringBuilder("abc");
    294     List<Character> chars = Lists.charactersOf(builder);
    295     assertEquals(asList('a', 'b', 'c'), chars);
    296     builder.append("def");
    297     assertEquals(
    298         asList('a', 'b', 'c', 'd', 'e', 'f'), chars);
    299     builder.deleteCharAt(5);
    300     assertEquals(
    301         asList('a', 'b', 'c', 'd', 'e'), chars);
    302   }
    303 
    304   public void testNewArrayListEmpty() {
    305     ArrayList<Integer> list = Lists.newArrayList();
    306     assertEquals(Collections.emptyList(), list);
    307   }
    308 
    309   public void testNewArrayListWithCapacity() {
    310     ArrayList<Integer> list = Lists.newArrayListWithCapacity(0);
    311     assertEquals(Collections.emptyList(), list);
    312 
    313     ArrayList<Integer> bigger = Lists.newArrayListWithCapacity(256);
    314     assertEquals(Collections.emptyList(), bigger);
    315   }
    316 
    317   public void testNewArrayListWithCapacity_negative() {
    318     try {
    319       Lists.newArrayListWithCapacity(-1);
    320       fail();
    321     } catch (IllegalArgumentException expected) {
    322     }
    323   }
    324 
    325   public void testNewArrayListWithExpectedSize() {
    326     ArrayList<Integer> list = Lists.newArrayListWithExpectedSize(0);
    327     assertEquals(Collections.emptyList(), list);
    328 
    329     ArrayList<Integer> bigger = Lists.newArrayListWithExpectedSize(256);
    330     assertEquals(Collections.emptyList(), bigger);
    331   }
    332 
    333   public void testNewArrayListWithExpectedSize_negative() {
    334     try {
    335       Lists.newArrayListWithExpectedSize(-1);
    336       fail();
    337     } catch (IllegalArgumentException expected) {
    338     }
    339   }
    340 
    341   public void testNewArrayListVarArgs() {
    342     ArrayList<Integer> list = Lists.newArrayList(0, 1, 1);
    343     assertEquals(SOME_COLLECTION, list);
    344   }
    345 
    346   public void testComputeArrayListCapacity() {
    347     assertEquals(5, Lists.computeArrayListCapacity(0));
    348     assertEquals(13, Lists.computeArrayListCapacity(8));
    349     assertEquals(89, Lists.computeArrayListCapacity(77));
    350     assertEquals(22000005, Lists.computeArrayListCapacity(20000000));
    351     assertEquals(Integer.MAX_VALUE,
    352         Lists.computeArrayListCapacity(Integer.MAX_VALUE - 1000));
    353   }
    354 
    355   public void testNewArrayListFromCollection() {
    356     ArrayList<Integer> list = Lists.newArrayList(SOME_COLLECTION);
    357     assertEquals(SOME_COLLECTION, list);
    358   }
    359 
    360   public void testNewArrayListFromIterable() {
    361     ArrayList<Integer> list = Lists.newArrayList(SOME_ITERABLE);
    362     assertEquals(SOME_COLLECTION, list);
    363   }
    364 
    365   public void testNewArrayListFromIterator() {
    366     ArrayList<Integer> list = Lists.newArrayList(SOME_COLLECTION.iterator());
    367     assertEquals(SOME_COLLECTION, list);
    368   }
    369 
    370   public void testNewLinkedListEmpty() {
    371     LinkedList<Integer> list = Lists.newLinkedList();
    372     assertEquals(Collections.emptyList(), list);
    373   }
    374 
    375   public void testNewLinkedListFromCollection() {
    376     LinkedList<Integer> list = Lists.newLinkedList(SOME_COLLECTION);
    377     assertEquals(SOME_COLLECTION, list);
    378   }
    379 
    380   public void testNewLinkedListFromIterable() {
    381     LinkedList<Integer> list = Lists.newLinkedList(SOME_ITERABLE);
    382     assertEquals(SOME_COLLECTION, list);
    383   }
    384 
    385   @GwtIncompatible("NullPointerTester")
    386   public void testNullPointerExceptions() throws Exception {
    387     NullPointerTester tester = new NullPointerTester();
    388     tester.testAllPublicStaticMethods(Lists.class);
    389   }
    390 
    391   /**
    392    * This is just here to illustrate how {@code Arrays#asList} differs from
    393    * {@code Lists#newArrayList}.
    394    */
    395   public void testArraysAsList() {
    396     List<String> ourWay = Lists.newArrayList("foo", "bar", "baz");
    397     List<String> otherWay = asList("foo", "bar", "baz");
    398 
    399     // They're logically equal
    400     assertEquals(ourWay, otherWay);
    401 
    402     // The result of Arrays.asList() is mutable
    403     otherWay.set(0, "FOO");
    404     assertEquals("FOO", otherWay.get(0));
    405 
    406     // But it can't grow
    407     try {
    408       otherWay.add("nope");
    409       fail("no exception thrown");
    410     } catch (UnsupportedOperationException expected) {
    411     }
    412 
    413     // And it can't shrink
    414     try {
    415       otherWay.remove(2);
    416       fail("no exception thrown");
    417     } catch (UnsupportedOperationException expected) {
    418     }
    419   }
    420 
    421   @GwtIncompatible("SerializableTester")
    422   public void testAsList1() {
    423     List<String> list = Lists.asList("foo", new String[] { "bar", "baz" });
    424     checkFooBarBazList(list);
    425     SerializableTester.reserializeAndAssert(list);
    426     assertTrue(list instanceof RandomAccess);
    427 
    428     new IteratorTester<String>(5, UNMODIFIABLE,
    429         asList("foo", "bar", "baz"),
    430         IteratorTester.KnownOrder.KNOWN_ORDER) {
    431       @Override protected Iterator<String> newTargetIterator() {
    432         return Lists.asList("foo", new String[] {"bar", "baz"}).iterator();
    433       }
    434     }.test();
    435   }
    436 
    437   private void checkFooBarBazList(List<String> list) {
    438     ASSERT.that(list).hasContentsInOrder("foo", "bar", "baz");
    439     assertEquals(3, list.size());
    440     assertIndexIsOutOfBounds(list, -1);
    441     assertEquals("foo", list.get(0));
    442     assertEquals("bar", list.get(1));
    443     assertEquals("baz", list.get(2));
    444     assertIndexIsOutOfBounds(list, 3);
    445   }
    446 
    447   public void testAsList1Small() {
    448     List<String> list = Lists.asList("foo", new String[0]);
    449     ASSERT.that(list).hasContentsInOrder("foo");
    450     assertEquals(1, list.size());
    451     assertIndexIsOutOfBounds(list, -1);
    452     assertEquals("foo", list.get(0));
    453     assertIndexIsOutOfBounds(list, 1);
    454     assertTrue(list instanceof RandomAccess);
    455 
    456     new IteratorTester<String>(3, UNMODIFIABLE, singletonList("foo"),
    457         IteratorTester.KnownOrder.KNOWN_ORDER) {
    458       @Override protected Iterator<String> newTargetIterator() {
    459         return Lists.asList("foo", new String[0]).iterator();
    460       }
    461     }.test();
    462   }
    463 
    464   public void testAsList2() {
    465     List<String> list = Lists.asList("foo", "bar", new String[] { "baz" });
    466     checkFooBarBazList(list);
    467     assertTrue(list instanceof RandomAccess);
    468 
    469     new IteratorTester<String>(5, UNMODIFIABLE, asList("foo", "bar",
    470         "baz"), IteratorTester.KnownOrder.KNOWN_ORDER) {
    471       @Override protected Iterator<String> newTargetIterator() {
    472         return Lists.asList("foo", "bar", new String[] {"baz"}).iterator();
    473       }
    474     }.test();
    475   }
    476 
    477   @GwtIncompatible("SerializableTester")
    478   public void testAsList2Small() {
    479     List<String> list = Lists.asList("foo", "bar", new String[0]);
    480     ASSERT.that(list).hasContentsInOrder("foo", "bar");
    481     assertEquals(2, list.size());
    482     assertIndexIsOutOfBounds(list, -1);
    483     assertEquals("foo", list.get(0));
    484     assertEquals("bar", list.get(1));
    485     assertIndexIsOutOfBounds(list, 2);
    486     SerializableTester.reserializeAndAssert(list);
    487     assertTrue(list instanceof RandomAccess);
    488 
    489     new IteratorTester<String>(5, UNMODIFIABLE, asList("foo", "bar"),
    490         IteratorTester.KnownOrder.KNOWN_ORDER) {
    491       @Override protected Iterator<String> newTargetIterator() {
    492         return Lists.asList("foo", "bar", new String[0]).iterator();
    493       }
    494     }.test();
    495   }
    496 
    497   private static void assertIndexIsOutOfBounds(List<String> list, int index) {
    498     try {
    499       list.get(index);
    500       fail();
    501     } catch (IndexOutOfBoundsException expected) {
    502     }
    503   }
    504 
    505   public void testReverseViewRandomAccess() {
    506     List<Integer> fromList = Lists.newArrayList(SOME_LIST);
    507     List<Integer> toList = Lists.reverse(fromList);
    508     assertReverseView(fromList, toList);
    509   }
    510 
    511   public void testReverseViewSequential() {
    512     List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST);
    513     List<Integer> toList = Lists.reverse(fromList);
    514     assertReverseView(fromList, toList);
    515   }
    516 
    517   private static void assertReverseView(List<Integer> fromList,
    518       List<Integer> toList) {
    519     /* fromList modifications reflected in toList */
    520     fromList.set(0, 5);
    521     assertEquals(asList(4, 3, 2, 5), toList);
    522     fromList.add(6);
    523     assertEquals(asList(6, 4, 3, 2, 5), toList);
    524     fromList.add(2, 9);
    525     assertEquals(asList(6, 4, 3, 9, 2, 5), toList);
    526     fromList.remove(Integer.valueOf(2));
    527     assertEquals(asList(6, 4, 3, 9, 5), toList);
    528     fromList.remove(3);
    529     assertEquals(asList(6, 3, 9, 5), toList);
    530 
    531     /* toList modifications reflected in fromList */
    532     toList.remove(0);
    533     assertEquals(asList(5, 9, 3), fromList);
    534     toList.add(7);
    535     assertEquals(asList(7, 5, 9, 3), fromList);
    536     toList.add(5);
    537     assertEquals(asList(5, 7, 5, 9, 3), fromList);
    538     toList.remove(Integer.valueOf(5));
    539     assertEquals(asList(5, 7, 9, 3), fromList);
    540     toList.set(1, 8);
    541     assertEquals(asList(5, 7, 8, 3), fromList);
    542     toList.clear();
    543     assertEquals(Collections.emptyList(), fromList);
    544   }
    545 
    546   @GwtIncompatible("SerializableTester")
    547   public void testTransformEqualityRandomAccess() {
    548     List<String> list = Lists.transform(SOME_LIST, SOME_FUNCTION);
    549     assertEquals(SOME_STRING_LIST, list);
    550     SerializableTester.reserializeAndAssert(list);
    551   }
    552 
    553   @GwtIncompatible("SerializableTester")
    554   public void testTransformEqualitySequential() {
    555     List<String> list = Lists.transform(SOME_SEQUENTIAL_LIST, SOME_FUNCTION);
    556     assertEquals(SOME_STRING_LIST, list);
    557     SerializableTester.reserializeAndAssert(list);
    558   }
    559 
    560   public void testTransformHashCodeRandomAccess() {
    561     List<String> list = Lists.transform(SOME_LIST, SOME_FUNCTION);
    562     assertEquals(SOME_STRING_LIST.hashCode(), list.hashCode());
    563   }
    564 
    565   public void testTransformHashCodeSequential() {
    566     List<String> list = Lists.transform(SOME_SEQUENTIAL_LIST, SOME_FUNCTION);
    567     assertEquals(SOME_STRING_LIST.hashCode(), list.hashCode());
    568   }
    569 
    570   public void testTransformModifiableRandomAccess() {
    571     List<Integer> fromList = Lists.newArrayList(SOME_LIST);
    572     List<String> list = Lists.transform(fromList, SOME_FUNCTION);
    573     assertTransformModifiable(list);
    574   }
    575 
    576   public void testTransformModifiableSequential() {
    577     List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST);
    578     List<String> list = Lists.transform(fromList, SOME_FUNCTION);
    579     assertTransformModifiable(list);
    580   }
    581 
    582   private static void assertTransformModifiable(List<String> list) {
    583     try {
    584       list.add("5");
    585       fail("transformed list is addable");
    586     } catch (UnsupportedOperationException expected) {}
    587     list.remove(0);
    588     assertEquals(asList("2", "3", "4"), list);
    589     list.remove("3");
    590     assertEquals(asList("2", "4"), list);
    591     try {
    592       list.set(0, "5");
    593       fail("transformed list is setable");
    594     } catch (UnsupportedOperationException expected) {}
    595     list.clear();
    596     assertEquals(Collections.emptyList(), list);
    597   }
    598 
    599   public void testTransformViewRandomAccess() {
    600     List<Integer> fromList = Lists.newArrayList(SOME_LIST);
    601     List<String> toList = Lists.transform(fromList, SOME_FUNCTION);
    602     assertTransformView(fromList, toList);
    603   }
    604 
    605   public void testTransformViewSequential() {
    606     List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST);
    607     List<String> toList = Lists.transform(fromList, SOME_FUNCTION);
    608     assertTransformView(fromList, toList);
    609   }
    610 
    611   private static void assertTransformView(List<Integer> fromList,
    612       List<String> toList) {
    613     /* fromList modifications reflected in toList */
    614     fromList.set(0, 5);
    615     assertEquals(asList("5", "2", "3", "4"), toList);
    616     fromList.add(6);
    617     assertEquals(asList("5", "2", "3", "4", "6"), toList);
    618     fromList.remove(Integer.valueOf(2));
    619     assertEquals(asList("5", "3", "4", "6"), toList);
    620     fromList.remove(2);
    621     assertEquals(asList("5", "3", "6"), toList);
    622 
    623     /* toList modifications reflected in fromList */
    624     toList.remove(2);
    625     assertEquals(asList(5, 3), fromList);
    626     toList.remove("5");
    627     assertEquals(asList(3), fromList);
    628     toList.clear();
    629     assertEquals(Collections.emptyList(), fromList);
    630   }
    631 
    632   public void testTransformRandomAccess() {
    633     List<String> list = Lists.transform(SOME_LIST, SOME_FUNCTION);
    634     assertTrue(list instanceof RandomAccess);
    635   }
    636 
    637   public void testTransformSequential() {
    638     List<String> list = Lists.transform(SOME_SEQUENTIAL_LIST, SOME_FUNCTION);
    639     assertFalse(list instanceof RandomAccess);
    640   }
    641 
    642   public void testTransformListIteratorRandomAccess() {
    643     List<Integer> fromList = Lists.newArrayList(SOME_LIST);
    644     List<String> list = Lists.transform(fromList, SOME_FUNCTION);
    645     assertTransformListIterator(list);
    646   }
    647 
    648   public void testTransformListIteratorSequential() {
    649     List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST);
    650     List<String> list = Lists.transform(fromList, SOME_FUNCTION);
    651     assertTransformListIterator(list);
    652   }
    653 
    654   private static void assertTransformListIterator(List<String> list) {
    655     ListIterator<String> iterator = list.listIterator(1);
    656     assertEquals(1, iterator.nextIndex());
    657     assertEquals("2", iterator.next());
    658     assertEquals("3", iterator.next());
    659     assertEquals("4", iterator.next());
    660     assertEquals(4, iterator.nextIndex());
    661     try {
    662       iterator.next();
    663       fail("did not detect end of list");
    664     } catch (NoSuchElementException expected) {}
    665     assertEquals(3, iterator.previousIndex());
    666     assertEquals("4", iterator.previous());
    667     assertEquals("3", iterator.previous());
    668     assertEquals("2", iterator.previous());
    669     assertTrue(iterator.hasPrevious());
    670     assertEquals("1", iterator.previous());
    671     assertFalse(iterator.hasPrevious());
    672     assertEquals(-1, iterator.previousIndex());
    673     try {
    674       iterator.previous();
    675       fail("did not detect beginning of list");
    676     } catch (NoSuchElementException expected) {}
    677     iterator.remove();
    678     assertEquals(asList("2", "3", "4"), list);
    679     assertFalse(list.isEmpty());
    680 
    681     // An UnsupportedOperationException or IllegalStateException may occur.
    682     try {
    683       iterator.add("1");
    684       fail("transformed list iterator is addable");
    685     } catch (UnsupportedOperationException expected) {
    686     } catch (IllegalStateException expected) {}
    687     try {
    688       iterator.set("1");
    689       fail("transformed list iterator is settable");
    690     } catch (UnsupportedOperationException expected) {
    691     } catch (IllegalStateException expected) {}
    692   }
    693 
    694   public void testTransformIteratorRandomAccess() {
    695     List<Integer> fromList = Lists.newArrayList(SOME_LIST);
    696     List<String> list = Lists.transform(fromList, SOME_FUNCTION);
    697     assertTransformIterator(list);
    698   }
    699 
    700   public void testTransformIteratorSequential() {
    701     List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST);
    702     List<String> list = Lists.transform(fromList, SOME_FUNCTION);
    703     assertTransformIterator(list);
    704   }
    705 
    706   /**
    707    * We use this class to avoid the need to suppress generics checks with
    708    * easy mock.
    709    */
    710   private interface IntegerList extends List<Integer> {}
    711 
    712   /**
    713    * This test depends on the fact that {@code AbstractSequentialList.iterator}
    714    * transforms the {@code iterator()} call into a call on {@code
    715    * listIterator(int)}. This is fine because the behavior is clearly
    716    * documented so it's not expected to change.
    717    */
    718   @GwtIncompatible("EsayMock")
    719   public void testTransformedSequentialIterationUsesBackingListIterationOnly() {
    720     List<Integer> randomAccessList = Lists.newArrayList(SOME_SEQUENTIAL_LIST);
    721     ListIterator<Integer> sampleListIterator =
    722         SOME_SEQUENTIAL_LIST.listIterator();
    723     List<Integer> listMock = EasyMock.createMock(IntegerList.class);
    724     EasyMock.expect(listMock.listIterator(0)).andReturn(sampleListIterator);
    725     EasyMock.replay(listMock);
    726     List<String> transform = Lists.transform(listMock, SOME_FUNCTION);
    727     assertTrue(Iterables.elementsEqual(
    728         transform, Lists.transform(randomAccessList, SOME_FUNCTION)));
    729     EasyMock.verify(listMock);
    730   }
    731 
    732   private static void assertTransformIterator(List<String> list) {
    733     Iterator<String> iterator = list.iterator();
    734     assertTrue(iterator.hasNext());
    735     assertEquals("1", iterator.next());
    736     assertTrue(iterator.hasNext());
    737     assertEquals("2", iterator.next());
    738     assertTrue(iterator.hasNext());
    739     assertEquals("3", iterator.next());
    740     assertTrue(iterator.hasNext());
    741     assertEquals("4", iterator.next());
    742     assertFalse(iterator.hasNext());
    743     try {
    744       iterator.next();
    745       fail("did not detect end of list");
    746     } catch (NoSuchElementException expected) {}
    747     iterator.remove();
    748     assertEquals(asList("1", "2", "3"), list);
    749     assertFalse(iterator.hasNext());
    750   }
    751 
    752   public void testPartition_badSize() {
    753     List<Integer> source = Collections.singletonList(1);
    754     try {
    755       Lists.partition(source, 0);
    756       fail();
    757     } catch (IllegalArgumentException expected) {
    758     }
    759   }
    760 
    761   public void testPartition_empty() {
    762     List<Integer> source = Collections.emptyList();
    763     List<List<Integer>> partitions = Lists.partition(source, 1);
    764     assertTrue(partitions.isEmpty());
    765     assertEquals(0, partitions.size());
    766   }
    767 
    768   public void testPartition_1_1() {
    769     List<Integer> source = Collections.singletonList(1);
    770     List<List<Integer>> partitions = Lists.partition(source, 1);
    771     assertEquals(1, partitions.size());
    772     assertEquals(Collections.singletonList(1), partitions.get(0));
    773   }
    774 
    775   public void testPartition_1_2() {
    776     List<Integer> source = Collections.singletonList(1);
    777     List<List<Integer>> partitions = Lists.partition(source, 2);
    778     assertEquals(1, partitions.size());
    779     assertEquals(Collections.singletonList(1), partitions.get(0));
    780   }
    781 
    782   public void testPartition_2_1() {
    783     List<Integer> source = asList(1, 2);
    784     List<List<Integer>> partitions = Lists.partition(source, 1);
    785     assertEquals(2, partitions.size());
    786     assertEquals(Collections.singletonList(1), partitions.get(0));
    787     assertEquals(Collections.singletonList(2), partitions.get(1));
    788   }
    789 
    790   public void testPartition_3_2() {
    791     List<Integer> source = asList(1, 2, 3);
    792     List<List<Integer>> partitions = Lists.partition(source, 2);
    793     assertEquals(2, partitions.size());
    794     assertEquals(asList(1, 2), partitions.get(0));
    795     assertEquals(asList(3), partitions.get(1));
    796   }
    797 
    798   @GwtIncompatible("ArrayList.subList doesn't implement RandomAccess in GWT.")
    799   public void testPartitionRandomAccessTrue() {
    800     List<Integer> source = asList(1, 2, 3);
    801     List<List<Integer>> partitions = Lists.partition(source, 2);
    802 
    803     assertTrue("partition should be RandomAccess, but not: "
    804         + partitions.getClass(),
    805         partitions instanceof RandomAccess);
    806 
    807     assertTrue("partition[0] should be RandomAccess, but not: "
    808         + partitions.get(0).getClass(),
    809         partitions.get(0) instanceof RandomAccess);
    810 
    811     assertTrue("partition[1] should be RandomAccess, but not: "
    812         + partitions.get(1).getClass(),
    813         partitions.get(1) instanceof RandomAccess);
    814   }
    815 
    816   public void testPartitionRandomAccessFalse() {
    817     List<Integer> source = Lists.newLinkedList(asList(1, 2, 3));
    818     List<List<Integer>> partitions = Lists.partition(source, 2);
    819     assertFalse(partitions instanceof RandomAccess);
    820     assertFalse(partitions.get(0) instanceof RandomAccess);
    821     assertFalse(partitions.get(1) instanceof RandomAccess);
    822   }
    823 
    824   // TODO: use the ListTestSuiteBuilder
    825 
    826   public void testPartition_view() {
    827     List<Integer> list = asList(1, 2, 3);
    828     List<List<Integer>> partitions = Lists.partition(list, 3);
    829 
    830     // Changes before the partition is retrieved are reflected
    831     list.set(0, 3);
    832 
    833     Iterator<List<Integer>> iterator = partitions.iterator();
    834 
    835     // Changes before the partition is retrieved are reflected
    836     list.set(1, 4);
    837 
    838     List<Integer> first = iterator.next();
    839 
    840     // Changes after are too (unlike Iterables.partition)
    841     list.set(2, 5);
    842 
    843     assertEquals(asList(3, 4, 5), first);
    844 
    845     // Changes to a sublist also write through to the original list
    846     first.set(1, 6);
    847     assertEquals(asList(3, 6, 5), list);
    848   }
    849 
    850   public void testPartitionSize_1() {
    851     List<Integer> list = asList(1, 2, 3);
    852     assertEquals(1, Lists.partition(list, Integer.MAX_VALUE).size());
    853     assertEquals(1, Lists.partition(list, Integer.MAX_VALUE - 1).size());
    854   }
    855 
    856   @GwtIncompatible("cannot do such a big explicit copy")
    857   public void testPartitionSize_2() {
    858     assertEquals(2, Lists.partition(Collections.nCopies(0x40000001, 1), 0x40000000).size());
    859   }
    860 
    861   // These tests are quick and basic and don't actually show unmodifiability...
    862 }
    863