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.collect.Iterators.advance;
20import static com.google.common.collect.Iterators.get;
21import static com.google.common.collect.Iterators.getLast;
22import static com.google.common.collect.Lists.newArrayList;
23import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
24import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
25import static com.google.common.truth.Truth.assertThat;
26import static java.util.Arrays.asList;
27import static java.util.Collections.singleton;
28
29import com.google.common.annotations.GwtCompatible;
30import com.google.common.annotations.GwtIncompatible;
31import com.google.common.base.Function;
32import com.google.common.base.Predicate;
33import com.google.common.base.Predicates;
34import com.google.common.collect.testing.IteratorFeature;
35import com.google.common.collect.testing.IteratorTester;
36import com.google.common.collect.testing.ListTestSuiteBuilder;
37import com.google.common.collect.testing.TestStringListGenerator;
38import com.google.common.collect.testing.features.CollectionFeature;
39import com.google.common.collect.testing.features.CollectionSize;
40import com.google.common.collect.testing.features.ListFeature;
41import com.google.common.testing.NullPointerTester;
42
43import junit.framework.AssertionFailedError;
44import junit.framework.Test;
45import junit.framework.TestCase;
46import junit.framework.TestSuite;
47
48import java.util.Arrays;
49import java.util.Collection;
50import java.util.Collections;
51import java.util.ConcurrentModificationException;
52import java.util.Enumeration;
53import java.util.Iterator;
54import java.util.List;
55import java.util.ListIterator;
56import java.util.NoSuchElementException;
57import java.util.RandomAccess;
58import java.util.Set;
59import java.util.Vector;
60
61/**
62 * Unit test for {@code Iterators}.
63 *
64 * @author Kevin Bourrillion
65 */
66@GwtCompatible(emulated = true)
67public class IteratorsTest extends TestCase {
68
69  @GwtIncompatible("suite")
70  public static Test suite() {
71    TestSuite suite = new TestSuite(IteratorsTest.class.getSimpleName());
72    suite.addTest(testsForRemoveAllAndRetainAll());
73    suite.addTestSuite(IteratorsTest.class);
74    return suite;
75  }
76
77  public void testEmptyIterator() {
78    Iterator<String> iterator = Iterators.emptyIterator();
79    assertFalse(iterator.hasNext());
80    try {
81      iterator.next();
82      fail("no exception thrown");
83    } catch (NoSuchElementException expected) {
84    }
85    try {
86      iterator.remove();
87      fail("no exception thrown");
88    } catch (UnsupportedOperationException expected) {
89    }
90  }
91
92  public void testEmptyListIterator() {
93    ListIterator<String> iterator = Iterators.emptyListIterator();
94    assertFalse(iterator.hasNext());
95    assertFalse(iterator.hasPrevious());
96    assertEquals(0, iterator.nextIndex());
97    assertEquals(-1, iterator.previousIndex());
98    try {
99      iterator.next();
100      fail("no exception thrown");
101    } catch (NoSuchElementException expected) {
102    }
103    try {
104      iterator.previous();
105      fail("no exception thrown");
106    } catch (NoSuchElementException expected) {
107    }
108    try {
109      iterator.remove();
110      fail("no exception thrown");
111    } catch (UnsupportedOperationException expected) {
112    }
113    try {
114      iterator.set("a");
115      fail("no exception thrown");
116    } catch (UnsupportedOperationException expected) {
117    }
118    try {
119      iterator.add("a");
120      fail("no exception thrown");
121    } catch (UnsupportedOperationException expected) {
122    }
123  }
124
125  public void testEmptyModifiableIterator() {
126    Iterator<String> iterator = Iterators.emptyModifiableIterator();
127    assertFalse(iterator.hasNext());
128    try {
129      iterator.next();
130      fail("Expected NoSuchElementException");
131    } catch (NoSuchElementException expected) {
132    }
133    try {
134      iterator.remove();
135      fail("Expected IllegalStateException");
136    } catch (IllegalStateException expected) {
137    }
138  }
139
140  public void testSize0() {
141    Iterator<String> iterator = Iterators.emptyIterator();
142    assertEquals(0, Iterators.size(iterator));
143  }
144
145  public void testSize1() {
146    Iterator<Integer> iterator = Collections.singleton(0).iterator();
147    assertEquals(1, Iterators.size(iterator));
148  }
149
150  public void testSize_partiallyConsumed() {
151    Iterator<Integer> iterator = asList(1, 2, 3, 4, 5).iterator();
152    iterator.next();
153    iterator.next();
154    assertEquals(3, Iterators.size(iterator));
155  }
156
157  public void test_contains_nonnull_yes() {
158    Iterator<String> set = asList("a", null, "b").iterator();
159    assertTrue(Iterators.contains(set, "b"));
160  }
161
162  public void test_contains_nonnull_no() {
163    Iterator<String> set = asList("a", "b").iterator();
164    assertFalse(Iterators.contains(set, "c"));
165  }
166
167  public void test_contains_null_yes() {
168    Iterator<String> set = asList("a", null, "b").iterator();
169    assertTrue(Iterators.contains(set, null));
170  }
171
172  public void test_contains_null_no() {
173    Iterator<String> set = asList("a", "b").iterator();
174    assertFalse(Iterators.contains(set, null));
175  }
176
177  public void testGetOnlyElement_noDefault_valid() {
178    Iterator<String> iterator = Collections.singletonList("foo").iterator();
179    assertEquals("foo", Iterators.getOnlyElement(iterator));
180  }
181
182  public void testGetOnlyElement_noDefault_empty() {
183    Iterator<String> iterator = Iterators.emptyIterator();
184    try {
185      Iterators.getOnlyElement(iterator);
186      fail();
187    } catch (NoSuchElementException expected) {
188    }
189  }
190
191  public void testGetOnlyElement_noDefault_moreThanOneLessThanFiveElements() {
192    Iterator<String> iterator = asList("one", "two").iterator();
193    try {
194      Iterators.getOnlyElement(iterator);
195      fail();
196    } catch (IllegalArgumentException expected) {
197      assertEquals("expected one element but was: <one, two>",
198                   expected.getMessage());
199    }
200  }
201
202  public void testGetOnlyElement_noDefault_fiveElements() {
203    Iterator<String> iterator =
204        asList("one", "two", "three", "four", "five").iterator();
205    try {
206      Iterators.getOnlyElement(iterator);
207      fail();
208    } catch (IllegalArgumentException expected) {
209      assertEquals("expected one element but was: "
210                   + "<one, two, three, four, five>",
211                   expected.getMessage());
212    }
213  }
214
215  public void testGetOnlyElement_noDefault_moreThanFiveElements() {
216    Iterator<String> iterator =
217        asList("one", "two", "three", "four", "five", "six").iterator();
218    try {
219      Iterators.getOnlyElement(iterator);
220      fail();
221    } catch (IllegalArgumentException expected) {
222      assertEquals("expected one element but was: "
223                   + "<one, two, three, four, five, ...>",
224                   expected.getMessage());
225    }
226  }
227
228  public void testGetOnlyElement_withDefault_singleton() {
229    Iterator<String> iterator = Collections.singletonList("foo").iterator();
230    assertEquals("foo", Iterators.getOnlyElement(iterator, "bar"));
231  }
232
233  public void testGetOnlyElement_withDefault_empty() {
234    Iterator<String> iterator = Iterators.emptyIterator();
235    assertEquals("bar", Iterators.getOnlyElement(iterator, "bar"));
236  }
237
238  public void testGetOnlyElement_withDefault_empty_null() {
239    Iterator<String> iterator = Iterators.emptyIterator();
240    assertNull(Iterators.getOnlyElement(iterator, null));
241  }
242
243  public void testGetOnlyElement_withDefault_two() {
244    Iterator<String> iterator = asList("foo", "bar").iterator();
245    try {
246      Iterators.getOnlyElement(iterator, "x");
247      fail();
248    } catch (IllegalArgumentException expected) {
249      assertEquals("expected one element but was: <foo, bar>",
250                   expected.getMessage());
251    }
252  }
253
254  @GwtIncompatible("Iterators.toArray(Iterator, Class)")
255  public void testToArrayEmpty() {
256    Iterator<String> iterator = Collections.<String>emptyList().iterator();
257    String[] array = Iterators.toArray(iterator, String.class);
258    assertTrue(Arrays.equals(new String[0], array));
259  }
260
261  @GwtIncompatible("Iterators.toArray(Iterator, Class)")
262  public void testToArraySingleton() {
263    Iterator<String> iterator = Collections.singletonList("a").iterator();
264    String[] array = Iterators.toArray(iterator, String.class);
265    assertTrue(Arrays.equals(new String[] { "a" }, array));
266  }
267
268  @GwtIncompatible("Iterators.toArray(Iterator, Class)")
269  public void testToArray() {
270    String[] sourceArray = new String[] {"a", "b", "c"};
271    Iterator<String> iterator = asList(sourceArray).iterator();
272    String[] newArray = Iterators.toArray(iterator, String.class);
273    assertTrue(Arrays.equals(sourceArray, newArray));
274  }
275
276  public void testFilterSimple() {
277    Iterator<String> unfiltered = Lists.newArrayList("foo", "bar").iterator();
278    Iterator<String> filtered = Iterators.filter(unfiltered,
279                                                 Predicates.equalTo("foo"));
280    List<String> expected = Collections.singletonList("foo");
281    List<String> actual = Lists.newArrayList(filtered);
282    assertEquals(expected, actual);
283  }
284
285  public void testFilterNoMatch() {
286    Iterator<String> unfiltered = Lists.newArrayList("foo", "bar").iterator();
287    Iterator<String> filtered = Iterators.filter(unfiltered,
288                                                 Predicates.alwaysFalse());
289    List<String> expected = Collections.emptyList();
290    List<String> actual = Lists.newArrayList(filtered);
291    assertEquals(expected, actual);
292  }
293
294  public void testFilterMatchAll() {
295    Iterator<String> unfiltered = Lists.newArrayList("foo", "bar").iterator();
296    Iterator<String> filtered = Iterators.filter(unfiltered,
297                                                 Predicates.alwaysTrue());
298    List<String> expected = Lists.newArrayList("foo", "bar");
299    List<String> actual = Lists.newArrayList(filtered);
300    assertEquals(expected, actual);
301  }
302
303  public void testFilterNothing() {
304    Iterator<String> unfiltered = Collections.<String>emptyList().iterator();
305    Iterator<String> filtered = Iterators.filter(unfiltered,
306        new Predicate<String>() {
307          @Override
308          public boolean apply(String s) {
309            throw new AssertionFailedError("Should never be evaluated");
310          }
311        });
312
313    List<String> expected = Collections.emptyList();
314    List<String> actual = Lists.newArrayList(filtered);
315    assertEquals(expected, actual);
316  }
317
318  @GwtIncompatible("unreasonably slow")
319  public void testFilterUsingIteratorTester() {
320    final List<Integer> list = asList(1, 2, 3, 4, 5);
321    final Predicate<Integer> isEven = new Predicate<Integer>() {
322      @Override
323      public boolean apply(Integer integer) {
324        return integer % 2 == 0;
325      }
326    };
327    new IteratorTester<Integer>(5, UNMODIFIABLE, asList(2, 4),
328        IteratorTester.KnownOrder.KNOWN_ORDER) {
329      @Override protected Iterator<Integer> newTargetIterator() {
330        return Iterators.filter(list.iterator(), isEven);
331      }
332    }.test();
333  }
334
335  public void testAny() {
336    List<String> list = Lists.newArrayList();
337    Predicate<String> predicate = Predicates.equalTo("pants");
338
339    assertFalse(Iterators.any(list.iterator(), predicate));
340    list.add("cool");
341    assertFalse(Iterators.any(list.iterator(), predicate));
342    list.add("pants");
343    assertTrue(Iterators.any(list.iterator(), predicate));
344  }
345
346  public void testAll() {
347    List<String> list = Lists.newArrayList();
348    Predicate<String> predicate = Predicates.equalTo("cool");
349
350    assertTrue(Iterators.all(list.iterator(), predicate));
351    list.add("cool");
352    assertTrue(Iterators.all(list.iterator(), predicate));
353    list.add("pants");
354    assertFalse(Iterators.all(list.iterator(), predicate));
355  }
356
357  public void testFind_firstElement() {
358    Iterable<String> list = Lists.newArrayList("cool", "pants");
359    Iterator<String> iterator = list.iterator();
360    assertEquals("cool", Iterators.find(iterator, Predicates.equalTo("cool")));
361    assertEquals("pants", iterator.next());
362  }
363
364  public void testFind_lastElement() {
365    Iterable<String> list = Lists.newArrayList("cool", "pants");
366    Iterator<String> iterator = list.iterator();
367    assertEquals("pants", Iterators.find(iterator,
368        Predicates.equalTo("pants")));
369    assertFalse(iterator.hasNext());
370  }
371
372  public void testFind_notPresent() {
373    Iterable<String> list = Lists.newArrayList("cool", "pants");
374    Iterator<String> iterator = list.iterator();
375    try {
376      Iterators.find(iterator, Predicates.alwaysFalse());
377      fail();
378    } catch (NoSuchElementException e) {
379    }
380    assertFalse(iterator.hasNext());
381  }
382
383  public void testFind_matchAlways() {
384    Iterable<String> list = Lists.newArrayList("cool", "pants");
385    Iterator<String> iterator = list.iterator();
386    assertEquals("cool", Iterators.find(iterator, Predicates.alwaysTrue()));
387  }
388
389  public void testFind_withDefault_first() {
390    Iterable<String> list = Lists.newArrayList("cool", "pants");
391    Iterator<String> iterator = list.iterator();
392    assertEquals("cool",
393        Iterators.find(iterator, Predicates.equalTo("cool"), "woot"));
394    assertEquals("pants", iterator.next());
395  }
396
397  public void testFind_withDefault_last() {
398    Iterable<String> list = Lists.newArrayList("cool", "pants");
399    Iterator<String> iterator = list.iterator();
400    assertEquals("pants",
401        Iterators.find(iterator, Predicates.equalTo("pants"), "woot"));
402    assertFalse(iterator.hasNext());
403  }
404
405  public void testFind_withDefault_notPresent() {
406    Iterable<String> list = Lists.newArrayList("cool", "pants");
407    Iterator<String> iterator = list.iterator();
408    assertEquals("woot",
409        Iterators.find(iterator, Predicates.alwaysFalse(), "woot"));
410    assertFalse(iterator.hasNext());
411  }
412
413  public void testFind_withDefault_notPresent_nullReturn() {
414    Iterable<String> list = Lists.newArrayList("cool", "pants");
415    Iterator<String> iterator = list.iterator();
416    assertNull(
417        Iterators.find(iterator, Predicates.alwaysFalse(), null));
418    assertFalse(iterator.hasNext());
419  }
420
421  public void testFind_withDefault_matchAlways() {
422    Iterable<String> list = Lists.newArrayList("cool", "pants");
423    Iterator<String> iterator = list.iterator();
424    assertEquals("cool",
425        Iterators.find(iterator, Predicates.alwaysTrue(), "woot"));
426    assertEquals("pants", iterator.next());
427  }
428
429  public void testTryFind_firstElement() {
430    Iterable<String> list = Lists.newArrayList("cool", "pants");
431    Iterator<String> iterator = list.iterator();
432    assertEquals("cool",
433        Iterators.tryFind(iterator, Predicates.equalTo("cool")).get());
434  }
435
436  public void testTryFind_lastElement() {
437    Iterable<String> list = Lists.newArrayList("cool", "pants");
438    Iterator<String> iterator = list.iterator();
439    assertEquals("pants",
440        Iterators.tryFind(iterator, Predicates.equalTo("pants")).get());
441  }
442
443  public void testTryFind_alwaysTrue() {
444    Iterable<String> list = Lists.newArrayList("cool", "pants");
445    Iterator<String> iterator = list.iterator();
446    assertEquals("cool",
447        Iterators.tryFind(iterator, Predicates.alwaysTrue()).get());
448  }
449
450  public void testTryFind_alwaysFalse_orDefault() {
451    Iterable<String> list = Lists.newArrayList("cool", "pants");
452    Iterator<String> iterator = list.iterator();
453    assertEquals("woot",
454        Iterators.tryFind(iterator, Predicates.alwaysFalse()).or("woot"));
455    assertFalse(iterator.hasNext());
456  }
457
458  public void testTryFind_alwaysFalse_isPresent() {
459    Iterable<String> list = Lists.newArrayList("cool", "pants");
460    Iterator<String> iterator = list.iterator();
461    assertFalse(
462        Iterators.tryFind(iterator, Predicates.alwaysFalse()).isPresent());
463    assertFalse(iterator.hasNext());
464  }
465
466  public void testTransform() {
467    Iterator<String> input = asList("1", "2", "3").iterator();
468    Iterator<Integer> result = Iterators.transform(input,
469        new Function<String, Integer>() {
470          @Override
471          public Integer apply(String from) {
472            return Integer.valueOf(from);
473          }
474        });
475
476    List<Integer> actual = Lists.newArrayList(result);
477    List<Integer> expected = asList(1, 2, 3);
478    assertEquals(expected, actual);
479  }
480
481  public void testTransformRemove() {
482    List<String> list = Lists.newArrayList("1", "2", "3");
483    Iterator<String> input = list.iterator();
484    Iterator<Integer> iterator = Iterators.transform(input,
485        new Function<String, Integer>() {
486          @Override
487          public Integer apply(String from) {
488            return Integer.valueOf(from);
489          }
490        });
491
492    assertEquals(Integer.valueOf(1), iterator.next());
493    assertEquals(Integer.valueOf(2), iterator.next());
494    iterator.remove();
495    assertEquals(asList("1", "3"), list);
496  }
497
498  public void testPoorlyBehavedTransform() {
499    Iterator<String> input = asList("1", null, "3").iterator();
500    Iterator<Integer> result = Iterators.transform(input,
501        new Function<String, Integer>() {
502          @Override
503          public Integer apply(String from) {
504            return Integer.valueOf(from);
505          }
506        });
507
508    result.next();
509    try {
510      result.next();
511      fail("Expected NFE");
512    } catch (NumberFormatException nfe) {
513      // Expected to fail.
514    }
515  }
516
517  public void testNullFriendlyTransform() {
518    Iterator<Integer> input = asList(1, 2, null, 3).iterator();
519    Iterator<String> result = Iterators.transform(input,
520        new Function<Integer, String>() {
521          @Override
522          public String apply(Integer from) {
523            return String.valueOf(from);
524          }
525        });
526
527    List<String> actual = Lists.newArrayList(result);
528    List<String> expected = asList("1", "2", "null", "3");
529    assertEquals(expected, actual);
530  }
531
532  public void testCycleOfEmpty() {
533    // "<String>" for javac 1.5.
534    Iterator<String> cycle = Iterators.<String>cycle();
535    assertFalse(cycle.hasNext());
536  }
537
538  public void testCycleOfOne() {
539    Iterator<String> cycle = Iterators.cycle("a");
540    for (int i = 0; i < 3; i++) {
541      assertTrue(cycle.hasNext());
542      assertEquals("a", cycle.next());
543    }
544  }
545
546  public void testCycleOfOneWithRemove() {
547    Iterable<String> iterable = Lists.newArrayList("a");
548    Iterator<String> cycle = Iterators.cycle(iterable);
549    assertTrue(cycle.hasNext());
550    assertEquals("a", cycle.next());
551    cycle.remove();
552    assertEquals(Collections.emptyList(), iterable);
553    assertFalse(cycle.hasNext());
554  }
555
556  public void testCycleOfTwo() {
557    Iterator<String> cycle = Iterators.cycle("a", "b");
558    for (int i = 0; i < 3; i++) {
559      assertTrue(cycle.hasNext());
560      assertEquals("a", cycle.next());
561      assertTrue(cycle.hasNext());
562      assertEquals("b", cycle.next());
563    }
564  }
565
566  public void testCycleOfTwoWithRemove() {
567    Iterable<String> iterable = Lists.newArrayList("a", "b");
568    Iterator<String> cycle = Iterators.cycle(iterable);
569    assertTrue(cycle.hasNext());
570    assertEquals("a", cycle.next());
571    assertTrue(cycle.hasNext());
572    assertEquals("b", cycle.next());
573    assertTrue(cycle.hasNext());
574    assertEquals("a", cycle.next());
575    cycle.remove();
576    assertEquals(Collections.singletonList("b"), iterable);
577    assertTrue(cycle.hasNext());
578    assertEquals("b", cycle.next());
579    assertTrue(cycle.hasNext());
580    assertEquals("b", cycle.next());
581    cycle.remove();
582    assertEquals(Collections.emptyList(), iterable);
583    assertFalse(cycle.hasNext());
584  }
585
586  public void testCycleRemoveWithoutNext() {
587    Iterator<String> cycle = Iterators.cycle("a", "b");
588    assertTrue(cycle.hasNext());
589    try {
590      cycle.remove();
591      fail("no exception thrown");
592    } catch (IllegalStateException expected) {
593    }
594  }
595
596  public void testCycleRemoveSameElementTwice() {
597    Iterator<String> cycle = Iterators.cycle("a", "b");
598    cycle.next();
599    cycle.remove();
600    try {
601      cycle.remove();
602      fail("no exception thrown");
603    } catch (IllegalStateException expected) {
604    }
605  }
606
607  public void testCycleWhenRemoveIsNotSupported() {
608    Iterable<String> iterable = asList("a", "b");
609    Iterator<String> cycle = Iterators.cycle(iterable);
610    cycle.next();
611    try {
612      cycle.remove();
613      fail("no exception thrown");
614    } catch (UnsupportedOperationException expected) {
615    }
616  }
617
618  public void testCycleRemoveAfterHasNext() {
619    Iterable<String> iterable = Lists.newArrayList("a");
620    Iterator<String> cycle = Iterators.cycle(iterable);
621    assertTrue(cycle.hasNext());
622    assertEquals("a", cycle.next());
623    assertTrue(cycle.hasNext());
624    cycle.remove();
625    assertEquals(Collections.emptyList(), iterable);
626    assertFalse(cycle.hasNext());
627  }
628
629  public void testCycleNoSuchElementException() {
630    Iterable<String> iterable = Lists.newArrayList("a");
631    Iterator<String> cycle = Iterators.cycle(iterable);
632    assertTrue(cycle.hasNext());
633    assertEquals("a", cycle.next());
634    cycle.remove();
635    assertFalse(cycle.hasNext());
636    try {
637      cycle.next();
638      fail();
639    } catch (NoSuchElementException expected) {}
640  }
641
642  @GwtIncompatible("unreasonably slow")
643  public void testCycleUsingIteratorTester() {
644    new IteratorTester<Integer>(5, UNMODIFIABLE, asList(1, 2, 1, 2, 1,
645        2, 1, 2, 1, 2, 1, 2), IteratorTester.KnownOrder.KNOWN_ORDER) {
646      @Override protected Iterator<Integer> newTargetIterator() {
647        return Iterators.cycle(asList(1, 2));
648      }
649    }.test();
650  }
651
652  @GwtIncompatible("slow (~5s)")
653  public void testConcatNoIteratorsYieldsEmpty() {
654    new EmptyIteratorTester() {
655      @SuppressWarnings("unchecked")
656      @Override protected Iterator<Integer> newTargetIterator() {
657        return Iterators.concat();
658      }
659    }.test();
660  }
661
662  @GwtIncompatible("slow (~5s)")
663  public void testConcatOneEmptyIteratorYieldsEmpty() {
664    new EmptyIteratorTester() {
665      @SuppressWarnings("unchecked")
666      @Override protected Iterator<Integer> newTargetIterator() {
667        return Iterators.concat(iterateOver());
668      }
669    }.test();
670  }
671
672  @GwtIncompatible("slow (~5s)")
673  public void testConcatMultipleEmptyIteratorsYieldsEmpty() {
674    new EmptyIteratorTester() {
675      @Override protected Iterator<Integer> newTargetIterator() {
676        return Iterators.concat(iterateOver(), iterateOver());
677      }
678    }.test();
679  }
680
681  @GwtIncompatible("slow (~3s)")
682  public void testConcatSingletonYieldsSingleton() {
683    new SingletonIteratorTester() {
684      @SuppressWarnings("unchecked")
685      @Override protected Iterator<Integer> newTargetIterator() {
686        return Iterators.concat(iterateOver(1));
687      }
688    }.test();
689  }
690
691  @GwtIncompatible("slow (~5s)")
692  public void testConcatEmptyAndSingletonAndEmptyYieldsSingleton() {
693    new SingletonIteratorTester() {
694      @Override protected Iterator<Integer> newTargetIterator() {
695        return Iterators.concat(iterateOver(), iterateOver(1), iterateOver());
696      }
697    }.test();
698  }
699
700  @GwtIncompatible("fairly slow (~40s)")
701  public void testConcatSingletonAndSingletonYieldsDoubleton() {
702    new DoubletonIteratorTester() {
703      @Override protected Iterator<Integer> newTargetIterator() {
704        return Iterators.concat(iterateOver(1), iterateOver(2));
705      }
706    }.test();
707  }
708
709  @GwtIncompatible("fairly slow (~40s)")
710  public void testConcatSingletonAndSingletonWithEmptiesYieldsDoubleton() {
711    new DoubletonIteratorTester() {
712      @Override protected Iterator<Integer> newTargetIterator() {
713        return Iterators.concat(
714            iterateOver(1), iterateOver(), iterateOver(), iterateOver(2));
715      }
716    }.test();
717  }
718
719  @GwtIncompatible("fairly slow (~50s)")
720  public void testConcatUnmodifiable() {
721    new IteratorTester<Integer>(5, UNMODIFIABLE, asList(1, 2),
722        IteratorTester.KnownOrder.KNOWN_ORDER) {
723      @Override protected Iterator<Integer> newTargetIterator() {
724        return Iterators.concat(asList(1).iterator(),
725            Arrays.<Integer>asList().iterator(), asList(2).iterator());
726      }
727    }.test();
728  }
729
730  /**
731   * Illustrates the somewhat bizarre behavior when a null is passed in.
732   */
733  public void testConcatContainingNull() {
734    @SuppressWarnings("unchecked")
735    Iterator<Iterator<Integer>> input
736        = asList(iterateOver(1, 2), null, iterateOver(3)).iterator();
737    Iterator<Integer> result = Iterators.concat(input);
738    assertEquals(1, (int) result.next());
739    assertEquals(2, (int) result.next());
740    try {
741      result.hasNext();
742      fail("no exception thrown");
743    } catch (NullPointerException e) {
744    }
745    try {
746      result.next();
747      fail("no exception thrown");
748    } catch (NullPointerException e) {
749    }
750    // There is no way to get "through" to the 3.  Buh-bye
751  }
752
753  @SuppressWarnings("unchecked")
754  public void testConcatVarArgsContainingNull() {
755    try {
756      Iterators.concat(iterateOver(1, 2), null, iterateOver(3), iterateOver(4),
757          iterateOver(5));
758      fail("no exception thrown");
759    } catch (NullPointerException e) {
760    }
761  }
762
763  public void testAddAllWithEmptyIterator() {
764    List<String> alreadyThere = Lists.newArrayList("already", "there");
765
766    boolean changed = Iterators.addAll(alreadyThere,
767                                       Iterators.<String>emptyIterator());
768    assertThat(alreadyThere).has().exactly("already", "there").inOrder();
769    assertFalse(changed);
770  }
771
772  public void testAddAllToList() {
773    List<String> alreadyThere = Lists.newArrayList("already", "there");
774    List<String> freshlyAdded = Lists.newArrayList("freshly", "added");
775
776    boolean changed = Iterators.addAll(alreadyThere, freshlyAdded.iterator());
777
778    assertThat(alreadyThere).has().exactly("already", "there", "freshly", "added");
779    assertTrue(changed);
780  }
781
782  public void testAddAllToSet() {
783    Set<String> alreadyThere
784        = Sets.newLinkedHashSet(asList("already", "there"));
785    List<String> oneMore = Lists.newArrayList("there");
786
787    boolean changed = Iterators.addAll(alreadyThere, oneMore.iterator());
788    assertThat(alreadyThere).has().exactly("already", "there").inOrder();
789    assertFalse(changed);
790  }
791
792  @GwtIncompatible("NullPointerTester")
793  public void testNullPointerExceptions() {
794    NullPointerTester tester = new NullPointerTester();
795    tester.testAllPublicStaticMethods(Iterators.class);
796  }
797
798  @GwtIncompatible("Only used by @GwtIncompatible code")
799  private static abstract class EmptyIteratorTester
800      extends IteratorTester<Integer> {
801    protected EmptyIteratorTester() {
802      super(3, MODIFIABLE, Collections.<Integer>emptySet(),
803          IteratorTester.KnownOrder.KNOWN_ORDER);
804    }
805  }
806
807  @GwtIncompatible("Only used by @GwtIncompatible code")
808  private static abstract class SingletonIteratorTester
809      extends IteratorTester<Integer> {
810    protected SingletonIteratorTester() {
811      super(3, MODIFIABLE, singleton(1), IteratorTester.KnownOrder.KNOWN_ORDER);
812    }
813  }
814
815  @GwtIncompatible("Only used by @GwtIncompatible code")
816  private static abstract class DoubletonIteratorTester
817      extends IteratorTester<Integer> {
818    protected DoubletonIteratorTester() {
819      super(5, MODIFIABLE, newArrayList(1, 2),
820          IteratorTester.KnownOrder.KNOWN_ORDER);
821    }
822  }
823
824  private static Iterator<Integer> iterateOver(final Integer... values) {
825    return newArrayList(values).iterator();
826  }
827
828  public void testElementsEqual() {
829    Iterable<?> a;
830    Iterable<?> b;
831
832    // Base case.
833    a = Lists.newArrayList();
834    b = Collections.emptySet();
835    assertTrue(Iterators.elementsEqual(a.iterator(), b.iterator()));
836
837    // A few elements.
838    a = asList(4, 8, 15, 16, 23, 42);
839    b = asList(4, 8, 15, 16, 23, 42);
840    assertTrue(Iterators.elementsEqual(a.iterator(), b.iterator()));
841
842    // The same, but with nulls.
843    a = asList(4, 8, null, 16, 23, 42);
844    b = asList(4, 8, null, 16, 23, 42);
845    assertTrue(Iterators.elementsEqual(a.iterator(), b.iterator()));
846
847    // Different Iterable types (still equal elements, though).
848    a = ImmutableList.of(4, 8, 15, 16, 23, 42);
849    b = asList(4, 8, 15, 16, 23, 42);
850    assertTrue(Iterators.elementsEqual(a.iterator(), b.iterator()));
851
852    // An element differs.
853    a = asList(4, 8, 15, 12, 23, 42);
854    b = asList(4, 8, 15, 16, 23, 42);
855    assertFalse(Iterators.elementsEqual(a.iterator(), b.iterator()));
856
857    // null versus non-null.
858    a = asList(4, 8, 15, null, 23, 42);
859    b = asList(4, 8, 15, 16, 23, 42);
860    assertFalse(Iterators.elementsEqual(a.iterator(), b.iterator()));
861    assertFalse(Iterators.elementsEqual(b.iterator(), a.iterator()));
862
863    // Different lengths.
864    a = asList(4, 8, 15, 16, 23);
865    b = asList(4, 8, 15, 16, 23, 42);
866    assertFalse(Iterators.elementsEqual(a.iterator(), b.iterator()));
867    assertFalse(Iterators.elementsEqual(b.iterator(), a.iterator()));
868
869    // Different lengths, one is empty.
870    a = Collections.emptySet();
871    b = asList(4, 8, 15, 16, 23, 42);
872    assertFalse(Iterators.elementsEqual(a.iterator(), b.iterator()));
873    assertFalse(Iterators.elementsEqual(b.iterator(), a.iterator()));
874  }
875
876  public void testPartition_badSize() {
877    Iterator<Integer> source = Iterators.singletonIterator(1);
878    try {
879      Iterators.partition(source, 0);
880      fail();
881    } catch (IllegalArgumentException expected) {
882    }
883  }
884
885  public void testPartition_empty() {
886    Iterator<Integer> source = Iterators.emptyIterator();
887    Iterator<List<Integer>> partitions = Iterators.partition(source, 1);
888    assertFalse(partitions.hasNext());
889  }
890
891  public void testPartition_singleton1() {
892    Iterator<Integer> source = Iterators.singletonIterator(1);
893    Iterator<List<Integer>> partitions = Iterators.partition(source, 1);
894    assertTrue(partitions.hasNext());
895    assertTrue(partitions.hasNext());
896    assertEquals(ImmutableList.of(1), partitions.next());
897    assertFalse(partitions.hasNext());
898  }
899
900  public void testPartition_singleton2() {
901    Iterator<Integer> source = Iterators.singletonIterator(1);
902    Iterator<List<Integer>> partitions = Iterators.partition(source, 2);
903    assertTrue(partitions.hasNext());
904    assertTrue(partitions.hasNext());
905    assertEquals(ImmutableList.of(1), partitions.next());
906    assertFalse(partitions.hasNext());
907  }
908
909  @GwtIncompatible("fairly slow (~50s)")
910  public void testPartition_general() {
911    new IteratorTester<List<Integer>>(5,
912        IteratorFeature.UNMODIFIABLE,
913        ImmutableList.of(
914            asList(1, 2, 3),
915            asList(4, 5, 6),
916            asList(7)),
917        IteratorTester.KnownOrder.KNOWN_ORDER) {
918      @Override protected Iterator<List<Integer>> newTargetIterator() {
919        Iterator<Integer> source = Iterators.forArray(1, 2, 3, 4, 5, 6, 7);
920        return Iterators.partition(source, 3);
921      }
922    }.test();
923  }
924
925  public void testPartition_view() {
926    List<Integer> list = asList(1, 2);
927    Iterator<List<Integer>> partitions
928        = Iterators.partition(list.iterator(), 1);
929
930    // Changes before the partition is retrieved are reflected
931    list.set(0, 3);
932    List<Integer> first = partitions.next();
933
934    // Changes after are not
935    list.set(0, 4);
936
937    assertEquals(ImmutableList.of(3), first);
938  }
939
940  @GwtIncompatible("?")
941  // TODO: Figure out why this is failing in GWT.
942  public void testPartitionRandomAccess() {
943    Iterator<Integer> source = asList(1, 2, 3).iterator();
944    Iterator<List<Integer>> partitions = Iterators.partition(source, 2);
945    assertTrue(partitions.next() instanceof RandomAccess);
946    assertTrue(partitions.next() instanceof RandomAccess);
947  }
948
949  public void testPaddedPartition_badSize() {
950    Iterator<Integer> source = Iterators.singletonIterator(1);
951    try {
952      Iterators.paddedPartition(source, 0);
953      fail();
954    } catch (IllegalArgumentException expected) {
955    }
956  }
957
958  public void testPaddedPartition_empty() {
959    Iterator<Integer> source = Iterators.emptyIterator();
960    Iterator<List<Integer>> partitions = Iterators.paddedPartition(source, 1);
961    assertFalse(partitions.hasNext());
962  }
963
964  public void testPaddedPartition_singleton1() {
965    Iterator<Integer> source = Iterators.singletonIterator(1);
966    Iterator<List<Integer>> partitions = Iterators.paddedPartition(source, 1);
967    assertTrue(partitions.hasNext());
968    assertTrue(partitions.hasNext());
969    assertEquals(ImmutableList.of(1), partitions.next());
970    assertFalse(partitions.hasNext());
971  }
972
973  public void testPaddedPartition_singleton2() {
974    Iterator<Integer> source = Iterators.singletonIterator(1);
975    Iterator<List<Integer>> partitions = Iterators.paddedPartition(source, 2);
976    assertTrue(partitions.hasNext());
977    assertTrue(partitions.hasNext());
978    assertEquals(asList(1, null), partitions.next());
979    assertFalse(partitions.hasNext());
980  }
981
982  @GwtIncompatible("fairly slow (~50s)")
983  public void testPaddedPartition_general() {
984    new IteratorTester<List<Integer>>(5,
985        IteratorFeature.UNMODIFIABLE,
986        ImmutableList.of(
987            asList(1, 2, 3),
988            asList(4, 5, 6),
989            asList(7, null, null)),
990        IteratorTester.KnownOrder.KNOWN_ORDER) {
991      @Override protected Iterator<List<Integer>> newTargetIterator() {
992        Iterator<Integer> source = Iterators.forArray(1, 2, 3, 4, 5, 6, 7);
993        return Iterators.paddedPartition(source, 3);
994      }
995    }.test();
996  }
997
998  public void testPaddedPartition_view() {
999    List<Integer> list = asList(1, 2);
1000    Iterator<List<Integer>> partitions
1001        = Iterators.paddedPartition(list.iterator(), 1);
1002
1003    // Changes before the PaddedPartition is retrieved are reflected
1004    list.set(0, 3);
1005    List<Integer> first = partitions.next();
1006
1007    // Changes after are not
1008    list.set(0, 4);
1009
1010    assertEquals(ImmutableList.of(3), first);
1011  }
1012
1013  public void testPaddedPartitionRandomAccess() {
1014    Iterator<Integer> source = asList(1, 2, 3).iterator();
1015    Iterator<List<Integer>> partitions = Iterators.paddedPartition(source, 2);
1016    assertTrue(partitions.next() instanceof RandomAccess);
1017    assertTrue(partitions.next() instanceof RandomAccess);
1018  }
1019
1020  public void testForArrayEmpty() {
1021    String[] array = new String[0];
1022    Iterator<String> iterator = Iterators.forArray(array);
1023    assertFalse(iterator.hasNext());
1024    try {
1025      iterator.next();
1026      fail();
1027    } catch (NoSuchElementException expected) {}
1028  }
1029
1030  public void testForArrayTypical() {
1031    String[] array = {"foo", "bar"};
1032    Iterator<String> iterator = Iterators.forArray(array);
1033    assertTrue(iterator.hasNext());
1034    assertEquals("foo", iterator.next());
1035    assertTrue(iterator.hasNext());
1036    try {
1037      iterator.remove();
1038      fail();
1039    } catch (UnsupportedOperationException expected) {}
1040    assertEquals("bar", iterator.next());
1041    assertFalse(iterator.hasNext());
1042    try {
1043      iterator.next();
1044      fail();
1045    } catch (NoSuchElementException expected) {}
1046  }
1047
1048  public void testForArrayOffset() {
1049    String[] array = {"foo", "bar", "cat", "dog"};
1050    Iterator<String> iterator = Iterators.forArray(array, 1, 2, 0);
1051    assertTrue(iterator.hasNext());
1052    assertEquals("bar", iterator.next());
1053    assertTrue(iterator.hasNext());
1054    assertEquals("cat", iterator.next());
1055    assertFalse(iterator.hasNext());
1056    try {
1057      Iterators.forArray(array, 2, 3, 0);
1058      fail();
1059    } catch (IndexOutOfBoundsException expected) {}
1060  }
1061
1062  public void testForArrayLength0() {
1063    String[] array = {"foo", "bar"};
1064    assertFalse(Iterators.forArray(array, 0, 0, 0).hasNext());
1065    assertFalse(Iterators.forArray(array, 1, 0, 0).hasNext());
1066    assertFalse(Iterators.forArray(array, 2, 0, 0).hasNext());
1067    try {
1068      Iterators.forArray(array, -1, 0, 0);
1069      fail();
1070    } catch (IndexOutOfBoundsException expected) {}
1071    try {
1072      Iterators.forArray(array, 3, 0, 0);
1073      fail();
1074    } catch (IndexOutOfBoundsException expected) {}
1075  }
1076
1077  @GwtIncompatible("unreasonably slow")
1078  public void testForArrayUsingTester() {
1079    new IteratorTester<Integer>(6, UNMODIFIABLE, asList(1, 2, 3),
1080        IteratorTester.KnownOrder.KNOWN_ORDER) {
1081      @Override protected Iterator<Integer> newTargetIterator() {
1082        return Iterators.forArray(1, 2, 3);
1083      }
1084    }.test();
1085  }
1086
1087  @GwtIncompatible("unreasonably slow")
1088  public void testForArrayWithOffsetUsingTester() {
1089    new IteratorTester<Integer>(6, UNMODIFIABLE, asList(1, 2, 3),
1090        IteratorTester.KnownOrder.KNOWN_ORDER) {
1091      @Override protected Iterator<Integer> newTargetIterator() {
1092        return Iterators.forArray(new Integer[] { 0, 1, 2, 3, 4 }, 1, 3, 0);
1093      }
1094    }.test();
1095  }
1096
1097  public void testForEnumerationEmpty() {
1098    Enumeration<Integer> enumer = enumerate();
1099    Iterator<Integer> iter = Iterators.forEnumeration(enumer);
1100
1101    assertFalse(iter.hasNext());
1102    try {
1103      iter.next();
1104      fail();
1105    } catch (NoSuchElementException expected) {
1106    }
1107  }
1108
1109  public void testForEnumerationSingleton() {
1110    Enumeration<Integer> enumer = enumerate(1);
1111    Iterator<Integer> iter = Iterators.forEnumeration(enumer);
1112
1113    assertTrue(iter.hasNext());
1114    assertTrue(iter.hasNext());
1115    assertEquals(1, (int) iter.next());
1116    try {
1117      iter.remove();
1118      fail();
1119    } catch (UnsupportedOperationException expected) {
1120    }
1121    assertFalse(iter.hasNext());
1122    try {
1123      iter.next();
1124      fail();
1125    } catch (NoSuchElementException expected) {
1126    }
1127  }
1128
1129  public void testForEnumerationTypical() {
1130    Enumeration<Integer> enumer = enumerate(1, 2, 3);
1131    Iterator<Integer> iter = Iterators.forEnumeration(enumer);
1132
1133    assertTrue(iter.hasNext());
1134    assertEquals(1, (int) iter.next());
1135    assertTrue(iter.hasNext());
1136    assertEquals(2, (int) iter.next());
1137    assertTrue(iter.hasNext());
1138    assertEquals(3, (int) iter.next());
1139    assertFalse(iter.hasNext());
1140  }
1141
1142  public void testAsEnumerationEmpty() {
1143    Iterator<Integer> iter = Iterators.emptyIterator();
1144    Enumeration<Integer> enumer = Iterators.asEnumeration(iter);
1145
1146    assertFalse(enumer.hasMoreElements());
1147    try {
1148      enumer.nextElement();
1149      fail();
1150    } catch (NoSuchElementException expected) {
1151    }
1152  }
1153
1154  public void testAsEnumerationSingleton() {
1155    Iterator<Integer> iter = ImmutableList.of(1).iterator();
1156    Enumeration<Integer> enumer = Iterators.asEnumeration(iter);
1157
1158    assertTrue(enumer.hasMoreElements());
1159    assertTrue(enumer.hasMoreElements());
1160    assertEquals(1, (int) enumer.nextElement());
1161    assertFalse(enumer.hasMoreElements());
1162    try {
1163      enumer.nextElement();
1164      fail();
1165    } catch (NoSuchElementException expected) {
1166    }
1167  }
1168
1169  public void testAsEnumerationTypical() {
1170    Iterator<Integer> iter = ImmutableList.of(1, 2, 3).iterator();
1171    Enumeration<Integer> enumer = Iterators.asEnumeration(iter);
1172
1173    assertTrue(enumer.hasMoreElements());
1174    assertEquals(1, (int) enumer.nextElement());
1175    assertTrue(enumer.hasMoreElements());
1176    assertEquals(2, (int) enumer.nextElement());
1177    assertTrue(enumer.hasMoreElements());
1178    assertEquals(3, (int) enumer.nextElement());
1179    assertFalse(enumer.hasMoreElements());
1180  }
1181
1182  private static Enumeration<Integer> enumerate(Integer... ints) {
1183    Vector<Integer> vector = new Vector<Integer>();
1184    vector.addAll(asList(ints));
1185    return vector.elements();
1186  }
1187
1188  public void testToString() {
1189    Iterator<String> iterator = Lists.newArrayList("yam", "bam", "jam", "ham").iterator();
1190    assertEquals("[yam, bam, jam, ham]", Iterators.toString(iterator));
1191  }
1192
1193  public void testToStringWithNull() {
1194    Iterator<String> iterator = Lists.newArrayList("hello", null, "world").iterator();
1195    assertEquals("[hello, null, world]", Iterators.toString(iterator));
1196  }
1197
1198  public void testToStringEmptyIterator() {
1199    Iterator<String> iterator = Collections.<String>emptyList().iterator();
1200    assertEquals("[]", Iterators.toString(iterator));
1201  }
1202
1203  public void testLimit() {
1204    List<String> list = newArrayList();
1205    try {
1206      Iterators.limit(list.iterator(), -1);
1207      fail("expected exception");
1208    } catch (IllegalArgumentException expected) {
1209      // expected
1210    }
1211
1212    assertFalse(Iterators.limit(list.iterator(), 0).hasNext());
1213    assertFalse(Iterators.limit(list.iterator(), 1).hasNext());
1214
1215    list.add("cool");
1216    assertFalse(Iterators.limit(list.iterator(), 0).hasNext());
1217    assertEquals(list, newArrayList(Iterators.limit(list.iterator(), 1)));
1218    assertEquals(list, newArrayList(Iterators.limit(list.iterator(), 2)));
1219
1220    list.add("pants");
1221    assertFalse(Iterators.limit(list.iterator(), 0).hasNext());
1222    assertEquals(ImmutableList.of("cool"),
1223        newArrayList(Iterators.limit(list.iterator(), 1)));
1224    assertEquals(list, newArrayList(Iterators.limit(list.iterator(), 2)));
1225    assertEquals(list, newArrayList(Iterators.limit(list.iterator(), 3)));
1226  }
1227
1228  public void testLimitRemove() {
1229    List<String> list = newArrayList();
1230    list.add("cool");
1231    list.add("pants");
1232    Iterator<String> iterator = Iterators.limit(list.iterator(), 1);
1233    iterator.next();
1234    iterator.remove();
1235    assertFalse(iterator.hasNext());
1236    assertEquals(1, list.size());
1237    assertEquals("pants", list.get(0));
1238  }
1239
1240  @GwtIncompatible("fairly slow (~30s)")
1241  public void testLimitUsingIteratorTester() {
1242    final List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);
1243    new IteratorTester<Integer>(5, MODIFIABLE, newArrayList(1, 2, 3),
1244        IteratorTester.KnownOrder.KNOWN_ORDER) {
1245      @Override protected Iterator<Integer> newTargetIterator() {
1246        return Iterators.limit(Lists.newArrayList(list).iterator(), 3);
1247      }
1248    }.test();
1249  }
1250
1251  public void testGetNext_withDefault_singleton() {
1252    Iterator<String> iterator = Collections.singletonList("foo").iterator();
1253    assertEquals("foo", Iterators.getNext(iterator, "bar"));
1254  }
1255
1256  public void testGetNext_withDefault_empty() {
1257    Iterator<String> iterator = Iterators.emptyIterator();
1258    assertEquals("bar", Iterators.getNext(iterator, "bar"));
1259  }
1260
1261  public void testGetNext_withDefault_empty_null() {
1262    Iterator<String> iterator = Iterators.emptyIterator();
1263    assertNull(Iterators.getNext(iterator, null));
1264  }
1265
1266  public void testGetNext_withDefault_two() {
1267    Iterator<String> iterator = asList("foo", "bar").iterator();
1268    assertEquals("foo", Iterators.getNext(iterator, "x"));
1269  }
1270
1271  public void testGetLast_basic() {
1272    List<String> list = newArrayList();
1273    list.add("a");
1274    list.add("b");
1275    assertEquals("b", getLast(list.iterator()));
1276  }
1277
1278  public void testGetLast_exception() {
1279    List<String> list = newArrayList();
1280    try {
1281      getLast(list.iterator());
1282      fail();
1283    } catch (NoSuchElementException expected) {
1284    }
1285  }
1286
1287  public void testGetLast_withDefault_singleton() {
1288    Iterator<String> iterator = Collections.singletonList("foo").iterator();
1289    assertEquals("foo", Iterators.getLast(iterator, "bar"));
1290  }
1291
1292  public void testGetLast_withDefault_empty() {
1293    Iterator<String> iterator = Iterators.emptyIterator();
1294    assertEquals("bar", Iterators.getLast(iterator, "bar"));
1295  }
1296
1297  public void testGetLast_withDefault_empty_null() {
1298    Iterator<String> iterator = Iterators.emptyIterator();
1299    assertNull(Iterators.getLast(iterator, null));
1300  }
1301
1302  public void testGetLast_withDefault_two() {
1303    Iterator<String> iterator = asList("foo", "bar").iterator();
1304    assertEquals("bar", Iterators.getLast(iterator, "x"));
1305  }
1306
1307  public void testGet_basic() {
1308    List<String> list = newArrayList();
1309    list.add("a");
1310    list.add("b");
1311    Iterator<String> iterator = list.iterator();
1312    assertEquals("b", get(iterator, 1));
1313    assertFalse(iterator.hasNext());
1314  }
1315
1316  public void testGet_atSize() {
1317    List<String> list = newArrayList();
1318    list.add("a");
1319    list.add("b");
1320    Iterator<String> iterator = list.iterator();
1321    try {
1322      get(iterator, 2);
1323      fail();
1324    } catch (IndexOutOfBoundsException expected) {}
1325    assertFalse(iterator.hasNext());
1326  }
1327
1328  public void testGet_pastEnd() {
1329    List<String> list = newArrayList();
1330    list.add("a");
1331    list.add("b");
1332    Iterator<String> iterator = list.iterator();
1333    try {
1334      get(iterator, 5);
1335      fail();
1336    } catch (IndexOutOfBoundsException expected) {}
1337    assertFalse(iterator.hasNext());
1338  }
1339
1340  public void testGet_empty() {
1341    List<String> list = newArrayList();
1342    Iterator<String> iterator = list.iterator();
1343    try {
1344      get(iterator, 0);
1345      fail();
1346    } catch (IndexOutOfBoundsException expected) {}
1347    assertFalse(iterator.hasNext());
1348  }
1349
1350  public void testGet_negativeIndex() {
1351    List<String> list = newArrayList("a", "b", "c");
1352    Iterator<String> iterator = list.iterator();
1353    try {
1354      get(iterator, -1);
1355      fail();
1356    } catch (IndexOutOfBoundsException expected) {}
1357  }
1358
1359  public void testGet_withDefault_basic() {
1360    List<String> list = newArrayList();
1361    list.add("a");
1362    list.add("b");
1363    Iterator<String> iterator = list.iterator();
1364    assertEquals("a", get(iterator, 0, "c"));
1365    assertTrue(iterator.hasNext());
1366  }
1367
1368  public void testGet_withDefault_atSize() {
1369    List<String> list = newArrayList();
1370    list.add("a");
1371    list.add("b");
1372    Iterator<String> iterator = list.iterator();
1373    assertEquals("c", get(iterator, 2, "c"));
1374    assertFalse(iterator.hasNext());
1375  }
1376
1377  public void testGet_withDefault_pastEnd() {
1378    List<String> list = newArrayList();
1379    list.add("a");
1380    list.add("b");
1381    Iterator<String> iterator = list.iterator();
1382    assertEquals("c", get(iterator, 3, "c"));
1383    assertFalse(iterator.hasNext());
1384  }
1385
1386  public void testGet_withDefault_negativeIndex() {
1387    List<String> list = newArrayList();
1388    list.add("a");
1389    list.add("b");
1390    Iterator<String> iterator = list.iterator();
1391    try {
1392      get(iterator, -1, "c");
1393      fail();
1394    } catch (IndexOutOfBoundsException expected) {
1395      // pass
1396    }
1397    assertTrue(iterator.hasNext());
1398  }
1399
1400  public void testAdvance_basic() {
1401    List<String> list = newArrayList();
1402    list.add("a");
1403    list.add("b");
1404    Iterator<String> iterator = list.iterator();
1405    advance(iterator, 1);
1406    assertEquals("b", iterator.next());
1407  }
1408
1409  public void testAdvance_pastEnd() {
1410    List<String> list = newArrayList();
1411    list.add("a");
1412    list.add("b");
1413    Iterator<String> iterator = list.iterator();
1414    advance(iterator, 5);
1415    assertFalse(iterator.hasNext());
1416  }
1417
1418  public void testAdvance_illegalArgument() {
1419    List<String> list = newArrayList("a", "b", "c");
1420    Iterator<String> iterator = list.iterator();
1421    try {
1422      advance(iterator, -1);
1423      fail();
1424    } catch (IllegalArgumentException expected) {}
1425  }
1426
1427  public void testFrequency() {
1428    List<String> list = newArrayList("a", null, "b", null, "a", null);
1429    assertEquals(2, Iterators.frequency(list.iterator(), "a"));
1430    assertEquals(1, Iterators.frequency(list.iterator(), "b"));
1431    assertEquals(0, Iterators.frequency(list.iterator(), "c"));
1432    assertEquals(0, Iterators.frequency(list.iterator(), 4.2));
1433    assertEquals(3, Iterators.frequency(list.iterator(), null));
1434  }
1435
1436  @GwtIncompatible("slow (~4s)")
1437  public void testSingletonIterator() {
1438    new IteratorTester<Integer>(
1439        3, UNMODIFIABLE, singleton(1), IteratorTester.KnownOrder.KNOWN_ORDER) {
1440      @Override protected Iterator<Integer> newTargetIterator() {
1441        return Iterators.singletonIterator(1);
1442      }
1443    }.test();
1444  }
1445
1446  public void testRemoveAll() {
1447    List<String> list = newArrayList("a", "b", "c", "d", "e");
1448    assertTrue(Iterators.removeAll(
1449        list.iterator(), newArrayList("b", "d", "f")));
1450    assertEquals(newArrayList("a", "c", "e"), list);
1451    assertFalse(Iterators.removeAll(
1452        list.iterator(), newArrayList("x", "y", "z")));
1453    assertEquals(newArrayList("a", "c", "e"), list);
1454  }
1455
1456  public void testRemoveIf() {
1457    List<String> list = newArrayList("a", "b", "c", "d", "e");
1458    assertTrue(Iterators.removeIf(
1459        list.iterator(),
1460        new Predicate<String>() {
1461          @Override
1462          public boolean apply(String s) {
1463            return s.equals("b") || s.equals("d") || s.equals("f");
1464          }
1465        }));
1466    assertEquals(newArrayList("a", "c", "e"), list);
1467    assertFalse(Iterators.removeIf(
1468        list.iterator(),
1469        new Predicate<String>() {
1470          @Override
1471          public boolean apply(String s) {
1472            return s.equals("x") || s.equals("y") || s.equals("z");
1473          }
1474        }));
1475    assertEquals(newArrayList("a", "c", "e"), list);
1476  }
1477
1478  public void testRetainAll() {
1479    List<String> list = newArrayList("a", "b", "c", "d", "e");
1480    assertTrue(Iterators.retainAll(
1481        list.iterator(), newArrayList("b", "d", "f")));
1482    assertEquals(newArrayList("b", "d"), list);
1483    assertFalse(Iterators.retainAll(
1484        list.iterator(), newArrayList("b", "e", "d")));
1485    assertEquals(newArrayList("b", "d"), list);
1486  }
1487
1488  @GwtIncompatible("ListTestSuiteBuilder")
1489  private static Test testsForRemoveAllAndRetainAll() {
1490    return ListTestSuiteBuilder.using(new TestStringListGenerator() {
1491          @Override public List<String> create(final String[] elements) {
1492            final List<String> delegate = newArrayList(elements);
1493            return new ForwardingList<String>() {
1494              @Override protected List<String> delegate() {
1495                return delegate;
1496              }
1497
1498              @Override public boolean removeAll(Collection<?> c) {
1499                return Iterators.removeAll(iterator(), c);
1500              }
1501
1502              @Override public boolean retainAll(Collection<?> c) {
1503                return Iterators.retainAll(iterator(), c);
1504              }
1505            };
1506          }
1507        })
1508        .named("ArrayList with Iterators.removeAll and retainAll")
1509        .withFeatures(
1510            ListFeature.GENERAL_PURPOSE,
1511            CollectionFeature.ALLOWS_NULL_VALUES,
1512            CollectionSize.ANY)
1513        .createTestSuite();
1514  }
1515
1516  public void testConsumingIterator() {
1517    // Test data
1518    List<String> list = Lists.newArrayList("a", "b");
1519
1520    // Test & Verify
1521    Iterator<String> consumingIterator =
1522        Iterators.consumingIterator(list.iterator());
1523
1524    assertEquals("Iterators.consumingIterator(...)", consumingIterator.toString());
1525
1526    assertThat(list).has().exactly("a", "b").inOrder();
1527
1528    assertTrue(consumingIterator.hasNext());
1529    assertThat(list).has().exactly("a", "b").inOrder();
1530    assertEquals("a", consumingIterator.next());
1531    assertThat(list).has().item("b");
1532
1533    assertTrue(consumingIterator.hasNext());
1534    assertEquals("b", consumingIterator.next());
1535    assertThat(list).isEmpty();
1536
1537    assertFalse(consumingIterator.hasNext());
1538  }
1539
1540  @GwtIncompatible("?")
1541  // TODO: Figure out why this is failing in GWT.
1542  public void testConsumingIterator_duelingIterators() {
1543    // Test data
1544    List<String> list = Lists.newArrayList("a", "b");
1545
1546    // Test & Verify
1547    Iterator<String> i1 = Iterators.consumingIterator(list.iterator());
1548    Iterator<String> i2 = Iterators.consumingIterator(list.iterator());
1549
1550    i1.next();
1551    try {
1552      i2.next();
1553      fail("Concurrent modification should throw an exception.");
1554    } catch (ConcurrentModificationException cme) {
1555      // Pass
1556    }
1557  }
1558
1559  public void testIndexOf_consumedData() {
1560    Iterator<String> iterator =
1561        Lists.newArrayList("manny", "mo", "jack").iterator();
1562    assertEquals(1, Iterators.indexOf(iterator, Predicates.equalTo("mo")));
1563    assertEquals("jack", iterator.next());
1564    assertFalse(iterator.hasNext());
1565  }
1566
1567  public void testIndexOf_consumedDataWithDuplicates() {
1568    Iterator<String> iterator =
1569        Lists.newArrayList("manny", "mo", "mo", "jack").iterator();
1570    assertEquals(1, Iterators.indexOf(iterator, Predicates.equalTo("mo")));
1571    assertEquals("mo", iterator.next());
1572    assertEquals("jack", iterator.next());
1573    assertFalse(iterator.hasNext());
1574  }
1575
1576  public void testIndexOf_consumedDataNoMatch() {
1577    Iterator<String> iterator =
1578        Lists.newArrayList("manny", "mo", "mo", "jack").iterator();
1579    assertEquals(-1, Iterators.indexOf(iterator, Predicates.equalTo("bob")));
1580    assertFalse(iterator.hasNext());
1581  }
1582
1583  @SuppressWarnings("deprecation")
1584  public void testUnmodifiableIteratorShortCircuit() {
1585    Iterator<String> mod = Lists.newArrayList("a", "b", "c").iterator();
1586    UnmodifiableIterator<String> unmod = Iterators.unmodifiableIterator(mod);
1587    assertNotSame(mod, unmod);
1588    assertSame(unmod, Iterators.unmodifiableIterator(unmod));
1589    assertSame(unmod, Iterators.unmodifiableIterator((Iterator<String>) unmod));
1590  }
1591
1592  @SuppressWarnings("deprecation")
1593  public void testPeekingIteratorShortCircuit() {
1594    Iterator<String> nonpeek = Lists.newArrayList("a", "b", "c").iterator();
1595    PeekingIterator<String> peek = Iterators.peekingIterator(nonpeek);
1596    assertNotSame(peek, nonpeek);
1597    assertSame(peek, Iterators.peekingIterator(peek));
1598    assertSame(peek, Iterators.peekingIterator((Iterator<String>) peek));
1599  }
1600}
1601