Home | History | Annotate | Download | only in collect
      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.truth.Truth.assertThat;
     20 import static java.util.Arrays.asList;
     21 
     22 import com.google.common.annotations.GwtCompatible;
     23 import com.google.common.annotations.GwtIncompatible;
     24 import com.google.common.base.Function;
     25 import com.google.common.base.Functions;
     26 import com.google.common.base.Joiner;
     27 import com.google.common.base.Optional;
     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 
     34 import junit.framework.AssertionFailedError;
     35 import junit.framework.TestCase;
     36 
     37 import java.util.ArrayList;
     38 import java.util.Collection;
     39 import java.util.Collections;
     40 import java.util.Iterator;
     41 import java.util.List;
     42 import java.util.Set;
     43 import java.util.SortedSet;
     44 
     45 import javax.annotation.Nullable;
     46 
     47 /**
     48  * Unit test for {@link FluentIterable}.
     49  *
     50  * @author Marcin Mikosik
     51  */
     52 @GwtCompatible(emulated = true)
     53 public class FluentIterableTest extends TestCase {
     54 
     55   @GwtIncompatible("NullPointerTester")
     56   public void testNullPointerExceptions() {
     57     NullPointerTester tester = new NullPointerTester();
     58     tester.testAllPublicStaticMethods(FluentIterable.class);
     59   }
     60 
     61   public void testFrom() {
     62     assertEquals(ImmutableList.of(1, 2, 3, 4),
     63         Lists.newArrayList(FluentIterable.from(ImmutableList.of(1, 2, 3, 4))));
     64   }
     65 
     66   @SuppressWarnings("deprecation") // test of deprecated method
     67   public void testFrom_alreadyFluentIterable() {
     68     FluentIterable<Integer> iterable = FluentIterable.from(asList(1));
     69     assertSame(iterable, FluentIterable.from(iterable));
     70   }
     71 
     72   public void testOfArray() {
     73     assertEquals(ImmutableList.of("1", "2", "3", "4"),
     74         Lists.newArrayList(FluentIterable.of(new Object[] {"1", "2", "3", "4"})));
     75   }
     76 
     77   public void testSize1Collection() {
     78     assertEquals(1, FluentIterable.from(asList("a")).size());
     79   }
     80 
     81   public void testSize2NonCollection() {
     82     Iterable<Integer> iterable = new Iterable<Integer>() {
     83       @Override
     84       public Iterator<Integer> iterator() {
     85         return asList(0, 1).iterator();
     86       }
     87     };
     88     assertEquals(2, FluentIterable.from(iterable).size());
     89   }
     90 
     91   public void testSize_collectionDoesntIterate() {
     92     List<Integer> nums = asList(1, 2, 3, 4, 5);
     93     List<Integer> collection = new ArrayList<Integer>(nums) {
     94       @Override public Iterator<Integer> iterator() {
     95         throw new AssertionFailedError("Don't iterate me!");
     96       }
     97     };
     98     assertEquals(5, FluentIterable.from(collection).size());
     99   }
    100 
    101   public void testContains_nullSetYes() {
    102     Iterable<String> set = Sets.newHashSet("a", null, "b");
    103     assertTrue(FluentIterable.from(set).contains(null));
    104   }
    105 
    106   public void testContains_nullSetNo() {
    107     Iterable<String> set = ImmutableSortedSet.of("a", "b");
    108     assertFalse(FluentIterable.from(set).contains(null));
    109   }
    110 
    111   public void testContains_nullIterableYes() {
    112     Iterable<String> iterable = iterable("a", null, "b");
    113     assertTrue(FluentIterable.from(iterable).contains(null));
    114   }
    115 
    116   public void testContains_nullIterableNo() {
    117     Iterable<String> iterable = iterable("a", "b");
    118     assertFalse(FluentIterable.from(iterable).contains(null));
    119   }
    120 
    121   public void testContains_nonNullSetYes() {
    122     Iterable<String> set = Sets.newHashSet("a", null, "b");
    123     assertTrue(FluentIterable.from(set).contains("b"));
    124   }
    125 
    126   public void testContains_nonNullSetNo() {
    127     Iterable<String> set = Sets.newHashSet("a", "b");
    128     assertFalse(FluentIterable.from(set).contains("c"));
    129   }
    130 
    131   public void testContains_nonNullIterableYes() {
    132     Iterable<String> set = iterable("a", null, "b");
    133     assertTrue(FluentIterable.from(set).contains("b"));
    134   }
    135 
    136   public void testContains_nonNullIterableNo() {
    137     Iterable<String> iterable = iterable("a", "b");
    138     assertFalse(FluentIterable.from(iterable).contains("c"));
    139   }
    140 
    141   public void testCycle() {
    142     FluentIterable<String> cycle = FluentIterable.from(asList("a", "b")).cycle();
    143 
    144     int howManyChecked = 0;
    145     for (String string : cycle) {
    146       String expected = (howManyChecked % 2 == 0) ? "a" : "b";
    147       assertEquals(expected, string);
    148       if (howManyChecked++ == 5) {
    149         break;
    150       }
    151     }
    152 
    153     // We left the last iterator pointing to "b". But a new iterator should
    154     // always point to "a".
    155     assertEquals("a", cycle.iterator().next());
    156   }
    157 
    158   public void testCycle_removingAllElementsStopsCycle() {
    159     FluentIterable<Integer> cycle = fluent(1, 2).cycle();
    160     Iterator<Integer> iterator = cycle.iterator();
    161     iterator.next();
    162     iterator.remove();
    163     iterator.next();
    164     iterator.remove();
    165     assertFalse(iterator.hasNext());
    166     assertFalse(cycle.iterator().hasNext());
    167   }
    168 
    169   public void testAppend() {
    170     FluentIterable<Integer> result =
    171         FluentIterable.<Integer>from(asList(1, 2, 3)).append(Lists.newArrayList(4, 5, 6));
    172     assertEquals(asList(1, 2, 3, 4, 5, 6), Lists.newArrayList(result));
    173     assertEquals("[1, 2, 3, 4, 5, 6]", result.toString());
    174 
    175     result = FluentIterable.<Integer>from(asList(1, 2, 3)).append(4, 5, 6);
    176     assertEquals(asList(1, 2, 3, 4, 5, 6), Lists.newArrayList(result));
    177     assertEquals("[1, 2, 3, 4, 5, 6]", result.toString());
    178   }
    179 
    180   public void testAppend_emptyList() {
    181     FluentIterable<Integer> result =
    182         FluentIterable.<Integer>from(asList(1, 2, 3)).append(Lists.<Integer>newArrayList());
    183     assertEquals(asList(1, 2, 3), Lists.newArrayList(result));
    184   }
    185 
    186   @SuppressWarnings("ReturnValueIgnored")
    187   public void testAppend_nullPointerException() {
    188     try {
    189       FluentIterable.<Integer>from(asList(1, 2)).append((List<Integer>) null);
    190       fail("Appending null iterable should throw NPE.");
    191     } catch (NullPointerException expected) {
    192     }
    193   }
    194 
    195   /*
    196    * Tests for partition(int size) method.
    197    */
    198 
    199   /*
    200    * Tests for partitionWithPadding(int size) method.
    201    */
    202 
    203   public void testFilter() {
    204     FluentIterable<String> filtered =
    205         FluentIterable.from(asList("foo", "bar")).filter(Predicates.equalTo("foo"));
    206 
    207     List<String> expected = Collections.singletonList("foo");
    208     List<String> actual = Lists.newArrayList(filtered);
    209     assertEquals(expected, actual);
    210     assertCanIterateAgain(filtered);
    211     assertEquals("[foo]", filtered.toString());
    212   }
    213 
    214   private static class TypeA {}
    215   private interface TypeB {}
    216   private static class HasBoth extends TypeA implements TypeB {}
    217 
    218   @GwtIncompatible("Iterables.filter(Iterable, Class)")
    219   public void testFilterByType() throws Exception {
    220     HasBoth hasBoth = new HasBoth();
    221     FluentIterable<TypeA> alist =
    222         FluentIterable.from(asList(new TypeA(), new TypeA(), hasBoth, new TypeA()));
    223     Iterable<TypeB> blist = alist.filter(TypeB.class);
    224     assertThat(blist).iteratesAs(hasBoth);
    225   }
    226 
    227   public void testAnyMatch() {
    228     ArrayList<String> list = Lists.newArrayList();
    229     FluentIterable<String> iterable = FluentIterable.<String>from(list);
    230     Predicate<String> predicate = Predicates.equalTo("pants");
    231 
    232     assertFalse(iterable.anyMatch(predicate));
    233     list.add("cool");
    234     assertFalse(iterable.anyMatch(predicate));
    235     list.add("pants");
    236     assertTrue(iterable.anyMatch(predicate));
    237   }
    238 
    239   public void testAllMatch() {
    240     List<String> list = Lists.newArrayList();
    241     FluentIterable<String> iterable = FluentIterable.<String>from(list);
    242     Predicate<String> predicate = Predicates.equalTo("cool");
    243 
    244     assertTrue(iterable.allMatch(predicate));
    245     list.add("cool");
    246     assertTrue(iterable.allMatch(predicate));
    247     list.add("pants");
    248     assertFalse(iterable.allMatch(predicate));
    249   }
    250 
    251   public void testFirstMatch() {
    252     FluentIterable<String> iterable = FluentIterable.from(Lists.newArrayList("cool", "pants"));
    253     assertEquals(Optional.of("cool"), iterable.firstMatch(Predicates.equalTo("cool")));
    254     assertEquals(Optional.of("pants"), iterable.firstMatch(Predicates.equalTo("pants")));
    255     assertEquals(Optional.absent(), iterable.firstMatch(Predicates.alwaysFalse()));
    256     assertEquals(Optional.of("cool"), iterable.firstMatch(Predicates.alwaysTrue()));
    257   }
    258 
    259   private static final class IntegerValueOfFunction implements Function<String, Integer> {
    260     @Override
    261     public Integer apply(String from) {
    262       return Integer.valueOf(from);
    263     }
    264   }
    265 
    266   public void testTransformWith() {
    267     List<String> input = asList("1", "2", "3");
    268     Iterable<Integer> iterable =
    269         FluentIterable.from(input).transform(new IntegerValueOfFunction());
    270 
    271     assertEquals(asList(1, 2, 3), Lists.newArrayList(iterable));
    272     assertCanIterateAgain(iterable);
    273     assertEquals("[1, 2, 3]", iterable.toString());
    274   }
    275 
    276   public void testTransformWith_poorlyBehavedTransform() {
    277     List<String> input = asList("1", null, "3");
    278     Iterable<Integer> iterable =
    279         FluentIterable.from(input).transform(new IntegerValueOfFunction());
    280 
    281     Iterator<Integer> resultIterator = iterable.iterator();
    282     resultIterator.next();
    283 
    284     try {
    285       resultIterator.next();
    286       fail("Transforming null to int should throw NumberFormatException");
    287     } catch (NumberFormatException expected) {
    288     }
    289   }
    290 
    291   private static final class StringValueOfFunction implements Function<Integer, String> {
    292     @Override
    293     public String apply(Integer from) {
    294       return String.valueOf(from);
    295     }
    296   }
    297 
    298   public void testTransformWith_nullFriendlyTransform() {
    299     List<Integer> input = asList(1, 2, null, 3);
    300     Iterable<String> result = FluentIterable.from(input).transform(new StringValueOfFunction());
    301 
    302     assertEquals(asList("1", "2", "null", "3"), Lists.newArrayList(result));
    303   }
    304 
    305   private static final class RepeatedStringValueOfFunction
    306       implements Function<Integer, List<String>> {
    307     @Override
    308     public List<String> apply(Integer from) {
    309       String value = String.valueOf(from);
    310       return ImmutableList.of(value, value);
    311     }
    312   }
    313 
    314   public void testTransformAndConcat() {
    315     List<Integer> input = asList(1, 2, 3);
    316     Iterable<String> result =
    317         FluentIterable.from(input).transformAndConcat(new RepeatedStringValueOfFunction());
    318     assertEquals(asList("1", "1", "2", "2", "3", "3"), Lists.newArrayList(result));
    319   }
    320 
    321   private static final class RepeatedStringValueOfWildcardFunction
    322       implements Function<Integer, List<? extends String>> {
    323     @Override
    324     public List<String> apply(Integer from) {
    325       String value = String.valueOf(from);
    326       return ImmutableList.of(value, value);
    327     }
    328   }
    329 
    330   public void testTransformAndConcat_wildcardFunctionGenerics() {
    331     List<Integer> input = asList(1, 2, 3);
    332     FluentIterable.from(input).transformAndConcat(new RepeatedStringValueOfWildcardFunction());
    333   }
    334 
    335   public void testFirst_list() {
    336     List<String> list = Lists.newArrayList("a", "b", "c");
    337     assertEquals("a", FluentIterable.from(list).first().get());
    338   }
    339 
    340   public void testFirst_null() {
    341     List<String> list = Lists.newArrayList(null, "a", "b");
    342     try {
    343       FluentIterable.from(list).first();
    344       fail();
    345     } catch (NullPointerException expected) {
    346     }
    347   }
    348 
    349   public void testFirst_emptyList() {
    350     List<String> list = Collections.emptyList();
    351     assertEquals(Optional.absent(), FluentIterable.from(list).first());
    352   }
    353 
    354   public void testFirst_sortedSet() {
    355     SortedSet<String> sortedSet = ImmutableSortedSet.of("b", "c", "a");
    356     assertEquals("a", FluentIterable.from(sortedSet).first().get());
    357   }
    358 
    359   public void testFirst_emptySortedSet() {
    360     SortedSet<String> sortedSet = ImmutableSortedSet.of();
    361     assertEquals(Optional.absent(), FluentIterable.from(sortedSet).first());
    362   }
    363 
    364   public void testFirst_iterable() {
    365     Set<String> set = ImmutableSet.of("a", "b", "c");
    366     assertEquals("a", FluentIterable.from(set).first().get());
    367   }
    368 
    369   public void testFirst_emptyIterable() {
    370     Set<String> set = Sets.newHashSet();
    371     assertEquals(Optional.absent(), FluentIterable.from(set).first());
    372   }
    373 
    374   public void testLast_list() {
    375     List<String> list = Lists.newArrayList("a", "b", "c");
    376     assertEquals("c", FluentIterable.from(list).last().get());
    377   }
    378 
    379   public void testLast_null() {
    380     List<String> list = Lists.newArrayList("a", "b", null);
    381     try {
    382       FluentIterable.from(list).last();
    383       fail();
    384     } catch (NullPointerException expected) {
    385     }
    386   }
    387 
    388   public void testLast_emptyList() {
    389     List<String> list = Collections.emptyList();
    390     assertEquals(Optional.absent(), FluentIterable.from(list).last());
    391   }
    392 
    393   public void testLast_sortedSet() {
    394     SortedSet<String> sortedSet = ImmutableSortedSet.of("b", "c", "a");
    395     assertEquals("c", FluentIterable.from(sortedSet).last().get());
    396   }
    397 
    398   public void testLast_emptySortedSet() {
    399     SortedSet<String> sortedSet = ImmutableSortedSet.of();
    400     assertEquals(Optional.absent(), FluentIterable.from(sortedSet).last());
    401   }
    402 
    403   public void testLast_iterable() {
    404     Set<String> set = ImmutableSet.of("a", "b", "c");
    405     assertEquals("c", FluentIterable.from(set).last().get());
    406   }
    407 
    408   public void testLast_emptyIterable() {
    409     Set<String> set = Sets.newHashSet();
    410     assertEquals(Optional.absent(), FluentIterable.from(set).last());
    411   }
    412 
    413   public void testSkip_simple() {
    414     Collection<String> set = ImmutableSet.of("a", "b", "c", "d", "e");
    415     assertEquals(Lists.newArrayList("c", "d", "e"),
    416         Lists.newArrayList(FluentIterable.from(set).skip(2)));
    417     assertEquals("[c, d, e]", FluentIterable.from(set).skip(2).toString());
    418   }
    419 
    420   public void testSkip_simpleList() {
    421     Collection<String> list = Lists.newArrayList("a", "b", "c", "d", "e");
    422     assertEquals(Lists.newArrayList("c", "d", "e"),
    423         Lists.newArrayList(FluentIterable.from(list).skip(2)));
    424     assertEquals("[c, d, e]", FluentIterable.from(list).skip(2).toString());
    425   }
    426 
    427   public void testSkip_pastEnd() {
    428     Collection<String> set = ImmutableSet.of("a", "b");
    429     assertEquals(Collections.emptyList(), Lists.newArrayList(FluentIterable.from(set).skip(20)));
    430   }
    431 
    432   public void testSkip_pastEndList() {
    433     Collection<String> list = Lists.newArrayList("a", "b");
    434     assertEquals(Collections.emptyList(), Lists.newArrayList(FluentIterable.from(list).skip(20)));
    435   }
    436 
    437   public void testSkip_skipNone() {
    438     Collection<String> set = ImmutableSet.of("a", "b");
    439     assertEquals(Lists.newArrayList("a", "b"),
    440         Lists.newArrayList(FluentIterable.from(set).skip(0)));
    441   }
    442 
    443   public void testSkip_skipNoneList() {
    444     Collection<String> list = Lists.newArrayList("a", "b");
    445     assertEquals(Lists.newArrayList("a", "b"),
    446         Lists.newArrayList(FluentIterable.from(list).skip(0)));
    447   }
    448 
    449   public void testSkip_iterator() throws Exception {
    450     new IteratorTester<Integer>(5, IteratorFeature.MODIFIABLE, Lists.newArrayList(2, 3),
    451         IteratorTester.KnownOrder.KNOWN_ORDER) {
    452       @Override protected Iterator<Integer> newTargetIterator() {
    453         Collection<Integer> collection = Sets.newLinkedHashSet();
    454         Collections.addAll(collection, 1, 2, 3);
    455         return FluentIterable.from(collection).skip(1).iterator();
    456       }
    457     }.test();
    458   }
    459 
    460   public void testSkip_iteratorList() throws Exception {
    461     new IteratorTester<Integer>(5, IteratorFeature.MODIFIABLE, Lists.newArrayList(2, 3),
    462         IteratorTester.KnownOrder.KNOWN_ORDER) {
    463       @Override protected Iterator<Integer> newTargetIterator() {
    464         return FluentIterable.from(Lists.newArrayList(1, 2, 3)).skip(1).iterator();
    465       }
    466     }.test();
    467   }
    468 
    469   public void testSkip_nonStructurallyModifiedList() throws Exception {
    470     List<String> list = Lists.newArrayList("a", "b", "c");
    471     FluentIterable<String> tail = FluentIterable.from(list).skip(1);
    472     Iterator<String> tailIterator = tail.iterator();
    473     list.set(2, "c2");
    474     assertEquals("b", tailIterator.next());
    475     assertEquals("c2", tailIterator.next());
    476     assertFalse(tailIterator.hasNext());
    477   }
    478 
    479   public void testSkip_structurallyModifiedSkipSome() throws Exception {
    480     Collection<String> set = Sets.newLinkedHashSet();
    481     Collections.addAll(set, "a", "b", "c");
    482     FluentIterable<String> tail = FluentIterable.from(set).skip(1);
    483     set.remove("b");
    484     set.addAll(Lists.newArrayList("X", "Y", "Z"));
    485     assertThat(tail).iteratesAs("c", "X", "Y", "Z");
    486   }
    487 
    488   public void testSkip_structurallyModifiedSkipSomeList() throws Exception {
    489     List<String> list = Lists.newArrayList("a", "b", "c");
    490     FluentIterable<String> tail = FluentIterable.from(list).skip(1);
    491     list.subList(1, 3).clear();
    492     list.addAll(0, Lists.newArrayList("X", "Y", "Z"));
    493     assertThat(tail).iteratesAs("Y", "Z", "a");
    494   }
    495 
    496   public void testSkip_structurallyModifiedSkipAll() throws Exception {
    497     Collection<String> set = Sets.newLinkedHashSet();
    498     Collections.addAll(set, "a", "b", "c");
    499     FluentIterable<String> tail = FluentIterable.from(set).skip(2);
    500     set.remove("a");
    501     set.remove("b");
    502     assertFalse(tail.iterator().hasNext());
    503   }
    504 
    505   public void testSkip_structurallyModifiedSkipAllList() throws Exception {
    506     List<String> list = Lists.newArrayList("a", "b", "c");
    507     FluentIterable<String> tail = FluentIterable.from(list).skip(2);
    508     list.subList(0, 2).clear();
    509     assertThat(tail).isEmpty();
    510   }
    511 
    512   @SuppressWarnings("ReturnValueIgnored")
    513   public void testSkip_illegalArgument() {
    514     try {
    515       FluentIterable.from(asList("a", "b", "c")).skip(-1);
    516       fail("Skipping negative number of elements should throw IllegalArgumentException.");
    517     } catch (IllegalArgumentException expected) {
    518     }
    519   }
    520 
    521   public void testLimit() {
    522     Iterable<String> iterable = Lists.newArrayList("foo", "bar", "baz");
    523     FluentIterable<String> limited = FluentIterable.from(iterable).limit(2);
    524 
    525     assertEquals(ImmutableList.of("foo", "bar"), Lists.newArrayList(limited));
    526     assertCanIterateAgain(limited);
    527     assertEquals("[foo, bar]", limited.toString());
    528   }
    529 
    530   @SuppressWarnings("ReturnValueIgnored")
    531   public void testLimit_illegalArgument() {
    532     try {
    533       FluentIterable.from(Lists.newArrayList("a", "b", "c")).limit(-1);
    534       fail("Passing negative number to limit(...) method should throw IllegalArgumentException");
    535     } catch (IllegalArgumentException expected) {
    536     }
    537   }
    538 
    539   public void testIsEmpty() {
    540     assertTrue(FluentIterable.<String>from(Collections.<String>emptyList()).isEmpty());
    541     assertFalse(FluentIterable.<String>from(Lists.newArrayList("foo")).isEmpty());
    542   }
    543 
    544   public void testToList() {
    545     assertEquals(Lists.newArrayList(1, 2, 3, 4), fluent(1, 2, 3, 4).toList());
    546   }
    547 
    548   public void testToList_empty() {
    549     assertTrue(fluent().toList().isEmpty());
    550   }
    551 
    552   public void testToSortedList_withComparator() {
    553     assertEquals(Lists.newArrayList(4, 3, 2, 1),
    554         fluent(4, 1, 3, 2).toSortedList(Ordering.<Integer>natural().reverse()));
    555   }
    556 
    557   public void testToSortedList_withDuplicates() {
    558     assertEquals(Lists.newArrayList(4, 3, 1, 1),
    559         fluent(1, 4, 1, 3).toSortedList(Ordering.<Integer>natural().reverse()));
    560   }
    561 
    562   public void testToSet() {
    563     assertThat(fluent(1, 2, 3, 4).toSet()).has().exactly(1, 2, 3, 4).inOrder();
    564   }
    565 
    566   public void testToSet_removeDuplicates() {
    567     assertThat(fluent(1, 2, 1, 2).toSet()).has().exactly(1, 2).inOrder();
    568   }
    569 
    570   public void testToSet_empty() {
    571     assertTrue(fluent().toSet().isEmpty());
    572   }
    573 
    574   public void testToSortedSet() {
    575     assertThat(fluent(1, 4, 2, 3).toSortedSet(Ordering.<Integer>natural().reverse()))
    576         .has().exactly(4, 3, 2, 1).inOrder();
    577   }
    578 
    579   public void testToSortedSet_removeDuplicates() {
    580     assertThat(fluent(1, 4, 1, 3).toSortedSet(Ordering.<Integer>natural().reverse()))
    581         .has().exactly(4, 3, 1).inOrder();
    582   }
    583 
    584   public void testToMap() {
    585     assertThat(fluent(1, 2, 3).toMap(Functions.toStringFunction()).entrySet())
    586         .has().exactly(
    587             Maps.immutableEntry(1, "1"),
    588             Maps.immutableEntry(2, "2"),
    589             Maps.immutableEntry(3, "3")).inOrder();
    590   }
    591 
    592   public void testToMap_nullKey() {
    593     try {
    594       fluent(1, null, 2).toMap(Functions.constant("foo"));
    595       fail();
    596     } catch (NullPointerException expected) {
    597     }
    598   }
    599 
    600   public void testToMap_nullValue() {
    601     try {
    602       fluent(1, 2, 3).toMap(Functions.constant(null));
    603       fail();
    604     } catch (NullPointerException expected) {
    605     }
    606   }
    607 
    608   public void testIndex() {
    609     ImmutableListMultimap<Integer, String> expected =
    610         ImmutableListMultimap.<Integer, String>builder()
    611             .putAll(3, "one", "two")
    612             .put(5, "three")
    613             .put(4, "four")
    614             .build();
    615     ImmutableListMultimap<Integer, String> index =
    616         FluentIterable.from(asList("one", "two", "three", "four")).index(
    617             new Function<String, Integer>() {
    618               @Override
    619               public Integer apply(String input) {
    620                 return input.length();
    621               }
    622             });
    623     assertEquals(expected, index);
    624   }
    625 
    626   public void testIndex_nullKey() {
    627     try {
    628       fluent(1, 2, 3).index(Functions.constant(null));
    629       fail();
    630     } catch (NullPointerException expected) {
    631     }
    632   }
    633 
    634   public void testIndex_nullValue() {
    635     try {
    636       fluent(1, null, 2).index(Functions.constant("foo"));
    637       fail();
    638     } catch (NullPointerException expected) {
    639     }
    640   }
    641 
    642   public void testUniqueIndex() {
    643     ImmutableMap<Integer, String> expected =
    644         ImmutableMap.of(3, "two", 5, "three", 4, "four");
    645     ImmutableMap<Integer, String> index =
    646         FluentIterable.from(asList("two", "three", "four")).uniqueIndex(
    647             new Function<String, Integer>() {
    648               @Override
    649               public Integer apply(String input) {
    650                 return input.length();
    651               }
    652             });
    653     assertEquals(expected, index);
    654   }
    655 
    656   public void testUniqueIndex_duplicateKey() {
    657     try {
    658       FluentIterable.from(asList("one", "two", "three", "four")).uniqueIndex(
    659           new Function<String, Integer>() {
    660             @Override
    661             public Integer apply(String input) {
    662               return input.length();
    663             }
    664           });
    665       fail();
    666     } catch (IllegalArgumentException expected) {
    667     }
    668   }
    669 
    670   public void testUniqueIndex_nullKey() {
    671     try {
    672       fluent(1, 2, 3).uniqueIndex(Functions.constant(null));
    673       fail();
    674     } catch (NullPointerException expected) {
    675     }
    676   }
    677 
    678   public void testUniqueIndex_nullValue() {
    679     try {
    680       fluent(1, null, 2).uniqueIndex(new Function<Integer, Object>() {
    681         @Override
    682         public Object apply(@Nullable Integer input) {
    683           return String.valueOf(input);
    684         }
    685       });
    686       fail();
    687     } catch (NullPointerException expected) {
    688     }
    689   }
    690 
    691   public void testCopyInto_List() {
    692     assertThat(fluent(1, 3, 5).copyInto(Lists.newArrayList(1, 2)))
    693         .has().exactly(1, 2, 1, 3, 5).inOrder();
    694   }
    695 
    696   public void testCopyInto_Set() {
    697     assertThat(fluent(1, 3, 5).copyInto(Sets.newHashSet(1, 2)))
    698         .has().exactly(1, 2, 3, 5);
    699   }
    700 
    701   public void testCopyInto_SetAllDuplicates() {
    702     assertThat(fluent(1, 3, 5).copyInto(Sets.newHashSet(1, 2, 3, 5)))
    703         .has().exactly(1, 2, 3, 5);
    704   }
    705 
    706   public void testCopyInto_NonCollection() {
    707     final ArrayList<Integer> list = Lists.newArrayList(1, 2, 3);
    708 
    709     final ArrayList<Integer> iterList = Lists.newArrayList(9, 8, 7);
    710     Iterable<Integer> iterable = new Iterable<Integer>() {
    711       @Override
    712       public Iterator<Integer> iterator() {
    713         return iterList.iterator();
    714       }
    715     };
    716 
    717     assertThat(FluentIterable.from(iterable).copyInto(list))
    718         .has().exactly(1, 2, 3, 9, 8, 7).inOrder();
    719   }
    720 
    721   public void testJoin() {
    722     assertEquals("2,1,3,4", fluent(2, 1, 3, 4).join(Joiner.on(",")));
    723   }
    724 
    725   public void testJoin_empty() {
    726     assertEquals("", fluent().join(Joiner.on(",")));
    727   }
    728 
    729   public void testGet() {
    730     assertEquals("a", FluentIterable
    731         .from(Lists.newArrayList("a", "b", "c")).get(0));
    732     assertEquals("b", FluentIterable
    733         .from(Lists.newArrayList("a", "b", "c")).get(1));
    734     assertEquals("c", FluentIterable
    735         .from(Lists.newArrayList("a", "b", "c")).get(2));
    736   }
    737 
    738   public void testGet_outOfBounds() {
    739     try {
    740       FluentIterable.from(Lists.newArrayList("a", "b", "c")).get(-1);
    741       fail();
    742     } catch (IndexOutOfBoundsException expected) {
    743     }
    744 
    745     try {
    746       FluentIterable.from(Lists.newArrayList("a", "b", "c")).get(3);
    747       fail();
    748     } catch (IndexOutOfBoundsException expected) {
    749     }
    750   }
    751 
    752   private static void assertCanIterateAgain(Iterable<?> iterable) {
    753     for (@SuppressWarnings("unused") Object obj : iterable) {
    754     }
    755   }
    756 
    757   private static FluentIterable<Integer> fluent(Integer... elements) {
    758     return FluentIterable.from(Lists.newArrayList(elements));
    759   }
    760 
    761   private static Iterable<String> iterable(String... elements) {
    762     final List<String> list = asList(elements);
    763     return new Iterable<String>() {
    764       @Override
    765       public Iterator<String> iterator() {
    766         return list.iterator();
    767       }
    768     };
    769   }
    770 }
    771