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