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.Iterables.skip;
20import static com.google.common.collect.Lists.newArrayList;
21import static com.google.common.collect.Sets.newLinkedHashSet;
22import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
23import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
24import static java.util.Arrays.asList;
25import static java.util.Collections.emptyList;
26import static org.junit.contrib.truth.Truth.ASSERT;
27
28import com.google.common.annotations.GwtCompatible;
29import com.google.common.annotations.GwtIncompatible;
30import com.google.common.base.Function;
31import com.google.common.base.Optional;
32import com.google.common.base.Predicate;
33import com.google.common.base.Predicates;
34import com.google.common.collect.testing.IteratorTester;
35import com.google.common.testing.NullPointerTester;
36
37import junit.framework.TestCase;
38
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.Collection;
42import java.util.Collections;
43import java.util.ConcurrentModificationException;
44import java.util.Iterator;
45import java.util.List;
46import java.util.NoSuchElementException;
47import java.util.Queue;
48import java.util.RandomAccess;
49import java.util.Set;
50import java.util.SortedSet;
51import java.util.TreeSet;
52
53/**
54 * Unit test for {@code Iterables}.
55 *
56 * @author Kevin Bourrillion
57 * @author Jared Levy
58 */
59@GwtCompatible(emulated = true)
60public class IterablesTest extends TestCase {
61
62  public void testSize0() {
63    Iterable<String> iterable = Collections.emptySet();
64    assertEquals(0, Iterables.size(iterable));
65  }
66
67  public void testSize1Collection() {
68    Iterable<String> iterable = Collections.singleton("a");
69    assertEquals(1, Iterables.size(iterable));
70  }
71
72  public void testSize2NonCollection() {
73    Iterable<Integer> iterable = new Iterable<Integer>() {
74      @Override
75      public Iterator<Integer> iterator() {
76        return asList(0, 1).iterator();
77      }
78    };
79    assertEquals(2, Iterables.size(iterable));
80  }
81
82  @SuppressWarnings("serial")
83  public void testSize_collection_doesntIterate() {
84    List<Integer> nums = asList(1, 2, 3, 4, 5);
85    List<Integer> collection = new ArrayList<Integer>(nums) {
86      @Override public Iterator<Integer> iterator() {
87        fail("Don't iterate me!");
88        return null;
89      }
90    };
91    assertEquals(5, Iterables.size(collection));
92  }
93
94  private static Iterable<String> iterable(String... elements) {
95    final List<String> list = asList(elements);
96    return new Iterable<String>() {
97      @Override
98      public Iterator<String> iterator() {
99        return list.iterator();
100      }
101    };
102  }
103
104  public void test_contains_null_set_yes() {
105    Iterable<String> set = Sets.newHashSet("a", null, "b");
106    assertTrue(Iterables.contains(set, null));
107  }
108
109  public void test_contains_null_set_no() {
110    Iterable<String> set = Sets.newHashSet("a", "b");
111    assertFalse(Iterables.contains(set, null));
112  }
113
114  public void test_contains_null_iterable_yes() {
115    Iterable<String> set = iterable("a", null, "b");
116    assertTrue(Iterables.contains(set, null));
117  }
118
119  public void test_contains_null_iterable_no() {
120    Iterable<String> set = iterable("a", "b");
121    assertFalse(Iterables.contains(set, null));
122  }
123
124  public void test_contains_nonnull_set_yes() {
125    Iterable<String> set = Sets.newHashSet("a", null, "b");
126    assertTrue(Iterables.contains(set, "b"));
127  }
128
129  public void test_contains_nonnull_set_no() {
130    Iterable<String> set = Sets.newHashSet("a", "b");
131    assertFalse(Iterables.contains(set, "c"));
132  }
133
134  public void test_contains_nonnull_iterable_yes() {
135    Iterable<String> set = iterable("a", null, "b");
136    assertTrue(Iterables.contains(set, "b"));
137  }
138
139  public void test_contains_nonnull_iterable_no() {
140    Iterable<String> set = iterable("a", "b");
141    assertFalse(Iterables.contains(set, "c"));
142  }
143
144  public void testGetOnlyElement_noDefault_valid() {
145    Iterable<String> iterable = Collections.singletonList("foo");
146    assertEquals("foo", Iterables.getOnlyElement(iterable));
147  }
148
149  public void testGetOnlyElement_noDefault_empty() {
150    Iterable<String> iterable = Collections.emptyList();
151    try {
152      Iterables.getOnlyElement(iterable);
153      fail();
154    } catch (NoSuchElementException expected) {
155    }
156  }
157
158  public void testGetOnlyElement_noDefault_multiple() {
159    Iterable<String> iterable = asList("foo", "bar");
160    try {
161      Iterables.getOnlyElement(iterable);
162      fail();
163    } catch (IllegalArgumentException expected) {
164    }
165  }
166
167  public void testGetOnlyElement_withDefault_singleton() {
168    Iterable<String> iterable = Collections.singletonList("foo");
169    assertEquals("foo", Iterables.getOnlyElement(iterable, "bar"));
170  }
171
172  public void testGetOnlyElement_withDefault_empty() {
173    Iterable<String> iterable = Collections.emptyList();
174    assertEquals("bar", Iterables.getOnlyElement(iterable, "bar"));
175  }
176
177  public void testGetOnlyElement_withDefault_empty_null() {
178    Iterable<String> iterable = Collections.emptyList();
179    assertNull(Iterables.getOnlyElement(iterable, null));
180  }
181
182  public void testGetOnlyElement_withDefault_multiple() {
183    Iterable<String> iterable = asList("foo", "bar");
184    try {
185      Iterables.getOnlyElement(iterable, "x");
186      fail();
187    } catch (IllegalArgumentException expected) {
188    }
189  }
190
191  @GwtIncompatible("Iterables.toArray(Iterable, Class)")
192  public void testToArrayEmpty() {
193    Iterable<String> iterable = Collections.emptyList();
194    String[] array = Iterables.toArray(iterable, String.class);
195    assertTrue(Arrays.equals(new String[0], array));
196  }
197
198  @GwtIncompatible("Iterables.toArray(Iterable, Class)")
199  public void testToArraySingleton() {
200    Iterable<String> iterable = Collections.singletonList("a");
201    String[] array = Iterables.toArray(iterable, String.class);
202    assertTrue(Arrays.equals(new String[] {"a"}, array));
203  }
204
205  @GwtIncompatible("Iterables.toArray(Iterable, Class)")
206  public void testToArray() {
207    String[] sourceArray = new String[] {"a", "b", "c"};
208    Iterable<String> iterable = asList(sourceArray);
209    String[] newArray = Iterables.toArray(iterable, String.class);
210    assertTrue(Arrays.equals(sourceArray, newArray));
211  }
212
213  public void testFilter() {
214    Iterable<String> unfiltered = newArrayList("foo", "bar");
215    Iterable<String> filtered = Iterables.filter(unfiltered,
216                                                 Predicates.equalTo("foo"));
217
218    List<String> expected = Collections.singletonList("foo");
219    List<String> actual = newArrayList(filtered);
220    assertEquals(expected, actual);
221    assertCanIterateAgain(filtered);
222    assertEquals("[foo]", filtered.toString());
223  }
224
225  public void testAny() {
226    List<String> list = newArrayList();
227    Predicate<String> predicate = Predicates.equalTo("pants");
228
229    assertFalse(Iterables.any(list, predicate));
230    list.add("cool");
231    assertFalse(Iterables.any(list, predicate));
232    list.add("pants");
233    assertTrue(Iterables.any(list, predicate));
234  }
235
236  public void testAll() {
237    List<String> list = newArrayList();
238    Predicate<String> predicate = Predicates.equalTo("cool");
239
240    assertTrue(Iterables.all(list, predicate));
241    list.add("cool");
242    assertTrue(Iterables.all(list, predicate));
243    list.add("pants");
244    assertFalse(Iterables.all(list, predicate));
245  }
246
247  public void testFind() {
248    Iterable<String> list = newArrayList("cool", "pants");
249    assertEquals("cool", Iterables.find(list, Predicates.equalTo("cool")));
250    assertEquals("pants", Iterables.find(list, Predicates.equalTo("pants")));
251    try {
252      Iterables.find(list, Predicates.alwaysFalse());
253      fail();
254    } catch (NoSuchElementException e) {
255    }
256    assertEquals("cool", Iterables.find(list, Predicates.alwaysTrue()));
257    assertCanIterateAgain(list);
258  }
259
260  public void testFind_withDefault() {
261    Iterable<String> list = Lists.newArrayList("cool", "pants");
262    assertEquals("cool",
263        Iterables.find(list, Predicates.equalTo("cool"), "woot"));
264    assertEquals("pants",
265        Iterables.find(list, Predicates.equalTo("pants"), "woot"));
266    assertEquals("woot", Iterables.find(list,
267        Predicates.alwaysFalse(), "woot"));
268    assertNull(Iterables.find(list, Predicates.alwaysFalse(), null));
269    assertEquals("cool",
270        Iterables.find(list, Predicates.alwaysTrue(), "woot"));
271    assertCanIterateAgain(list);
272  }
273
274  public void testTryFind() {
275    Iterable<String> list = newArrayList("cool", "pants");
276    assertEquals(Optional.of("cool"),
277        Iterables.tryFind(list, Predicates.equalTo("cool")));
278    assertEquals(Optional.of("pants"),
279        Iterables.tryFind(list, Predicates.equalTo("pants")));
280    assertEquals(Optional.of("cool"),
281        Iterables.tryFind(list, Predicates.alwaysTrue()));
282    assertEquals(Optional.absent(),
283        Iterables.tryFind(list, Predicates.alwaysFalse()));
284    assertCanIterateAgain(list);
285  }
286
287  private static class TypeA {}
288  private interface TypeB {}
289  private static class HasBoth extends TypeA implements TypeB {}
290
291  @GwtIncompatible("Iterables.filter(Iterable, Class)")
292  public void testFilterByType() throws Exception {
293    HasBoth hasBoth = new HasBoth();
294    Iterable<TypeA> alist = Lists
295        .newArrayList(new TypeA(), new TypeA(), hasBoth, new TypeA());
296    Iterable<TypeB> blist = Iterables.filter(alist, TypeB.class);
297    ASSERT.that(blist).hasContentsInOrder(hasBoth);
298  }
299
300  public void testTransform() {
301    List<String> input = asList("1", "2", "3");
302    Iterable<Integer> result = Iterables.transform(input,
303        new Function<String, Integer>() {
304          @Override
305          public Integer apply(String from) {
306            return Integer.valueOf(from);
307          }
308        });
309
310    List<Integer> actual = newArrayList(result);
311    List<Integer> expected = asList(1, 2, 3);
312    assertEquals(expected, actual);
313    assertCanIterateAgain(result);
314    assertEquals("[1, 2, 3]", result.toString());
315  }
316
317  public void testPoorlyBehavedTransform() {
318    List<String> input = asList("1", null, "3");
319    Iterable<Integer> result = Iterables.transform(input,
320        new Function<String, Integer>() {
321          @Override
322          public Integer apply(String from) {
323            return Integer.valueOf(from);
324          }
325        });
326
327    Iterator<Integer> resultIterator = result.iterator();
328    resultIterator.next();
329
330    try {
331      resultIterator.next();
332      fail("Expected NFE");
333    } catch (NumberFormatException nfe) {
334      // Expected to fail.
335    }
336  }
337
338  public void testNullFriendlyTransform() {
339    List<Integer> input = asList(1, 2, null, 3);
340    Iterable<String> result = Iterables.transform(input,
341        new Function<Integer, String>() {
342          @Override
343          public String apply(Integer from) {
344            return String.valueOf(from);
345          }
346        });
347
348    List<String> actual = newArrayList(result);
349    List<String> expected = asList("1", "2", "null", "3");
350    assertEquals(expected, actual);
351  }
352
353  // Far less exhaustive than the tests in IteratorsTest
354  public void testCycle() {
355    Iterable<String> cycle = Iterables.cycle("a", "b");
356
357    int howManyChecked = 0;
358    for (String string : cycle) {
359      String expected = (howManyChecked % 2 == 0) ? "a" : "b";
360      assertEquals(expected, string);
361      if (howManyChecked++ == 5) {
362        break;
363      }
364    }
365
366    // We left the last iterator pointing to "b". But a new iterator should
367    // always point to "a".
368    for (String string : cycle) {
369      assertEquals("a", string);
370      break;
371    }
372
373    assertEquals("[a, b] (cycled)", cycle.toString());
374  }
375
376  // Again, the exhaustive tests are in IteratorsTest
377  public void testConcatIterable() {
378    List<Integer> list1 = newArrayList(1);
379    List<Integer> list2 = newArrayList(4);
380
381    @SuppressWarnings("unchecked")
382    List<List<Integer>> input = newArrayList(list1, list2);
383
384    Iterable<Integer> result = Iterables.concat(input);
385    assertEquals(asList(1, 4), newArrayList(result));
386
387    // Now change the inputs and see result dynamically change as well
388
389    list1.add(2);
390    List<Integer> list3 = newArrayList(3);
391    input.add(1, list3);
392
393    assertEquals(asList(1, 2, 3, 4), newArrayList(result));
394    assertEquals("[1, 2, 3, 4]", result.toString());
395  }
396
397  public void testConcatVarargs() {
398    List<Integer> list1 = newArrayList(1);
399    List<Integer> list2 = newArrayList(4);
400    List<Integer> list3 = newArrayList(7, 8);
401    List<Integer> list4 = newArrayList(9);
402    List<Integer> list5 = newArrayList(10);
403    @SuppressWarnings("unchecked")
404    Iterable<Integer> result =
405        Iterables.concat(list1, list2, list3, list4, list5);
406    assertEquals(asList(1, 4, 7, 8, 9, 10), newArrayList(result));
407    assertEquals("[1, 4, 7, 8, 9, 10]", result.toString());
408  }
409
410  public void testConcatNullPointerException() {
411    List<Integer> list1 = newArrayList(1);
412    List<Integer> list2 = newArrayList(4);
413
414    try {
415      Iterables.concat(list1, null, list2);
416      fail();
417    } catch (NullPointerException expected) {}
418  }
419
420  public void testConcatPeformingFiniteCycle() {
421    Iterable<Integer> iterable = asList(1, 2, 3);
422    int n = 4;
423    Iterable<Integer> repeated
424        = Iterables.concat(Collections.nCopies(n, iterable));
425    ASSERT.that(repeated).hasContentsInOrder(
426        1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3);
427  }
428
429  public void testPartition_badSize() {
430    Iterable<Integer> source = Collections.singleton(1);
431    try {
432      Iterables.partition(source, 0);
433      fail();
434    } catch (IllegalArgumentException expected) {
435    }
436  }
437
438  public void testPartition_empty() {
439    Iterable<Integer> source = Collections.emptySet();
440    Iterable<List<Integer>> partitions = Iterables.partition(source, 1);
441    assertTrue(Iterables.isEmpty(partitions));
442  }
443
444  public void testPartition_singleton1() {
445    Iterable<Integer> source = Collections.singleton(1);
446    Iterable<List<Integer>> partitions = Iterables.partition(source, 1);
447    assertEquals(1, Iterables.size(partitions));
448    assertEquals(Collections.singletonList(1), partitions.iterator().next());
449  }
450
451  public void testPartition_view() {
452    List<Integer> list = asList(1, 2);
453    Iterable<List<Integer>> partitions = Iterables.partition(list, 2);
454
455    // Changes before the partition is retrieved are reflected
456    list.set(0, 3);
457
458    Iterator<List<Integer>> iterator = partitions.iterator();
459
460    // Changes before the partition is retrieved are reflected
461    list.set(1, 4);
462
463    List<Integer> first = iterator.next();
464
465    // Changes after are not
466    list.set(0, 5);
467
468    assertEquals(ImmutableList.of(3, 4), first);
469  }
470
471  @GwtIncompatible("?")
472  // TODO: Figure out why this is failing in GWT.
473  public void testPartitionRandomAccessInput() {
474    Iterable<Integer> source = asList(1, 2, 3);
475    Iterable<List<Integer>> partitions = Iterables.partition(source, 2);
476    Iterator<List<Integer>> iterator = partitions.iterator();
477    assertTrue(iterator.next() instanceof RandomAccess);
478    assertTrue(iterator.next() instanceof RandomAccess);
479  }
480
481  @GwtIncompatible("?")
482  // TODO: Figure out why this is failing in GWT.
483  public void testPartitionNonRandomAccessInput() {
484    Iterable<Integer> source = Lists.newLinkedList(asList(1, 2, 3));
485    Iterable<List<Integer>> partitions = Iterables.partition(source, 2);
486    Iterator<List<Integer>> iterator = partitions.iterator();
487    // Even though the input list doesn't implement RandomAccess, the output
488    // lists do.
489    assertTrue(iterator.next() instanceof RandomAccess);
490    assertTrue(iterator.next() instanceof RandomAccess);
491  }
492
493  public void testPaddedPartition_basic() {
494    List<Integer> list = asList(1, 2, 3, 4, 5);
495    Iterable<List<Integer>> partitions = Iterables.paddedPartition(list, 2);
496    assertEquals(3, Iterables.size(partitions));
497    assertEquals(asList(5, null), Iterables.getLast(partitions));
498  }
499
500  public void testPaddedPartitionRandomAccessInput() {
501    Iterable<Integer> source = asList(1, 2, 3);
502    Iterable<List<Integer>> partitions = Iterables.paddedPartition(source, 2);
503    Iterator<List<Integer>> iterator = partitions.iterator();
504    assertTrue(iterator.next() instanceof RandomAccess);
505    assertTrue(iterator.next() instanceof RandomAccess);
506  }
507
508  public void testPaddedPartitionNonRandomAccessInput() {
509    Iterable<Integer> source = Lists.newLinkedList(asList(1, 2, 3));
510    Iterable<List<Integer>> partitions = Iterables.paddedPartition(source, 2);
511    Iterator<List<Integer>> iterator = partitions.iterator();
512    // Even though the input list doesn't implement RandomAccess, the output
513    // lists do.
514    assertTrue(iterator.next() instanceof RandomAccess);
515    assertTrue(iterator.next() instanceof RandomAccess);
516  }
517
518  // More tests in IteratorsTest
519  public void testAddAllToList() {
520    List<String> alreadyThere = newArrayList("already", "there");
521    List<String> freshlyAdded = newArrayList("freshly", "added");
522
523    boolean changed = Iterables.addAll(alreadyThere, freshlyAdded);
524    ASSERT.that(alreadyThere).hasContentsInOrder(
525        "already", "there", "freshly", "added");
526    assertTrue(changed);
527  }
528
529  private static void assertCanIterateAgain(Iterable<?> iterable) {
530    for (@SuppressWarnings("unused") Object obj : iterable) {
531    }
532  }
533
534  @GwtIncompatible("NullPointerTester")
535  public void testNullPointerExceptions() throws Exception {
536    NullPointerTester tester = new NullPointerTester();
537    tester.testAllPublicStaticMethods(Iterables.class);
538  }
539
540  // More exhaustive tests are in IteratorsTest.
541  public void testElementsEqual() throws Exception {
542    Iterable<?> a;
543    Iterable<?> b;
544
545    // A few elements.
546    a = asList(4, 8, 15, 16, 23, 42);
547    b = asList(4, 8, 15, 16, 23, 42);
548    assertTrue(Iterables.elementsEqual(a, b));
549
550    // An element differs.
551    a = asList(4, 8, 15, 12, 23, 42);
552    b = asList(4, 8, 15, 16, 23, 42);
553    assertFalse(Iterables.elementsEqual(a, b));
554
555    // null versus non-null.
556    a = asList(4, 8, 15, null, 23, 42);
557    b = asList(4, 8, 15, 16, 23, 42);
558    assertFalse(Iterables.elementsEqual(a, b));
559    assertFalse(Iterables.elementsEqual(b, a));
560
561    // Different lengths.
562    a = asList(4, 8, 15, 16, 23);
563    b = asList(4, 8, 15, 16, 23, 42);
564    assertFalse(Iterables.elementsEqual(a, b));
565    assertFalse(Iterables.elementsEqual(b, a));
566  }
567
568  @GwtIncompatible("slow (~30s)")
569  @SuppressWarnings("deprecation") // test of a deprecated method
570  public void testReversePassesIteratorsTester() {
571    new IteratorTester<Integer>(5, MODIFIABLE, newArrayList(2, 4, 6, 8),
572        IteratorTester.KnownOrder.KNOWN_ORDER) {
573      @Override protected Iterator<Integer> newTargetIterator() {
574        return Iterables.reverse(newArrayList(8, 6, 4, 2)).iterator();
575      }
576    }.test();
577  }
578
579  @SuppressWarnings("deprecation") // test of a deprecated method
580  public void testReverseWorksAsExpected() {
581    String[] testStrs = new String[] {"foo", "bar", "baz"};
582    String[] expected = new String[] {"baz", "bar", "foo"};
583
584    List<String> stuff = ImmutableList.copyOf(testStrs);
585
586    Iterable<String> reversed = Iterables.reverse(stuff);
587    ASSERT.that(reversed).hasContentsInOrder(expected);
588    assertEquals("[baz, bar, foo]", reversed.toString());
589
590    List<String> removable = newArrayList("foo", "bar", "bad", "baz");
591
592    reversed = Iterables.reverse(removable);
593    ASSERT.that(reversed).hasContentsInOrder("baz", "bad", "bar", "foo");
594
595    Iterator<String> reverseIter = reversed.iterator();
596    assertEquals("baz", reverseIter.next());
597    assertEquals("bad", reverseIter.next());
598    reverseIter.remove();
599
600    ASSERT.that(reversed).hasContentsInOrder(expected);
601    ASSERT.that(reversed).hasContentsInOrder(expected);
602  }
603
604  public void testToString() {
605    List<String> list = Collections.emptyList();
606    assertEquals("[]", Iterables.toString(list));
607
608    list = newArrayList("yam", "bam", "jam", "ham");
609    assertEquals("[yam, bam, jam, ham]", Iterables.toString(list));
610  }
611
612  public void testLimit() {
613    Iterable<String> iterable = newArrayList("foo", "bar", "baz");
614    Iterable<String> limited = Iterables.limit(iterable, 2);
615
616    List<String> expected = ImmutableList.of("foo", "bar");
617    List<String> actual = newArrayList(limited);
618    assertEquals(expected, actual);
619    assertCanIterateAgain(limited);
620    assertEquals("[foo, bar]", limited.toString());
621  }
622
623  public void testLimit_illegalArgument() {
624    List<String> list = newArrayList("a", "b", "c");
625    try {
626      Iterables.limit(list, -1);
627      fail();
628    } catch (IllegalArgumentException expected) {}
629  }
630
631  public void testIsEmpty() {
632    Iterable<String> emptyList = Collections.emptyList();
633    assertTrue(Iterables.isEmpty(emptyList));
634
635    Iterable<String> singletonList = Collections.singletonList("foo");
636    assertFalse(Iterables.isEmpty(singletonList));
637  }
638
639  public void testSkip_simple() {
640    Collection<String> set = ImmutableSet.of("a", "b", "c", "d", "e");
641    assertEquals(newArrayList("c", "d", "e"), newArrayList(skip(set, 2)));
642    assertEquals("[c, d, e]", skip(set, 2).toString());
643  }
644
645  public void testSkip_simpleList() {
646    Collection<String> list = newArrayList("a", "b", "c", "d", "e");
647    assertEquals(newArrayList("c", "d", "e"), newArrayList(skip(list, 2)));
648    assertEquals("[c, d, e]", skip(list, 2).toString());
649  }
650
651  public void testSkip_pastEnd() {
652    Collection<String> set = ImmutableSet.of("a", "b");
653    assertEquals(emptyList(), newArrayList(skip(set, 20)));
654  }
655
656  public void testSkip_pastEndList() {
657    Collection<String> list = newArrayList("a", "b");
658    assertEquals(emptyList(), newArrayList(skip(list, 20)));
659  }
660
661  public void testSkip_skipNone() {
662    Collection<String> set = ImmutableSet.of("a", "b");
663    assertEquals(newArrayList("a", "b"), newArrayList(skip(set, 0)));
664  }
665
666  public void testSkip_skipNoneList() {
667    Collection<String> list = newArrayList("a", "b");
668    assertEquals(newArrayList("a", "b"), newArrayList(skip(list, 0)));
669  }
670
671  @GwtIncompatible("slow (~35s)")
672  public void testSkip_iterator() {
673    new IteratorTester<Integer>(5, MODIFIABLE, newArrayList(2, 3),
674        IteratorTester.KnownOrder.KNOWN_ORDER) {
675      @Override protected Iterator<Integer> newTargetIterator() {
676        return skip(newLinkedHashSet(asList(1, 2, 3)), 1).iterator();
677      }
678    }.test();
679  }
680
681  @GwtIncompatible("slow (~35s)")
682  public void testSkip_iteratorList() {
683    new IteratorTester<Integer>(5, MODIFIABLE, newArrayList(2, 3),
684        IteratorTester.KnownOrder.KNOWN_ORDER) {
685      @Override protected Iterator<Integer> newTargetIterator() {
686        return skip(newArrayList(1, 2, 3), 1).iterator();
687      }
688    }.test();
689  }
690
691  public void testSkip_nonStructurallyModifiedList() throws Exception {
692    List<String> list = newArrayList("a", "b", "c");
693    Iterable<String> tail = skip(list, 1);
694    Iterator<String> tailIterator = tail.iterator();
695    list.set(2, "C");
696    assertEquals("b", tailIterator.next());
697    assertEquals("C", tailIterator.next());
698    assertFalse(tailIterator.hasNext());
699  }
700
701  public void testSkip_structurallyModifiedSkipSome() throws Exception {
702    Collection<String> set = newLinkedHashSet(asList("a", "b", "c"));
703    Iterable<String> tail = skip(set, 1);
704    set.remove("b");
705    set.addAll(newArrayList("A", "B", "C"));
706    ASSERT.that(tail).hasContentsInOrder("c", "A", "B", "C");
707  }
708
709  public void testSkip_structurallyModifiedSkipSomeList() throws Exception {
710    List<String> list = newArrayList("a", "b", "c");
711    Iterable<String> tail = skip(list, 1);
712    list.subList(1, 3).clear();
713    list.addAll(0, newArrayList("A", "B", "C"));
714    ASSERT.that(tail).hasContentsInOrder("B", "C", "a");
715  }
716
717  public void testSkip_structurallyModifiedSkipAll() throws Exception {
718    Collection<String> set = newLinkedHashSet(asList("a", "b", "c"));
719    Iterable<String> tail = skip(set, 2);
720    set.remove("a");
721    set.remove("b");
722    assertFalse(tail.iterator().hasNext());
723  }
724
725  public void testSkip_structurallyModifiedSkipAllList() throws Exception {
726    List<String> list = newArrayList("a", "b", "c");
727    Iterable<String> tail = skip(list, 2);
728    list.subList(0, 2).clear();
729    assertTrue(Iterables.isEmpty(tail));
730  }
731
732  public void testSkip_illegalArgument() {
733    List<String> list = newArrayList("a", "b", "c");
734    try {
735      skip(list, -1);
736      fail();
737    } catch (IllegalArgumentException expected) {}
738  }
739
740  private void testGetOnAbc(Iterable<String> iterable) {
741    try {
742      Iterables.get(iterable, -1);
743      fail();
744    } catch (IndexOutOfBoundsException expected) {}
745    assertEquals("a", Iterables.get(iterable, 0));
746    assertEquals("b", Iterables.get(iterable, 1));
747    assertEquals("c", Iterables.get(iterable, 2));
748    try {
749      Iterables.get(iterable, 3);
750      fail();
751    } catch (IndexOutOfBoundsException nsee) {}
752    try {
753      Iterables.get(iterable, 4);
754      fail();
755    } catch (IndexOutOfBoundsException nsee) {}
756  }
757
758  private void testGetOnEmpty(Iterable<String> iterable) {
759    try {
760      Iterables.get(iterable, 0);
761      fail();
762    } catch (IndexOutOfBoundsException expected) {}
763  }
764
765  public void testGet_list() {
766    testGetOnAbc(newArrayList("a", "b", "c"));
767  }
768
769  public void testGet_emptyList() {
770    testGetOnEmpty(Collections.<String>emptyList());
771  }
772
773  public void testGet_sortedSet() {
774    testGetOnAbc(ImmutableSortedSet.of("b", "c", "a"));
775  }
776
777  public void testGet_emptySortedSet() {
778    testGetOnEmpty(ImmutableSortedSet.<String>of());
779  }
780
781  public void testGet_iterable() {
782    testGetOnAbc(ImmutableSet.of("a", "b", "c"));
783  }
784
785  public void testGet_emptyIterable() {
786    testGetOnEmpty(Sets.<String>newHashSet());
787  }
788
789  public void testGet_withDefault_negativePosition() {
790    try {
791      Iterables.get(newArrayList("a", "b", "c"), -1, "d");
792      fail();
793    } catch (IndexOutOfBoundsException expected) {
794      // pass
795    }
796  }
797
798  public void testGet_withDefault_simple() {
799    ArrayList<String> list = newArrayList("a", "b", "c");
800    assertEquals("b", Iterables.get(list, 1, "d"));
801  }
802
803  public void testGet_withDefault_iterable() {
804    Set<String> set = ImmutableSet.of("a", "b", "c");
805    assertEquals("b", Iterables.get(set, 1, "d"));
806  }
807
808  public void testGet_withDefault_last() {
809    ArrayList<String> list = newArrayList("a", "b", "c");
810    assertEquals("c", Iterables.get(list, 2, "d"));
811  }
812
813  public void testGet_withDefault_lastPlusOne() {
814    ArrayList<String> list = newArrayList("a", "b", "c");
815    assertEquals("d", Iterables.get(list, 3, "d"));
816  }
817
818  public void testGet_withDefault_doesntIterate() {
819    List<String> list = new DiesOnIteratorArrayList();
820    list.add("a");
821    assertEquals("a", Iterables.get(list, 0, "b"));
822  }
823
824  public void testGetFirst_withDefault_singleton() {
825    Iterable<String> iterable = Collections.singletonList("foo");
826    assertEquals("foo", Iterables.getFirst(iterable, "bar"));
827  }
828
829  public void testGetFirst_withDefault_empty() {
830    Iterable<String> iterable = Collections.emptyList();
831    assertEquals("bar", Iterables.getFirst(iterable, "bar"));
832  }
833
834  public void testGetFirst_withDefault_empty_null() {
835    Iterable<String> iterable = Collections.emptyList();
836    assertNull(Iterables.getFirst(iterable, null));
837  }
838
839  public void testGetFirst_withDefault_multiple() {
840    Iterable<String> iterable = asList("foo", "bar");
841    assertEquals("foo", Iterables.getFirst(iterable, "qux"));
842  }
843
844  public void testGetLast_list() {
845    List<String> list = newArrayList("a", "b", "c");
846    assertEquals("c", Iterables.getLast(list));
847  }
848
849  public void testGetLast_emptyList() {
850    List<String> list = Collections.emptyList();
851    try {
852      Iterables.getLast(list);
853      fail();
854    } catch (NoSuchElementException e) {}
855  }
856
857  public void testGetLast_sortedSet() {
858    SortedSet<String> sortedSet = ImmutableSortedSet.of("b", "c", "a");
859    assertEquals("c", Iterables.getLast(sortedSet));
860  }
861
862  public void testGetLast_withDefault_singleton() {
863    Iterable<String> iterable = Collections.singletonList("foo");
864    assertEquals("foo", Iterables.getLast(iterable, "bar"));
865  }
866
867  public void testGetLast_withDefault_empty() {
868    Iterable<String> iterable = Collections.emptyList();
869    assertEquals("bar", Iterables.getLast(iterable, "bar"));
870  }
871
872  public void testGetLast_withDefault_empty_null() {
873    Iterable<String> iterable = Collections.emptyList();
874    assertNull(Iterables.getLast(iterable, null));
875  }
876
877  public void testGetLast_withDefault_multiple() {
878    Iterable<String> iterable = asList("foo", "bar");
879    assertEquals("bar", Iterables.getLast(iterable, "qux"));
880  }
881
882  /**
883   * {@link ArrayList} extension that forbids the use of
884   * {@link Collection#iterator} for tests that need to prove that it isn't
885   * called.
886   */
887  private static class DiesOnIteratorArrayList extends ArrayList<String> {
888    /**
889     * @throws UnsupportedOperationException all the time
890     */
891    @Override
892    public Iterator<String> iterator() {
893      throw new UnsupportedOperationException();
894    }
895  }
896
897  public void testGetLast_withDefault_not_empty_list() {
898    // TODO: verify that this is the best testing strategy.
899    List<String> diesOnIteratorList = new DiesOnIteratorArrayList();
900    diesOnIteratorList.add("bar");
901
902    assertEquals("bar", Iterables.getLast(diesOnIteratorList, "qux"));
903  }
904
905  /**
906   * {@link TreeSet} extension that forbids the use of
907   * {@link Collection#iterator} for tests that need to prove that it isn't
908   * called.
909   */
910  private static final class DiesOnIteratorTreeSet extends TreeSet<String> {
911    /**
912     * @throws UnsupportedOperationException all the time
913     */
914    @Override
915    public Iterator<String> iterator() {
916      throw new UnsupportedOperationException();
917    }
918  }
919
920  public void testGetLast_withDefault_not_empty_sortedSet() {
921    // TODO: verify that this is the best testing strategy.
922    SortedSet<String> diesOnIteratorSortedSet = new DiesOnIteratorTreeSet();
923    diesOnIteratorSortedSet.add("bar");
924
925    assertEquals("bar", Iterables.getLast(diesOnIteratorSortedSet, "qux"));
926  }
927
928  public void testGetLast_emptySortedSet() {
929    SortedSet<String> sortedSet = ImmutableSortedSet.of();
930    try {
931      Iterables.getLast(sortedSet);
932      fail();
933    } catch (NoSuchElementException e) {}
934  }
935
936  public void testGetLast_iterable() {
937    Set<String> set = ImmutableSet.of("a", "b", "c");
938    assertEquals("c", Iterables.getLast(set));
939  }
940
941  public void testGetLast_emptyIterable() {
942    Set<String> set = Sets.newHashSet();
943    try {
944      Iterables.getLast(set);
945      fail();
946    } catch (NoSuchElementException e) {}
947  }
948
949  public void testUnmodifiableIterable() {
950    List<String> list = newArrayList("a", "b", "c");
951    Iterable<String> iterable = Iterables.unmodifiableIterable(list);
952    Iterator<String> iterator = iterable.iterator();
953    iterator.next();
954    try {
955      iterator.remove();
956      fail();
957    } catch (UnsupportedOperationException expected) {}
958    assertEquals("[a, b, c]", iterable.toString());
959  }
960
961  @SuppressWarnings("deprecation") // test of deprecated method
962  public void testUnmodifiableIterableShortCircuit() {
963    List<String> list = newArrayList("a", "b", "c");
964    Iterable<String> iterable = Iterables.unmodifiableIterable(list);
965    Iterable<String> iterable2 = Iterables.unmodifiableIterable(iterable);
966    assertSame(iterable, iterable2);
967    ImmutableList<String> immutableList = ImmutableList.of("a", "b", "c");
968    assertSame(immutableList, Iterables.unmodifiableIterable(immutableList));
969    assertSame(immutableList,
970        Iterables.unmodifiableIterable((List<String>) immutableList));
971  }
972
973  public void testFrequency_multiset() {
974    Multiset<String> multiset
975        = ImmutableMultiset.of("a", "b", "a", "c", "b", "a");
976    assertEquals(3, Iterables.frequency(multiset, "a"));
977    assertEquals(2, Iterables.frequency(multiset, "b"));
978    assertEquals(1, Iterables.frequency(multiset, "c"));
979    assertEquals(0, Iterables.frequency(multiset, "d"));
980    assertEquals(0, Iterables.frequency(multiset, 4.2));
981    assertEquals(0, Iterables.frequency(multiset, null));
982  }
983
984  public void testFrequency_set() {
985    Set<String> set = Sets.newHashSet("a", "b", "c");
986    assertEquals(1, Iterables.frequency(set, "a"));
987    assertEquals(1, Iterables.frequency(set, "b"));
988    assertEquals(1, Iterables.frequency(set, "c"));
989    assertEquals(0, Iterables.frequency(set, "d"));
990    assertEquals(0, Iterables.frequency(set, 4.2));
991    assertEquals(0, Iterables.frequency(set, null));
992  }
993
994  public void testFrequency_list() {
995    List<String> list = newArrayList("a", "b", "a", "c", "b", "a");
996    assertEquals(3, Iterables.frequency(list, "a"));
997    assertEquals(2, Iterables.frequency(list, "b"));
998    assertEquals(1, Iterables.frequency(list, "c"));
999    assertEquals(0, Iterables.frequency(list, "d"));
1000    assertEquals(0, Iterables.frequency(list, 4.2));
1001    assertEquals(0, Iterables.frequency(list, null));
1002  }
1003
1004  public void testRemoveAll_collection() {
1005    List<String> list = newArrayList("a", "b", "c", "d", "e");
1006    assertTrue(Iterables.removeAll(list, newArrayList("b", "d", "f")));
1007    assertEquals(newArrayList("a", "c", "e"), list);
1008    assertFalse(Iterables.removeAll(list, newArrayList("x", "y", "z")));
1009    assertEquals(newArrayList("a", "c", "e"), list);
1010  }
1011
1012  public void testRemoveAll_iterable() {
1013    final List<String> list = newArrayList("a", "b", "c", "d", "e");
1014    Iterable<String> iterable = new Iterable<String>() {
1015      @Override
1016      public Iterator<String> iterator() {
1017        return list.iterator();
1018      }
1019    };
1020    assertTrue(Iterables.removeAll(iterable, newArrayList("b", "d", "f")));
1021    assertEquals(newArrayList("a", "c", "e"), list);
1022    assertFalse(Iterables.removeAll(iterable, newArrayList("x", "y", "z")));
1023    assertEquals(newArrayList("a", "c", "e"), list);
1024  }
1025
1026  public void testRetainAll_collection() {
1027    List<String> list = newArrayList("a", "b", "c", "d", "e");
1028    assertTrue(Iterables.retainAll(list, newArrayList("b", "d", "f")));
1029    assertEquals(newArrayList("b", "d"), list);
1030    assertFalse(Iterables.retainAll(list, newArrayList("b", "e", "d")));
1031    assertEquals(newArrayList("b", "d"), list);
1032  }
1033
1034  public void testRetainAll_iterable() {
1035    final List<String> list = newArrayList("a", "b", "c", "d", "e");
1036    Iterable<String> iterable = new Iterable<String>() {
1037      @Override
1038      public Iterator<String> iterator() {
1039        return list.iterator();
1040      }
1041    };
1042    assertTrue(Iterables.retainAll(iterable, newArrayList("b", "d", "f")));
1043    assertEquals(newArrayList("b", "d"), list);
1044    assertFalse(Iterables.retainAll(iterable, newArrayList("b", "e", "d")));
1045    assertEquals(newArrayList("b", "d"), list);
1046  }
1047
1048  public void testRemoveIf_randomAccess() {
1049    List<String> list = newArrayList("a", "b", "c", "d", "e");
1050    assertTrue(Iterables.removeIf(list,
1051        new Predicate<String>() {
1052          @Override
1053          public boolean apply(String s) {
1054            return s.equals("b") || s.equals("d") || s.equals("f");
1055          }
1056        }));
1057    assertEquals(newArrayList("a", "c", "e"), list);
1058    assertFalse(Iterables.removeIf(list,
1059        new Predicate<String>() {
1060          @Override
1061          public boolean apply(String s) {
1062            return s.equals("x") || s.equals("y") || s.equals("z");
1063          }
1064        }));
1065    assertEquals(newArrayList("a", "c", "e"), list);
1066  }
1067
1068  public void testRemoveIf_transformedList() {
1069    List<String> list = newArrayList("1", "2", "3", "4", "5");
1070    List<Integer> transformed = Lists.transform(list,
1071        new Function<String, Integer>() {
1072          @Override
1073          public Integer apply(String s) {
1074            return Integer.valueOf(s);
1075          }
1076        });
1077    assertTrue(Iterables.removeIf(transformed,
1078        new Predicate<Integer>() {
1079          @Override
1080          public boolean apply(Integer n) {
1081            return (n & 1) == 0;  // isEven()
1082          }
1083        }));
1084    assertEquals(newArrayList("1", "3", "5"), list);
1085    assertFalse(Iterables.removeIf(transformed,
1086        new Predicate<Integer>() {
1087          @Override
1088          public boolean apply(Integer n) {
1089            return (n & 1) == 0;  // isEven()
1090          }
1091        }));
1092    assertEquals(newArrayList("1", "3", "5"), list);
1093  }
1094
1095  public void testRemoveIf_noRandomAccess() {
1096    List<String> list = Lists.newLinkedList(asList("a", "b", "c", "d", "e"));
1097    assertTrue(Iterables.removeIf(list,
1098        new Predicate<String>() {
1099          @Override
1100          public boolean apply(String s) {
1101            return s.equals("b") || s.equals("d") || s.equals("f");
1102          }
1103        }));
1104    assertEquals(newArrayList("a", "c", "e"), list);
1105    assertFalse(Iterables.removeIf(list,
1106        new Predicate<String>() {
1107          @Override
1108          public boolean apply(String s) {
1109            return s.equals("x") || s.equals("y") || s.equals("z");
1110          }
1111        }));
1112    assertEquals(newArrayList("a", "c", "e"), list);
1113  }
1114
1115  // The Maps returned by Maps.filterEntries(), Maps.filterKeys(), and
1116  // Maps.filterValues() are not tested with removeIf() since Maps are not
1117  // Iterable.  Those returned by Iterators.filter() and Iterables.filter()
1118  // are not tested because they are unmodifiable.
1119
1120  public void testIterableWithToString() {
1121    assertEquals("[]", create().toString());
1122    assertEquals("[a]", create("a").toString());
1123    assertEquals("[a, b, c]", create("a", "b", "c").toString());
1124    assertEquals("[c, a, a]", create("c", "a", "a").toString());
1125  }
1126
1127  public void testIterableWithToStringNull() {
1128    assertEquals("[null]", create((String) null).toString());
1129    assertEquals("[null, null]", create(null, null).toString());
1130    assertEquals("[, null, a]", create("", null, "a").toString());
1131  }
1132
1133  /** Returns a new iterable over the specified strings. */
1134  private static Iterable<String> create(String... strings) {
1135    final List<String> list = asList(strings);
1136    return new Iterables.IterableWithToString<String>() {
1137      @Override
1138      public Iterator<String> iterator() {
1139        return list.iterator();
1140      }
1141    };
1142  }
1143
1144  public void testConsumingIterable() {
1145    // Test data
1146    List<String> list = Lists.newArrayList(asList("a", "b"));
1147
1148    // Test & Verify
1149    Iterable<String> consumingIterable = Iterables.consumingIterable(list);
1150    Iterator<String> consumingIterator = consumingIterable.iterator();
1151
1152    ASSERT.that(list).hasContentsInOrder("a", "b");
1153
1154    assertTrue(consumingIterator.hasNext());
1155    ASSERT.that(list).hasContentsInOrder("a", "b");
1156    assertEquals("a", consumingIterator.next());
1157    ASSERT.that(list).hasContentsInOrder("b");
1158
1159    assertTrue(consumingIterator.hasNext());
1160    assertEquals("b", consumingIterator.next());
1161    ASSERT.that(list).isEmpty();
1162
1163    assertFalse(consumingIterator.hasNext());
1164  }
1165
1166  @GwtIncompatible("?")
1167  // TODO: Figure out why this is failing in GWT.
1168  public void testConsumingIterable_duelingIterators() {
1169    // Test data
1170    List<String> list = Lists.newArrayList(asList("a", "b"));
1171
1172    // Test & Verify
1173    Iterator<String> i1 = Iterables.consumingIterable(list).iterator();
1174    Iterator<String> i2 = Iterables.consumingIterable(list).iterator();
1175
1176    i1.next();
1177    try {
1178      i2.next();
1179      fail("Concurrent modification should throw an exception.");
1180    } catch (ConcurrentModificationException cme) {
1181      // Pass
1182    }
1183  }
1184
1185  public void testConsumingIterable_queue_iterator() {
1186    final List<Integer> items = ImmutableList.of(4, 8, 15, 16, 23, 42);
1187    new IteratorTester<Integer>(
1188        3,
1189        UNMODIFIABLE,
1190        items,
1191        IteratorTester.KnownOrder.KNOWN_ORDER) {
1192      @Override protected Iterator<Integer> newTargetIterator() {
1193        return Iterables.consumingIterable(Lists.newLinkedList(items))
1194            .iterator();
1195      }
1196    }.test();
1197  }
1198
1199  public void testConsumingIterable_queue_removesFromQueue() {
1200    Queue<Integer> queue = Lists.newLinkedList(asList(5, 14));
1201
1202    Iterator<Integer> consumingIterator =
1203        Iterables.consumingIterable(queue).iterator();
1204
1205    assertEquals(5, queue.peek().intValue());
1206    assertEquals(5, consumingIterator.next().intValue());
1207
1208    assertEquals(14, queue.peek().intValue());
1209    assertTrue(consumingIterator.hasNext());
1210    assertTrue(queue.isEmpty());
1211  }
1212
1213  public void testConsumingIterable_noIteratorCall() {
1214    Queue<Integer> queue =
1215        new UnIterableQueue<Integer>(Lists.newLinkedList(asList(5, 14)));
1216
1217    Iterator<Integer> consumingIterator =
1218        Iterables.consumingIterable(queue).iterator();
1219    /*
1220     * Make sure that we can get an element off without calling
1221     * UnIterableQueue.iterator().
1222     */
1223    assertEquals(5, consumingIterator.next().intValue());
1224  }
1225
1226  private static class UnIterableQueue<T> extends ForwardingQueue<T> {
1227    private Queue<T> queue;
1228
1229    UnIterableQueue(Queue<T> queue) {
1230      this.queue = queue;
1231    }
1232
1233    @Override public Iterator<T> iterator() {
1234      throw new UnsupportedOperationException();
1235    }
1236
1237    @Override protected Queue<T> delegate() {
1238      return queue;
1239    }
1240  }
1241
1242  public void testIndexOf_empty() {
1243    List<String> list = new ArrayList<String>();
1244    assertEquals(-1, Iterables.indexOf(list, Predicates.equalTo("")));
1245  }
1246
1247  public void testIndexOf_oneElement() {
1248    List<String> list = Lists.newArrayList("bob");
1249    assertEquals(0, Iterables.indexOf(list, Predicates.equalTo("bob")));
1250    assertEquals(-1, Iterables.indexOf(list, Predicates.equalTo("jack")));
1251  }
1252
1253  public void testIndexOf_twoElements() {
1254    List<String> list = Lists.newArrayList("mary", "bob");
1255    assertEquals(0, Iterables.indexOf(list, Predicates.equalTo("mary")));
1256    assertEquals(1, Iterables.indexOf(list, Predicates.equalTo("bob")));
1257    assertEquals(-1, Iterables.indexOf(list, Predicates.equalTo("jack")));
1258  }
1259
1260  public void testIndexOf_withDuplicates() {
1261    List<String> list =
1262        Lists.newArrayList("mary", "bob", "bob", "bob", "sam");
1263    assertEquals(0, Iterables.indexOf(list, Predicates.equalTo("mary")));
1264    assertEquals(1, Iterables.indexOf(list, Predicates.equalTo("bob")));
1265    assertEquals(4, Iterables.indexOf(list, Predicates.equalTo("sam")));
1266    assertEquals(-1, Iterables.indexOf(list, Predicates.equalTo("jack")));
1267  }
1268
1269  private static final Predicate<CharSequence> STARTSWITH_A =
1270      new Predicate<CharSequence>() {
1271        @Override public boolean apply(CharSequence input) {
1272          return (input.length() > 0) && (input.charAt(0) == 'a');
1273        }
1274      };
1275
1276  public void testIndexOf_genericPredicate() {
1277    List<CharSequence> sequences = Lists.newArrayList();
1278    sequences.add("bob");
1279    sequences.add(new StringBuilder("charlie"));
1280    sequences.add(new StringBuffer("henry"));
1281    sequences.add(new StringBuilder("apple"));
1282    sequences.add("lemon");
1283
1284    assertEquals(3, Iterables.indexOf(sequences, STARTSWITH_A));
1285  }
1286
1287  public void testIndexOf_genericPredicate2() {
1288    List<String> sequences =
1289        Lists.newArrayList("bob", "charlie", "henry", "apple", "lemon");
1290    assertEquals(3, Iterables.indexOf(sequences, STARTSWITH_A));
1291  }
1292
1293  public void testMergeSorted_empty() {
1294    // Setup
1295    Iterable<Iterable<Integer>> elements = ImmutableList.of();
1296
1297    // Test
1298    Iterable<Integer> iterable =
1299        Iterables.mergeSorted(elements, Ordering.natural());
1300
1301    // Verify
1302    Iterator<Integer> iterator = iterable.iterator();
1303    assertFalse(iterator.hasNext());
1304    try {
1305      iterator.next();
1306      fail("next() on empty iterator should throw NoSuchElementException");
1307    } catch (NoSuchElementException e) {
1308      // Huzzah!
1309    }
1310  }
1311
1312  public void testMergeSorted_single_empty() {
1313    // Setup
1314    Iterable<Integer> iterable0 = ImmutableList.of();
1315    Iterable<Iterable<Integer>> iterables = ImmutableList.of(iterable0);
1316
1317    // Test & Verify
1318    verifyMergeSorted(iterables, ImmutableList.<Integer>of());
1319  }
1320
1321  public void testMergeSorted_single() {
1322    // Setup
1323    Iterable<Integer> iterable0 = ImmutableList.of(1, 2, 3);
1324    Iterable<Iterable<Integer>> iterables = ImmutableList.of(iterable0);
1325
1326    // Test & Verify
1327    verifyMergeSorted(iterables, iterable0);
1328  }
1329
1330  public void testMergeSorted_pyramid() {
1331    List<Iterable<Integer>> iterables = Lists.newLinkedList();
1332    List<Integer> allIntegers = Lists.newArrayList();
1333
1334    // Creates iterators like: {{}, {0}, {0, 1}, {0, 1, 2}, ...}
1335    for (int i = 0; i < 10; i++) {
1336      List<Integer> list = Lists.newLinkedList();
1337      for (int j = 0; j < i; j++) {
1338        list.add(j);
1339        allIntegers.add(j);
1340      }
1341      iterables.add(Ordering.natural().sortedCopy(list));
1342    }
1343
1344    verifyMergeSorted(iterables, allIntegers);
1345  }
1346
1347  // Like the pyramid, but creates more unique values, along with repeated ones.
1348  public void testMergeSorted_skipping_pyramid() {
1349    List<Iterable<Integer>> iterables = Lists.newLinkedList();
1350    List<Integer> allIntegers = Lists.newArrayList();
1351
1352    for (int i = 0; i < 20; i++) {
1353      List<Integer> list = Lists.newLinkedList();
1354      for (int j = 0; j < i; j++) {
1355        list.add(j * i);
1356        allIntegers.add(j * i);
1357      }
1358      iterables.add(Ordering.natural().sortedCopy(list));
1359    }
1360
1361    verifyMergeSorted(iterables, allIntegers);
1362  }
1363
1364  private void verifyMergeSorted(Iterable<Iterable<Integer>> iterables,
1365      Iterable<Integer> unsortedExpected) {
1366    Iterable<Integer> expected =
1367        Ordering.natural().sortedCopy(unsortedExpected);
1368
1369    Iterable<Integer> mergedIterator =
1370        Iterables.mergeSorted(iterables, Ordering.natural());
1371
1372    assertEquals(Lists.newLinkedList(expected),
1373        Lists.newLinkedList(mergedIterator));
1374  }
1375}
1376