ListsTest.java revision 1d580d0f6ee4f21eb309ba7b509d2c6d671c4044
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
17package com.google.common.collect;
18
19import static com.google.common.base.Preconditions.checkNotNull;
20import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
21import static java.util.Arrays.asList;
22import static java.util.Collections.singletonList;
23import static org.junit.contrib.truth.Truth.ASSERT;
24
25import com.google.common.annotations.GwtCompatible;
26import com.google.common.annotations.GwtIncompatible;
27import com.google.common.base.Function;
28import com.google.common.base.Functions;
29import com.google.common.collect.testing.IteratorTester;
30import com.google.common.collect.testing.ListTestSuiteBuilder;
31import com.google.common.collect.testing.SampleElements;
32import com.google.common.collect.testing.TestListGenerator;
33import com.google.common.collect.testing.TestStringListGenerator;
34import com.google.common.collect.testing.features.CollectionFeature;
35import com.google.common.collect.testing.features.CollectionSize;
36import com.google.common.collect.testing.features.ListFeature;
37import com.google.common.testing.NullPointerTester;
38import com.google.common.testing.SerializableTester;
39
40import junit.framework.Test;
41import junit.framework.TestCase;
42import junit.framework.TestSuite;
43
44import org.easymock.EasyMock;
45
46import java.io.Serializable;
47import java.util.ArrayList;
48import java.util.Collection;
49import java.util.Collections;
50import java.util.Iterator;
51import java.util.LinkedList;
52import java.util.List;
53import java.util.ListIterator;
54import java.util.NoSuchElementException;
55import 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)
65public 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