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