• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import static com.google.common.collect.Lists.newArrayList;
20 import static com.google.common.truth.Truth.assertThat;
21 import static java.util.Arrays.asList;
22 
23 import com.google.common.annotations.GwtCompatible;
24 import com.google.common.annotations.GwtIncompatible;
25 import com.google.common.base.Function;
26 import com.google.common.base.Functions;
27 import com.google.common.base.Joiner;
28 import com.google.common.base.Predicate;
29 import com.google.common.base.Predicates;
30 import com.google.common.collect.testing.IteratorFeature;
31 import com.google.common.collect.testing.IteratorTester;
32 import com.google.common.testing.NullPointerTester;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Set;
39 import java.util.SortedSet;
40 import java.util.concurrent.TimeUnit;
41 import junit.framework.AssertionFailedError;
42 import junit.framework.TestCase;
43 import org.checkerframework.checker.nullness.compatqual.NullableDecl;
44 
45 /**
46  * Unit test for {@link FluentIterable}.
47  *
48  * @author Marcin Mikosik
49  */
50 @GwtCompatible(emulated = true)
51 public class FluentIterableTest extends TestCase {
52 
53   @GwtIncompatible // NullPointerTester
testNullPointerExceptions()54   public void testNullPointerExceptions() {
55     NullPointerTester tester = new NullPointerTester();
56     tester.testAllPublicStaticMethods(FluentIterable.class);
57   }
58 
testFromArrayAndAppend()59   public void testFromArrayAndAppend() {
60     FluentIterable<TimeUnit> units =
61         FluentIterable.from(TimeUnit.values()).append(TimeUnit.SECONDS);
62   }
63 
testFromArrayAndIteratorRemove()64   public void testFromArrayAndIteratorRemove() {
65     FluentIterable<TimeUnit> units = FluentIterable.from(TimeUnit.values());
66     try {
67       Iterables.removeIf(units, Predicates.equalTo(TimeUnit.SECONDS));
68       fail("Expected an UnsupportedOperationException to be thrown but it wasn't.");
69     } catch (UnsupportedOperationException expected) {
70     }
71   }
72 
testFrom()73   public void testFrom() {
74     assertEquals(
75         ImmutableList.of(1, 2, 3, 4),
76         Lists.newArrayList(FluentIterable.from(ImmutableList.of(1, 2, 3, 4))));
77   }
78 
79   @SuppressWarnings("deprecation") // test of deprecated method
testFrom_alreadyFluentIterable()80   public void testFrom_alreadyFluentIterable() {
81     FluentIterable<Integer> iterable = FluentIterable.from(asList(1));
82     assertSame(iterable, FluentIterable.from(iterable));
83   }
84 
testOf()85   public void testOf() {
86     assertEquals(ImmutableList.of(1, 2, 3, 4), Lists.newArrayList(FluentIterable.of(1, 2, 3, 4)));
87   }
88 
testFromArray()89   public void testFromArray() {
90     assertEquals(
91         ImmutableList.of("1", "2", "3", "4"),
92         Lists.newArrayList(FluentIterable.from(new Object[] {"1", "2", "3", "4"})));
93   }
94 
testOf_empty()95   public void testOf_empty() {
96     assertEquals(ImmutableList.of(), Lists.newArrayList(FluentIterable.of()));
97   }
98 
99   // Exhaustive tests are in IteratorsTest. These are copied from IterablesTest.
testConcatIterable()100   public void testConcatIterable() {
101     List<Integer> list1 = newArrayList(1);
102     List<Integer> list2 = newArrayList(4);
103 
104     @SuppressWarnings("unchecked")
105     List<List<Integer>> input = newArrayList(list1, list2);
106 
107     FluentIterable<Integer> result = FluentIterable.concat(input);
108     assertEquals(asList(1, 4), newArrayList(result));
109 
110     // Now change the inputs and see result dynamically change as well
111 
112     list1.add(2);
113     List<Integer> list3 = newArrayList(3);
114     input.add(1, list3);
115 
116     assertEquals(asList(1, 2, 3, 4), newArrayList(result));
117     assertEquals("[1, 2, 3, 4]", result.toString());
118   }
119 
testConcatVarargs()120   public void testConcatVarargs() {
121     List<Integer> list1 = newArrayList(1);
122     List<Integer> list2 = newArrayList(4);
123     List<Integer> list3 = newArrayList(7, 8);
124     List<Integer> list4 = newArrayList(9);
125     List<Integer> list5 = newArrayList(10);
126     @SuppressWarnings("unchecked")
127     FluentIterable<Integer> result = FluentIterable.concat(list1, list2, list3, list4, list5);
128     assertEquals(asList(1, 4, 7, 8, 9, 10), newArrayList(result));
129     assertEquals("[1, 4, 7, 8, 9, 10]", result.toString());
130   }
131 
testConcatNullPointerException()132   public void testConcatNullPointerException() {
133     List<Integer> list1 = newArrayList(1);
134     List<Integer> list2 = newArrayList(4);
135 
136     try {
137       FluentIterable.concat(list1, null, list2);
138       fail();
139     } catch (NullPointerException expected) {
140     }
141   }
142 
testConcatPeformingFiniteCycle()143   public void testConcatPeformingFiniteCycle() {
144     Iterable<Integer> iterable = asList(1, 2, 3);
145     int n = 4;
146     FluentIterable<Integer> repeated = FluentIterable.concat(Collections.nCopies(n, iterable));
147     assertThat(repeated).containsExactly(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3).inOrder();
148   }
149 
150   interface X {}
151 
152   interface Y {}
153 
154   static class A implements X, Y {}
155 
156   static class B implements X, Y {}
157 
158   /**
159    * This test passes if the {@code concat(…).filter(…).filter(…)} statement at the end compiles.
160    * That statement compiles only if {@link FluentIterable#concat concat(aIterable, bIterable)}
161    * returns a {@link FluentIterable} of elements of an anonymous type whose supertypes are the <a
162    * href="https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.9">intersection</a> of
163    * the supertypes of {@code A} and the supertypes of {@code B}.
164    */
testConcatIntersectionType()165   public void testConcatIntersectionType() {
166     Iterable<A> aIterable = ImmutableList.of();
167     Iterable<B> bIterable = ImmutableList.of();
168 
169     Predicate<X> xPredicate = Predicates.alwaysTrue();
170     Predicate<Y> yPredicate = Predicates.alwaysTrue();
171 
172     FluentIterable<?> unused =
173         FluentIterable.concat(aIterable, bIterable).filter(xPredicate).filter(yPredicate);
174 
175     /* The following fails to compile:
176      *
177      * The method append(Iterable<? extends FluentIterableTest.A>) in the type
178      * FluentIterable<FluentIterableTest.A> is not applicable for the arguments
179      * (Iterable<FluentIterableTest.B>)
180      */
181     // FluentIterable.from(aIterable).append(bIterable);
182 
183     /* The following fails to compile:
184      *
185      * The method filter(Predicate<? super Object>) in the type FluentIterable<Object> is not
186      * applicable for the arguments (Predicate<FluentIterableTest.X>)
187      */
188     // FluentIterable.of().append(aIterable).append(bIterable).filter(xPredicate);
189   }
190 
testSize0()191   public void testSize0() {
192     assertEquals(0, FluentIterable.<String>of().size());
193   }
194 
testSize1Collection()195   public void testSize1Collection() {
196     assertEquals(1, FluentIterable.from(asList("a")).size());
197   }
198 
testSize2NonCollection()199   public void testSize2NonCollection() {
200     Iterable<Integer> iterable =
201         new Iterable<Integer>() {
202           @Override
203           public Iterator<Integer> iterator() {
204             return asList(0, 1).iterator();
205           }
206         };
207     assertEquals(2, FluentIterable.from(iterable).size());
208   }
209 
testSize_collectionDoesntIterate()210   public void testSize_collectionDoesntIterate() {
211     List<Integer> nums = asList(1, 2, 3, 4, 5);
212     List<Integer> collection =
213         new ArrayList<Integer>(nums) {
214           @Override
215           public Iterator<Integer> iterator() {
216             throw new AssertionFailedError("Don't iterate me!");
217           }
218         };
219     assertEquals(5, FluentIterable.from(collection).size());
220   }
221 
testContains_nullSetYes()222   public void testContains_nullSetYes() {
223     Iterable<String> set = Sets.newHashSet("a", null, "b");
224     assertTrue(FluentIterable.from(set).contains(null));
225   }
226 
testContains_nullSetNo()227   public void testContains_nullSetNo() {
228     Iterable<String> set = ImmutableSortedSet.of("a", "b");
229     assertFalse(FluentIterable.from(set).contains(null));
230   }
231 
testContains_nullIterableYes()232   public void testContains_nullIterableYes() {
233     Iterable<String> iterable = iterable("a", null, "b");
234     assertTrue(FluentIterable.from(iterable).contains(null));
235   }
236 
testContains_nullIterableNo()237   public void testContains_nullIterableNo() {
238     Iterable<String> iterable = iterable("a", "b");
239     assertFalse(FluentIterable.from(iterable).contains(null));
240   }
241 
testContains_nonNullSetYes()242   public void testContains_nonNullSetYes() {
243     Iterable<String> set = Sets.newHashSet("a", null, "b");
244     assertTrue(FluentIterable.from(set).contains("b"));
245   }
246 
testContains_nonNullSetNo()247   public void testContains_nonNullSetNo() {
248     Iterable<String> set = Sets.newHashSet("a", "b");
249     assertFalse(FluentIterable.from(set).contains("c"));
250   }
251 
testContains_nonNullIterableYes()252   public void testContains_nonNullIterableYes() {
253     Iterable<String> set = iterable("a", null, "b");
254     assertTrue(FluentIterable.from(set).contains("b"));
255   }
256 
testContains_nonNullIterableNo()257   public void testContains_nonNullIterableNo() {
258     Iterable<String> iterable = iterable("a", "b");
259     assertFalse(FluentIterable.from(iterable).contains("c"));
260   }
261 
testOfToString()262   public void testOfToString() {
263     assertEquals("[yam, bam, jam, ham]", FluentIterable.of("yam", "bam", "jam", "ham").toString());
264   }
265 
testToString()266   public void testToString() {
267     assertEquals("[]", FluentIterable.from(Collections.emptyList()).toString());
268     assertEquals("[]", FluentIterable.<String>of().toString());
269 
270     assertEquals(
271         "[yam, bam, jam, ham]", FluentIterable.from(asList("yam", "bam", "jam", "ham")).toString());
272   }
273 
testCycle()274   public void testCycle() {
275     FluentIterable<String> cycle = FluentIterable.from(asList("a", "b")).cycle();
276 
277     int howManyChecked = 0;
278     for (String string : cycle) {
279       String expected = (howManyChecked % 2 == 0) ? "a" : "b";
280       assertEquals(expected, string);
281       if (howManyChecked++ == 5) {
282         break;
283       }
284     }
285 
286     // We left the last iterator pointing to "b". But a new iterator should
287     // always point to "a".
288     assertEquals("a", cycle.iterator().next());
289   }
290 
testCycle_emptyIterable()291   public void testCycle_emptyIterable() {
292     FluentIterable<Integer> cycle = FluentIterable.<Integer>of().cycle();
293     assertFalse(cycle.iterator().hasNext());
294   }
295 
testCycle_removingAllElementsStopsCycle()296   public void testCycle_removingAllElementsStopsCycle() {
297     FluentIterable<Integer> cycle = fluent(1, 2).cycle();
298     Iterator<Integer> iterator = cycle.iterator();
299     iterator.next();
300     iterator.remove();
301     iterator.next();
302     iterator.remove();
303     assertFalse(iterator.hasNext());
304     assertFalse(cycle.iterator().hasNext());
305   }
306 
testAppend()307   public void testAppend() {
308     FluentIterable<Integer> result =
309         FluentIterable.<Integer>from(asList(1, 2, 3)).append(Lists.newArrayList(4, 5, 6));
310     assertEquals(asList(1, 2, 3, 4, 5, 6), Lists.newArrayList(result));
311     assertEquals("[1, 2, 3, 4, 5, 6]", result.toString());
312 
313     result = FluentIterable.<Integer>from(asList(1, 2, 3)).append(4, 5, 6);
314     assertEquals(asList(1, 2, 3, 4, 5, 6), Lists.newArrayList(result));
315     assertEquals("[1, 2, 3, 4, 5, 6]", result.toString());
316   }
317 
testAppend_toEmpty()318   public void testAppend_toEmpty() {
319     FluentIterable<Integer> result =
320         FluentIterable.<Integer>of().append(Lists.newArrayList(1, 2, 3));
321     assertEquals(asList(1, 2, 3), Lists.newArrayList(result));
322   }
323 
testAppend_emptyList()324   public void testAppend_emptyList() {
325     FluentIterable<Integer> result =
326         FluentIterable.<Integer>from(asList(1, 2, 3)).append(Lists.<Integer>newArrayList());
327     assertEquals(asList(1, 2, 3), Lists.newArrayList(result));
328   }
329 
testAppend_nullPointerException()330   public void testAppend_nullPointerException() {
331     try {
332       FluentIterable<Integer> unused =
333           FluentIterable.<Integer>from(asList(1, 2)).append((List<Integer>) null);
334       fail("Appending null iterable should throw NPE.");
335     } catch (NullPointerException expected) {
336     }
337   }
338 
339   /*
340    * Tests for partition(int size) method.
341    */
342 
343   /*
344    * Tests for partitionWithPadding(int size) method.
345    */
346 
testFilter()347   public void testFilter() {
348     FluentIterable<String> filtered =
349         FluentIterable.from(asList("foo", "bar")).filter(Predicates.equalTo("foo"));
350 
351     List<String> expected = Collections.singletonList("foo");
352     List<String> actual = Lists.newArrayList(filtered);
353     assertEquals(expected, actual);
354     assertCanIterateAgain(filtered);
355     assertEquals("[foo]", filtered.toString());
356   }
357 
358   private static class TypeA {}
359 
360   private interface TypeB {}
361 
362   private static class HasBoth extends TypeA implements TypeB {}
363 
364   @GwtIncompatible // Iterables.filter(Iterable, Class)
testFilterByType()365   public void testFilterByType() throws Exception {
366     HasBoth hasBoth = new HasBoth();
367     FluentIterable<TypeA> alist =
368         FluentIterable.from(asList(new TypeA(), new TypeA(), hasBoth, new TypeA()));
369     Iterable<TypeB> blist = alist.filter(TypeB.class);
370     assertThat(blist).containsExactly(hasBoth).inOrder();
371   }
372 
testAnyMatch()373   public void testAnyMatch() {
374     ArrayList<String> list = Lists.newArrayList();
375     FluentIterable<String> iterable = FluentIterable.<String>from(list);
376     Predicate<String> predicate = Predicates.equalTo("pants");
377 
378     assertFalse(iterable.anyMatch(predicate));
379     list.add("cool");
380     assertFalse(iterable.anyMatch(predicate));
381     list.add("pants");
382     assertTrue(iterable.anyMatch(predicate));
383   }
384 
testAllMatch()385   public void testAllMatch() {
386     List<String> list = Lists.newArrayList();
387     FluentIterable<String> iterable = FluentIterable.<String>from(list);
388     Predicate<String> predicate = Predicates.equalTo("cool");
389 
390     assertTrue(iterable.allMatch(predicate));
391     list.add("cool");
392     assertTrue(iterable.allMatch(predicate));
393     list.add("pants");
394     assertFalse(iterable.allMatch(predicate));
395   }
396 
testFirstMatch()397   public void testFirstMatch() {
398     FluentIterable<String> iterable = FluentIterable.from(Lists.newArrayList("cool", "pants"));
399     assertThat(iterable.firstMatch(Predicates.equalTo("cool"))).hasValue("cool");
400     assertThat(iterable.firstMatch(Predicates.equalTo("pants"))).hasValue("pants");
401     assertThat(iterable.firstMatch(Predicates.alwaysFalse())).isAbsent();
402     assertThat(iterable.firstMatch(Predicates.alwaysTrue())).hasValue("cool");
403   }
404 
405   private static final class IntegerValueOfFunction implements Function<String, Integer> {
406     @Override
apply(String from)407     public Integer apply(String from) {
408       return Integer.valueOf(from);
409     }
410   }
411 
testTransformWith()412   public void testTransformWith() {
413     List<String> input = asList("1", "2", "3");
414     Iterable<Integer> iterable = FluentIterable.from(input).transform(new IntegerValueOfFunction());
415 
416     assertEquals(asList(1, 2, 3), Lists.newArrayList(iterable));
417     assertCanIterateAgain(iterable);
418     assertEquals("[1, 2, 3]", iterable.toString());
419   }
420 
testTransformWith_poorlyBehavedTransform()421   public void testTransformWith_poorlyBehavedTransform() {
422     List<String> input = asList("1", null, "3");
423     Iterable<Integer> iterable = FluentIterable.from(input).transform(new IntegerValueOfFunction());
424 
425     Iterator<Integer> resultIterator = iterable.iterator();
426     resultIterator.next();
427 
428     try {
429       resultIterator.next();
430       fail("Transforming null to int should throw NumberFormatException");
431     } catch (NumberFormatException expected) {
432     }
433   }
434 
435   private static final class StringValueOfFunction implements Function<Integer, String> {
436     @Override
apply(Integer from)437     public String apply(Integer from) {
438       return String.valueOf(from);
439     }
440   }
441 
testTransformWith_nullFriendlyTransform()442   public void testTransformWith_nullFriendlyTransform() {
443     List<Integer> input = asList(1, 2, null, 3);
444     Iterable<String> result = FluentIterable.from(input).transform(new StringValueOfFunction());
445 
446     assertEquals(asList("1", "2", "null", "3"), Lists.newArrayList(result));
447   }
448 
449   private static final class RepeatedStringValueOfFunction
450       implements Function<Integer, List<String>> {
451     @Override
apply(Integer from)452     public List<String> apply(Integer from) {
453       String value = String.valueOf(from);
454       return ImmutableList.of(value, value);
455     }
456   }
457 
testTransformAndConcat()458   public void testTransformAndConcat() {
459     List<Integer> input = asList(1, 2, 3);
460     Iterable<String> result =
461         FluentIterable.from(input).transformAndConcat(new RepeatedStringValueOfFunction());
462     assertEquals(asList("1", "1", "2", "2", "3", "3"), Lists.newArrayList(result));
463   }
464 
465   private static final class RepeatedStringValueOfWildcardFunction
466       implements Function<Integer, List<? extends String>> {
467     @Override
apply(Integer from)468     public List<String> apply(Integer from) {
469       String value = String.valueOf(from);
470       return ImmutableList.of(value, value);
471     }
472   }
473 
testTransformAndConcat_wildcardFunctionGenerics()474   public void testTransformAndConcat_wildcardFunctionGenerics() {
475     List<Integer> input = asList(1, 2, 3);
476     FluentIterable<String> unused =
477         FluentIterable.from(input).transformAndConcat(new RepeatedStringValueOfWildcardFunction());
478   }
479 
testFirst_list()480   public void testFirst_list() {
481     List<String> list = Lists.newArrayList("a", "b", "c");
482     assertThat(FluentIterable.from(list).first()).hasValue("a");
483   }
484 
testFirst_null()485   public void testFirst_null() {
486     List<String> list = Lists.newArrayList(null, "a", "b");
487     try {
488       FluentIterable.from(list).first();
489       fail();
490     } catch (NullPointerException expected) {
491     }
492   }
493 
testFirst_emptyList()494   public void testFirst_emptyList() {
495     List<String> list = Collections.emptyList();
496     assertThat(FluentIterable.from(list).first()).isAbsent();
497   }
498 
testFirst_sortedSet()499   public void testFirst_sortedSet() {
500     SortedSet<String> sortedSet = ImmutableSortedSet.of("b", "c", "a");
501     assertThat(FluentIterable.from(sortedSet).first()).hasValue("a");
502   }
503 
testFirst_emptySortedSet()504   public void testFirst_emptySortedSet() {
505     SortedSet<String> sortedSet = ImmutableSortedSet.of();
506     assertThat(FluentIterable.from(sortedSet).first()).isAbsent();
507   }
508 
testFirst_iterable()509   public void testFirst_iterable() {
510     Set<String> set = ImmutableSet.of("a", "b", "c");
511     assertThat(FluentIterable.from(set).first()).hasValue("a");
512   }
513 
testFirst_emptyIterable()514   public void testFirst_emptyIterable() {
515     Set<String> set = Sets.newHashSet();
516     assertThat(FluentIterable.from(set).first()).isAbsent();
517   }
518 
testLast_list()519   public void testLast_list() {
520     List<String> list = Lists.newArrayList("a", "b", "c");
521     assertThat(FluentIterable.from(list).last()).hasValue("c");
522   }
523 
testLast_null()524   public void testLast_null() {
525     List<String> list = Lists.newArrayList("a", "b", null);
526     try {
527       FluentIterable.from(list).last();
528       fail();
529     } catch (NullPointerException expected) {
530     }
531   }
532 
testLast_emptyList()533   public void testLast_emptyList() {
534     List<String> list = Collections.emptyList();
535     assertThat(FluentIterable.from(list).last()).isAbsent();
536   }
537 
testLast_sortedSet()538   public void testLast_sortedSet() {
539     SortedSet<String> sortedSet = ImmutableSortedSet.of("b", "c", "a");
540     assertThat(FluentIterable.from(sortedSet).last()).hasValue("c");
541   }
542 
testLast_emptySortedSet()543   public void testLast_emptySortedSet() {
544     SortedSet<String> sortedSet = ImmutableSortedSet.of();
545     assertThat(FluentIterable.from(sortedSet).last()).isAbsent();
546   }
547 
testLast_iterable()548   public void testLast_iterable() {
549     Set<String> set = ImmutableSet.of("a", "b", "c");
550     assertThat(FluentIterable.from(set).last()).hasValue("c");
551   }
552 
testLast_emptyIterable()553   public void testLast_emptyIterable() {
554     Set<String> set = Sets.newHashSet();
555     assertThat(FluentIterable.from(set).last()).isAbsent();
556   }
557 
testSkip_simple()558   public void testSkip_simple() {
559     Collection<String> set = ImmutableSet.of("a", "b", "c", "d", "e");
560     assertEquals(
561         Lists.newArrayList("c", "d", "e"), Lists.newArrayList(FluentIterable.from(set).skip(2)));
562     assertEquals("[c, d, e]", FluentIterable.from(set).skip(2).toString());
563   }
564 
testSkip_simpleList()565   public void testSkip_simpleList() {
566     Collection<String> list = Lists.newArrayList("a", "b", "c", "d", "e");
567     assertEquals(
568         Lists.newArrayList("c", "d", "e"), Lists.newArrayList(FluentIterable.from(list).skip(2)));
569     assertEquals("[c, d, e]", FluentIterable.from(list).skip(2).toString());
570   }
571 
testSkip_pastEnd()572   public void testSkip_pastEnd() {
573     Collection<String> set = ImmutableSet.of("a", "b");
574     assertEquals(Collections.emptyList(), Lists.newArrayList(FluentIterable.from(set).skip(20)));
575   }
576 
testSkip_pastEndList()577   public void testSkip_pastEndList() {
578     Collection<String> list = Lists.newArrayList("a", "b");
579     assertEquals(Collections.emptyList(), Lists.newArrayList(FluentIterable.from(list).skip(20)));
580   }
581 
testSkip_skipNone()582   public void testSkip_skipNone() {
583     Collection<String> set = ImmutableSet.of("a", "b");
584     assertEquals(
585         Lists.newArrayList("a", "b"), Lists.newArrayList(FluentIterable.from(set).skip(0)));
586   }
587 
testSkip_skipNoneList()588   public void testSkip_skipNoneList() {
589     Collection<String> list = Lists.newArrayList("a", "b");
590     assertEquals(
591         Lists.newArrayList("a", "b"), Lists.newArrayList(FluentIterable.from(list).skip(0)));
592   }
593 
testSkip_iterator()594   public void testSkip_iterator() throws Exception {
595     new IteratorTester<Integer>(
596         5,
597         IteratorFeature.MODIFIABLE,
598         Lists.newArrayList(2, 3),
599         IteratorTester.KnownOrder.KNOWN_ORDER) {
600       @Override
601       protected Iterator<Integer> newTargetIterator() {
602         Collection<Integer> collection = Sets.newLinkedHashSet();
603         Collections.addAll(collection, 1, 2, 3);
604         return FluentIterable.from(collection).skip(1).iterator();
605       }
606     }.test();
607   }
608 
testSkip_iteratorList()609   public void testSkip_iteratorList() throws Exception {
610     new IteratorTester<Integer>(
611         5,
612         IteratorFeature.MODIFIABLE,
613         Lists.newArrayList(2, 3),
614         IteratorTester.KnownOrder.KNOWN_ORDER) {
615       @Override
616       protected Iterator<Integer> newTargetIterator() {
617         return FluentIterable.from(Lists.newArrayList(1, 2, 3)).skip(1).iterator();
618       }
619     }.test();
620   }
621 
testSkip_nonStructurallyModifiedList()622   public void testSkip_nonStructurallyModifiedList() throws Exception {
623     List<String> list = Lists.newArrayList("a", "b", "c");
624     FluentIterable<String> tail = FluentIterable.from(list).skip(1);
625     Iterator<String> tailIterator = tail.iterator();
626     list.set(2, "c2");
627     assertEquals("b", tailIterator.next());
628     assertEquals("c2", tailIterator.next());
629     assertFalse(tailIterator.hasNext());
630   }
631 
testSkip_structurallyModifiedSkipSome()632   public void testSkip_structurallyModifiedSkipSome() throws Exception {
633     Collection<String> set = Sets.newLinkedHashSet();
634     Collections.addAll(set, "a", "b", "c");
635     FluentIterable<String> tail = FluentIterable.from(set).skip(1);
636     set.remove("b");
637     set.addAll(Lists.newArrayList("X", "Y", "Z"));
638     assertThat(tail).containsExactly("c", "X", "Y", "Z").inOrder();
639   }
640 
testSkip_structurallyModifiedSkipSomeList()641   public void testSkip_structurallyModifiedSkipSomeList() throws Exception {
642     List<String> list = Lists.newArrayList("a", "b", "c");
643     FluentIterable<String> tail = FluentIterable.from(list).skip(1);
644     list.subList(1, 3).clear();
645     list.addAll(0, Lists.newArrayList("X", "Y", "Z"));
646     assertThat(tail).containsExactly("Y", "Z", "a").inOrder();
647   }
648 
testSkip_structurallyModifiedSkipAll()649   public void testSkip_structurallyModifiedSkipAll() throws Exception {
650     Collection<String> set = Sets.newLinkedHashSet();
651     Collections.addAll(set, "a", "b", "c");
652     FluentIterable<String> tail = FluentIterable.from(set).skip(2);
653     set.remove("a");
654     set.remove("b");
655     assertFalse(tail.iterator().hasNext());
656   }
657 
testSkip_structurallyModifiedSkipAllList()658   public void testSkip_structurallyModifiedSkipAllList() throws Exception {
659     List<String> list = Lists.newArrayList("a", "b", "c");
660     FluentIterable<String> tail = FluentIterable.from(list).skip(2);
661     list.subList(0, 2).clear();
662     assertThat(tail).isEmpty();
663   }
664 
testSkip_illegalArgument()665   public void testSkip_illegalArgument() {
666     try {
667       FluentIterable.from(asList("a", "b", "c")).skip(-1);
668       fail("Skipping negative number of elements should throw IllegalArgumentException.");
669     } catch (IllegalArgumentException expected) {
670     }
671   }
672 
testLimit()673   public void testLimit() {
674     Iterable<String> iterable = Lists.newArrayList("foo", "bar", "baz");
675     FluentIterable<String> limited = FluentIterable.from(iterable).limit(2);
676 
677     assertEquals(ImmutableList.of("foo", "bar"), Lists.newArrayList(limited));
678     assertCanIterateAgain(limited);
679     assertEquals("[foo, bar]", limited.toString());
680   }
681 
testLimit_illegalArgument()682   public void testLimit_illegalArgument() {
683     try {
684       FluentIterable<String> unused =
685           FluentIterable.from(Lists.newArrayList("a", "b", "c")).limit(-1);
686       fail("Passing negative number to limit(...) method should throw IllegalArgumentException");
687     } catch (IllegalArgumentException expected) {
688     }
689   }
690 
testIsEmpty()691   public void testIsEmpty() {
692     assertTrue(FluentIterable.<String>from(Collections.<String>emptyList()).isEmpty());
693     assertFalse(FluentIterable.<String>from(Lists.newArrayList("foo")).isEmpty());
694   }
695 
testToList()696   public void testToList() {
697     assertEquals(Lists.newArrayList(1, 2, 3, 4), fluent(1, 2, 3, 4).toList());
698   }
699 
testToList_empty()700   public void testToList_empty() {
701     assertTrue(fluent().toList().isEmpty());
702   }
703 
testToSortedList_withComparator()704   public void testToSortedList_withComparator() {
705     assertEquals(
706         Lists.newArrayList(4, 3, 2, 1),
707         fluent(4, 1, 3, 2).toSortedList(Ordering.<Integer>natural().reverse()));
708   }
709 
testToSortedList_withDuplicates()710   public void testToSortedList_withDuplicates() {
711     assertEquals(
712         Lists.newArrayList(4, 3, 1, 1),
713         fluent(1, 4, 1, 3).toSortedList(Ordering.<Integer>natural().reverse()));
714   }
715 
testToSet()716   public void testToSet() {
717     assertThat(fluent(1, 2, 3, 4).toSet()).containsExactly(1, 2, 3, 4).inOrder();
718   }
719 
testToSet_removeDuplicates()720   public void testToSet_removeDuplicates() {
721     assertThat(fluent(1, 2, 1, 2).toSet()).containsExactly(1, 2).inOrder();
722   }
723 
testToSet_empty()724   public void testToSet_empty() {
725     assertTrue(fluent().toSet().isEmpty());
726   }
727 
testToSortedSet()728   public void testToSortedSet() {
729     assertThat(fluent(1, 4, 2, 3).toSortedSet(Ordering.<Integer>natural().reverse()))
730         .containsExactly(4, 3, 2, 1)
731         .inOrder();
732   }
733 
testToSortedSet_removeDuplicates()734   public void testToSortedSet_removeDuplicates() {
735     assertThat(fluent(1, 4, 1, 3).toSortedSet(Ordering.<Integer>natural().reverse()))
736         .containsExactly(4, 3, 1)
737         .inOrder();
738   }
739 
testToMultiset()740   public void testToMultiset() {
741     assertThat(fluent(1, 2, 1, 3, 2, 4).toMultiset()).containsExactly(1, 1, 2, 2, 3, 4).inOrder();
742   }
743 
testToMultiset_empty()744   public void testToMultiset_empty() {
745     assertThat(fluent().toMultiset()).isEmpty();
746   }
747 
testToMap()748   public void testToMap() {
749     assertThat(fluent(1, 2, 3).toMap(Functions.toStringFunction()).entrySet())
750         .containsExactly(
751             Maps.immutableEntry(1, "1"), Maps.immutableEntry(2, "2"), Maps.immutableEntry(3, "3"))
752         .inOrder();
753   }
754 
testToMap_nullKey()755   public void testToMap_nullKey() {
756     try {
757       fluent(1, null, 2).toMap(Functions.constant("foo"));
758       fail();
759     } catch (NullPointerException expected) {
760     }
761   }
762 
testToMap_nullValue()763   public void testToMap_nullValue() {
764     try {
765       fluent(1, 2, 3).toMap(Functions.constant(null));
766       fail();
767     } catch (NullPointerException expected) {
768     }
769   }
770 
testIndex()771   public void testIndex() {
772     ImmutableListMultimap<Integer, String> expected =
773         ImmutableListMultimap.<Integer, String>builder()
774             .putAll(3, "one", "two")
775             .put(5, "three")
776             .put(4, "four")
777             .build();
778     ImmutableListMultimap<Integer, String> index =
779         FluentIterable.from(asList("one", "two", "three", "four"))
780             .index(
781                 new Function<String, Integer>() {
782                   @Override
783                   public Integer apply(String input) {
784                     return input.length();
785                   }
786                 });
787     assertEquals(expected, index);
788   }
789 
testIndex_nullKey()790   public void testIndex_nullKey() {
791     try {
792       ImmutableListMultimap<Object, Integer> unused =
793           fluent(1, 2, 3).index(Functions.constant(null));
794       fail();
795     } catch (NullPointerException expected) {
796     }
797   }
798 
testIndex_nullValue()799   public void testIndex_nullValue() {
800     try {
801       ImmutableListMultimap<String, Integer> unused =
802           fluent(1, null, 2).index(Functions.constant("foo"));
803       fail();
804     } catch (NullPointerException expected) {
805     }
806   }
807 
testUniqueIndex()808   public void testUniqueIndex() {
809     ImmutableMap<Integer, String> expected = ImmutableMap.of(3, "two", 5, "three", 4, "four");
810     ImmutableMap<Integer, String> index =
811         FluentIterable.from(asList("two", "three", "four"))
812             .uniqueIndex(
813                 new Function<String, Integer>() {
814                   @Override
815                   public Integer apply(String input) {
816                     return input.length();
817                   }
818                 });
819     assertEquals(expected, index);
820   }
821 
testUniqueIndex_duplicateKey()822   public void testUniqueIndex_duplicateKey() {
823     try {
824       ImmutableMap<Integer, String> unused =
825           FluentIterable.from(asList("one", "two", "three", "four"))
826               .uniqueIndex(
827                   new Function<String, Integer>() {
828                     @Override
829                     public Integer apply(String input) {
830                       return input.length();
831                     }
832                   });
833       fail();
834     } catch (IllegalArgumentException expected) {
835     }
836   }
837 
testUniqueIndex_nullKey()838   public void testUniqueIndex_nullKey() {
839     try {
840       fluent(1, 2, 3).uniqueIndex(Functions.constant(null));
841       fail();
842     } catch (NullPointerException expected) {
843     }
844   }
845 
testUniqueIndex_nullValue()846   public void testUniqueIndex_nullValue() {
847     try {
848       ImmutableMap<Object, Integer> unused =
849           fluent(1, null, 2)
850               .uniqueIndex(
851                   new Function<Integer, Object>() {
852                     @Override
853                     public Object apply(@NullableDecl Integer input) {
854                       return String.valueOf(input);
855                     }
856                   });
857       fail();
858     } catch (NullPointerException expected) {
859     }
860   }
861 
testCopyInto_List()862   public void testCopyInto_List() {
863     assertThat(fluent(1, 3, 5).copyInto(Lists.newArrayList(1, 2)))
864         .containsExactly(1, 2, 1, 3, 5)
865         .inOrder();
866   }
867 
testCopyInto_Set()868   public void testCopyInto_Set() {
869     assertThat(fluent(1, 3, 5).copyInto(Sets.newHashSet(1, 2))).containsExactly(1, 2, 3, 5);
870   }
871 
testCopyInto_SetAllDuplicates()872   public void testCopyInto_SetAllDuplicates() {
873     assertThat(fluent(1, 3, 5).copyInto(Sets.newHashSet(1, 2, 3, 5))).containsExactly(1, 2, 3, 5);
874   }
875 
testCopyInto_NonCollection()876   public void testCopyInto_NonCollection() {
877     final ArrayList<Integer> list = Lists.newArrayList(1, 2, 3);
878 
879     final ArrayList<Integer> iterList = Lists.newArrayList(9, 8, 7);
880     Iterable<Integer> iterable =
881         new Iterable<Integer>() {
882           @Override
883           public Iterator<Integer> iterator() {
884             return iterList.iterator();
885           }
886         };
887 
888     assertThat(FluentIterable.from(iterable).copyInto(list))
889         .containsExactly(1, 2, 3, 9, 8, 7)
890         .inOrder();
891   }
892 
testJoin()893   public void testJoin() {
894     assertEquals("2,1,3,4", fluent(2, 1, 3, 4).join(Joiner.on(",")));
895   }
896 
testJoin_empty()897   public void testJoin_empty() {
898     assertEquals("", fluent().join(Joiner.on(",")));
899   }
900 
testGet()901   public void testGet() {
902     assertEquals("a", FluentIterable.from(Lists.newArrayList("a", "b", "c")).get(0));
903     assertEquals("b", FluentIterable.from(Lists.newArrayList("a", "b", "c")).get(1));
904     assertEquals("c", FluentIterable.from(Lists.newArrayList("a", "b", "c")).get(2));
905   }
906 
testGet_outOfBounds()907   public void testGet_outOfBounds() {
908     try {
909       FluentIterable.from(Lists.newArrayList("a", "b", "c")).get(-1);
910       fail();
911     } catch (IndexOutOfBoundsException expected) {
912     }
913 
914     try {
915       FluentIterable.from(Lists.newArrayList("a", "b", "c")).get(3);
916       fail();
917     } catch (IndexOutOfBoundsException expected) {
918     }
919   }
920 
assertCanIterateAgain(Iterable<?> iterable)921   private static void assertCanIterateAgain(Iterable<?> iterable) {
922     for (Object unused : iterable) {
923       // do nothing
924     }
925   }
926 
fluent(Integer... elements)927   private static FluentIterable<Integer> fluent(Integer... elements) {
928     return FluentIterable.from(Lists.newArrayList(elements));
929   }
930 
iterable(String... elements)931   private static Iterable<String> iterable(String... elements) {
932     final List<String> list = asList(elements);
933     return new Iterable<String>() {
934       @Override
935       public Iterator<String> iterator() {
936         return list.iterator();
937       }
938     };
939   }
940 }
941