1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE; 21 import static com.google.common.truth.Truth.assertThat; 22 import static java.util.Arrays.asList; 23 import static java.util.Collections.singletonList; 24 25 import com.google.common.annotations.GwtCompatible; 26 import com.google.common.annotations.GwtIncompatible; 27 import com.google.common.base.Function; 28 import com.google.common.base.Functions; 29 import com.google.common.collect.testing.IteratorTester; 30 import com.google.common.collect.testing.ListTestSuiteBuilder; 31 import com.google.common.collect.testing.TestStringListGenerator; 32 import com.google.common.collect.testing.features.CollectionFeature; 33 import com.google.common.collect.testing.features.CollectionSize; 34 import com.google.common.collect.testing.features.ListFeature; 35 import com.google.common.collect.testing.google.ListGenerators.CharactersOfCharSequenceGenerator; 36 import com.google.common.collect.testing.google.ListGenerators.CharactersOfStringGenerator; 37 import com.google.common.testing.NullPointerTester; 38 import com.google.common.testing.SerializableTester; 39 import java.io.Serializable; 40 import java.util.ArrayList; 41 import java.util.Collection; 42 import java.util.Collections; 43 import java.util.Iterator; 44 import java.util.LinkedList; 45 import java.util.List; 46 import java.util.ListIterator; 47 import java.util.NoSuchElementException; 48 import java.util.RandomAccess; 49 import java.util.concurrent.CopyOnWriteArrayList; 50 import junit.framework.Test; 51 import junit.framework.TestCase; 52 import junit.framework.TestSuite; 53 54 /** 55 * Unit test for {@code Lists}. 56 * 57 * @author Kevin Bourrillion 58 * @author Mike Bostock 59 * @author Jared Levy 60 */ 61 @GwtCompatible(emulated = true) 62 public class ListsTest extends TestCase { 63 64 private static final Collection<Integer> SOME_COLLECTION = asList(0, 1, 1); 65 66 private static final Iterable<Integer> SOME_ITERABLE = new SomeIterable(); 67 68 private static final class RemoveFirstFunction implements Function<String, String>, Serializable { 69 @Override apply(String from)70 public String apply(String from) { 71 return (from.length() == 0) ? from : from.substring(1); 72 } 73 } 74 75 private static class SomeIterable implements Iterable<Integer>, Serializable { 76 @Override iterator()77 public Iterator<Integer> iterator() { 78 return SOME_COLLECTION.iterator(); 79 } 80 81 private static final long serialVersionUID = 0; 82 } 83 84 private static final List<Integer> SOME_LIST = Lists.newArrayList(1, 2, 3, 4); 85 86 private static final List<Integer> SOME_SEQUENTIAL_LIST = Lists.newLinkedList(asList(1, 2, 3, 4)); 87 88 private static final List<String> SOME_STRING_LIST = asList("1", "2", "3", "4"); 89 90 private static final Function<Number, String> SOME_FUNCTION = new SomeFunction(); 91 92 private static class SomeFunction implements Function<Number, String>, Serializable { 93 @Override apply(Number n)94 public String apply(Number n) { 95 return String.valueOf(n); 96 } 97 98 private static final long serialVersionUID = 0; 99 } 100 101 @GwtIncompatible // suite suite()102 public static Test suite() { 103 TestSuite suite = new TestSuite(); 104 suite.addTestSuite(ListsTest.class); 105 106 suite.addTest( 107 ListTestSuiteBuilder.using( 108 new TestStringListGenerator() { 109 @Override 110 protected List<String> create(String[] elements) { 111 String[] rest = new String[elements.length - 1]; 112 System.arraycopy(elements, 1, rest, 0, elements.length - 1); 113 return Lists.asList(elements[0], rest); 114 } 115 }) 116 .named("Lists.asList, 2 parameter") 117 .withFeatures( 118 CollectionSize.SEVERAL, 119 CollectionSize.ONE, 120 CollectionFeature.SERIALIZABLE, 121 CollectionFeature.ALLOWS_NULL_VALUES) 122 .createTestSuite()); 123 124 suite.addTest( 125 ListTestSuiteBuilder.using( 126 new TestStringListGenerator() { 127 @Override 128 protected List<String> create(String[] elements) { 129 String[] rest = new String[elements.length - 2]; 130 System.arraycopy(elements, 2, rest, 0, elements.length - 2); 131 return Lists.asList(elements[0], elements[1], rest); 132 } 133 }) 134 .named("Lists.asList, 3 parameter") 135 .withFeatures( 136 CollectionSize.SEVERAL, 137 CollectionFeature.SERIALIZABLE, 138 CollectionFeature.ALLOWS_NULL_VALUES) 139 .createTestSuite()); 140 141 final Function<String, String> removeFirst = new RemoveFirstFunction(); 142 143 suite.addTest( 144 ListTestSuiteBuilder.using( 145 new TestStringListGenerator() { 146 @Override 147 protected List<String> create(String[] elements) { 148 List<String> fromList = Lists.newArrayList(); 149 for (String element : elements) { 150 fromList.add("q" + checkNotNull(element)); 151 } 152 return Lists.transform(fromList, removeFirst); 153 } 154 }) 155 .named("Lists.transform, random access, no nulls") 156 .withFeatures( 157 CollectionSize.ANY, 158 ListFeature.REMOVE_OPERATIONS, 159 CollectionFeature.SERIALIZABLE, 160 CollectionFeature.ALLOWS_NULL_QUERIES) 161 .createTestSuite()); 162 163 suite.addTest( 164 ListTestSuiteBuilder.using( 165 new TestStringListGenerator() { 166 @Override 167 protected List<String> create(String[] elements) { 168 List<String> fromList = Lists.newLinkedList(); 169 for (String element : elements) { 170 fromList.add("q" + checkNotNull(element)); 171 } 172 return Lists.transform(fromList, removeFirst); 173 } 174 }) 175 .named("Lists.transform, sequential access, no nulls") 176 .withFeatures( 177 CollectionSize.ANY, 178 ListFeature.REMOVE_OPERATIONS, 179 CollectionFeature.SERIALIZABLE, 180 CollectionFeature.ALLOWS_NULL_QUERIES) 181 .createTestSuite()); 182 183 suite.addTest( 184 ListTestSuiteBuilder.using( 185 new TestStringListGenerator() { 186 @Override 187 protected List<String> create(String[] elements) { 188 List<String> fromList = Lists.newArrayList(elements); 189 return Lists.transform(fromList, Functions.<String>identity()); 190 } 191 }) 192 .named("Lists.transform, random access, nulls") 193 .withFeatures( 194 CollectionSize.ANY, 195 ListFeature.REMOVE_OPERATIONS, 196 CollectionFeature.SERIALIZABLE, 197 CollectionFeature.ALLOWS_NULL_VALUES) 198 .createTestSuite()); 199 200 suite.addTest( 201 ListTestSuiteBuilder.using( 202 new TestStringListGenerator() { 203 @Override 204 protected List<String> create(String[] elements) { 205 List<String> fromList = Lists.newLinkedList(asList(elements)); 206 return Lists.transform(fromList, Functions.<String>identity()); 207 } 208 }) 209 .named("Lists.transform, sequential access, nulls") 210 .withFeatures( 211 CollectionSize.ANY, 212 ListFeature.REMOVE_OPERATIONS, 213 CollectionFeature.SERIALIZABLE, 214 CollectionFeature.ALLOWS_NULL_VALUES) 215 .createTestSuite()); 216 217 suite.addTest( 218 ListTestSuiteBuilder.using( 219 new TestStringListGenerator() { 220 @Override 221 protected List<String> create(String[] elements) { 222 List<String> list = Lists.newArrayList(); 223 for (int i = elements.length - 1; i >= 0; i--) { 224 list.add(elements[i]); 225 } 226 return Lists.reverse(list); 227 } 228 }) 229 .named("Lists.reverse[ArrayList]") 230 .withFeatures( 231 CollectionSize.ANY, 232 CollectionFeature.ALLOWS_NULL_VALUES, 233 ListFeature.GENERAL_PURPOSE) 234 .createTestSuite()); 235 236 suite.addTest( 237 ListTestSuiteBuilder.using( 238 new TestStringListGenerator() { 239 @Override 240 protected List<String> create(String[] elements) { 241 String[] reverseElements = new String[elements.length]; 242 for (int i = elements.length - 1, j = 0; i >= 0; i--, j++) { 243 reverseElements[j] = elements[i]; 244 } 245 return Lists.reverse(asList(reverseElements)); 246 } 247 }) 248 .named("Lists.reverse[Arrays.asList]") 249 .withFeatures( 250 CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES, ListFeature.SUPPORTS_SET) 251 .createTestSuite()); 252 253 suite.addTest( 254 ListTestSuiteBuilder.using( 255 new TestStringListGenerator() { 256 @Override 257 protected List<String> create(String[] elements) { 258 List<String> list = Lists.newLinkedList(); 259 for (int i = elements.length - 1; i >= 0; i--) { 260 list.add(elements[i]); 261 } 262 return Lists.reverse(list); 263 } 264 }) 265 .named("Lists.reverse[LinkedList]") 266 .withFeatures( 267 CollectionSize.ANY, 268 CollectionFeature.ALLOWS_NULL_VALUES, 269 ListFeature.GENERAL_PURPOSE) 270 .createTestSuite()); 271 272 suite.addTest( 273 ListTestSuiteBuilder.using( 274 new TestStringListGenerator() { 275 @Override 276 protected List<String> create(String[] elements) { 277 ImmutableList.Builder<String> builder = ImmutableList.builder(); 278 for (int i = elements.length - 1; i >= 0; i--) { 279 builder.add(elements[i]); 280 } 281 return Lists.reverse(builder.build()); 282 } 283 }) 284 .named("Lists.reverse[ImmutableList]") 285 .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES) 286 .createTestSuite()); 287 288 suite.addTest( 289 ListTestSuiteBuilder.using(new CharactersOfStringGenerator()) 290 .named("Lists.charactersOf[String]") 291 .withFeatures( 292 CollectionSize.ANY, 293 CollectionFeature.SERIALIZABLE, 294 CollectionFeature.ALLOWS_NULL_QUERIES) 295 .createTestSuite()); 296 297 suite.addTest( 298 ListTestSuiteBuilder.using(new CharactersOfCharSequenceGenerator()) 299 .named("Lists.charactersOf[CharSequence]") 300 .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_QUERIES) 301 .createTestSuite()); 302 303 return suite; 304 } 305 testCharactersOfIsView()306 public void testCharactersOfIsView() { 307 StringBuilder builder = new StringBuilder("abc"); 308 List<Character> chars = Lists.charactersOf(builder); 309 assertEquals(asList('a', 'b', 'c'), chars); 310 builder.append("def"); 311 assertEquals(asList('a', 'b', 'c', 'd', 'e', 'f'), chars); 312 builder.deleteCharAt(5); 313 assertEquals(asList('a', 'b', 'c', 'd', 'e'), chars); 314 } 315 testNewArrayListEmpty()316 public void testNewArrayListEmpty() { 317 ArrayList<Integer> list = Lists.newArrayList(); 318 assertEquals(Collections.emptyList(), list); 319 } 320 testNewArrayListWithCapacity()321 public void testNewArrayListWithCapacity() { 322 ArrayList<Integer> list = Lists.newArrayListWithCapacity(0); 323 assertEquals(Collections.emptyList(), list); 324 325 ArrayList<Integer> bigger = Lists.newArrayListWithCapacity(256); 326 assertEquals(Collections.emptyList(), bigger); 327 } 328 testNewArrayListWithCapacity_negative()329 public void testNewArrayListWithCapacity_negative() { 330 try { 331 Lists.newArrayListWithCapacity(-1); 332 fail(); 333 } catch (IllegalArgumentException expected) { 334 } 335 } 336 testNewArrayListWithExpectedSize()337 public void testNewArrayListWithExpectedSize() { 338 ArrayList<Integer> list = Lists.newArrayListWithExpectedSize(0); 339 assertEquals(Collections.emptyList(), list); 340 341 ArrayList<Integer> bigger = Lists.newArrayListWithExpectedSize(256); 342 assertEquals(Collections.emptyList(), bigger); 343 } 344 testNewArrayListWithExpectedSize_negative()345 public void testNewArrayListWithExpectedSize_negative() { 346 try { 347 Lists.newArrayListWithExpectedSize(-1); 348 fail(); 349 } catch (IllegalArgumentException expected) { 350 } 351 } 352 testNewArrayListVarArgs()353 public void testNewArrayListVarArgs() { 354 ArrayList<Integer> list = Lists.newArrayList(0, 1, 1); 355 assertEquals(SOME_COLLECTION, list); 356 } 357 testComputeArrayListCapacity()358 public void testComputeArrayListCapacity() { 359 assertEquals(5, Lists.computeArrayListCapacity(0)); 360 assertEquals(13, Lists.computeArrayListCapacity(8)); 361 assertEquals(89, Lists.computeArrayListCapacity(77)); 362 assertEquals(22000005, Lists.computeArrayListCapacity(20000000)); 363 assertEquals(Integer.MAX_VALUE, Lists.computeArrayListCapacity(Integer.MAX_VALUE - 1000)); 364 } 365 testNewArrayListFromCollection()366 public void testNewArrayListFromCollection() { 367 ArrayList<Integer> list = Lists.newArrayList(SOME_COLLECTION); 368 assertEquals(SOME_COLLECTION, list); 369 } 370 testNewArrayListFromIterable()371 public void testNewArrayListFromIterable() { 372 ArrayList<Integer> list = Lists.newArrayList(SOME_ITERABLE); 373 assertEquals(SOME_COLLECTION, list); 374 } 375 testNewArrayListFromIterator()376 public void testNewArrayListFromIterator() { 377 ArrayList<Integer> list = Lists.newArrayList(SOME_COLLECTION.iterator()); 378 assertEquals(SOME_COLLECTION, list); 379 } 380 testNewLinkedListEmpty()381 public void testNewLinkedListEmpty() { 382 LinkedList<Integer> list = Lists.newLinkedList(); 383 assertEquals(Collections.emptyList(), list); 384 } 385 testNewLinkedListFromCollection()386 public void testNewLinkedListFromCollection() { 387 LinkedList<Integer> list = Lists.newLinkedList(SOME_COLLECTION); 388 assertEquals(SOME_COLLECTION, list); 389 } 390 testNewLinkedListFromIterable()391 public void testNewLinkedListFromIterable() { 392 LinkedList<Integer> list = Lists.newLinkedList(SOME_ITERABLE); 393 assertEquals(SOME_COLLECTION, list); 394 } 395 396 @GwtIncompatible // CopyOnWriteArrayList testNewCOWALEmpty()397 public void testNewCOWALEmpty() { 398 CopyOnWriteArrayList<Integer> list = Lists.newCopyOnWriteArrayList(); 399 assertEquals(Collections.emptyList(), list); 400 } 401 402 @GwtIncompatible // CopyOnWriteArrayList testNewCOWALFromIterable()403 public void testNewCOWALFromIterable() { 404 CopyOnWriteArrayList<Integer> list = Lists.newCopyOnWriteArrayList(SOME_ITERABLE); 405 assertEquals(SOME_COLLECTION, list); 406 } 407 408 @GwtIncompatible // NullPointerTester testNullPointerExceptions()409 public void testNullPointerExceptions() { 410 NullPointerTester tester = new NullPointerTester(); 411 tester.testAllPublicStaticMethods(Lists.class); 412 } 413 414 /** 415 * This is just here to illustrate how {@code Arrays#asList} differs from {@code 416 * Lists#newArrayList}. 417 */ testArraysAsList()418 public void testArraysAsList() { 419 List<String> ourWay = Lists.newArrayList("foo", "bar", "baz"); 420 List<String> otherWay = asList("foo", "bar", "baz"); 421 422 // They're logically equal 423 assertEquals(ourWay, otherWay); 424 425 // The result of Arrays.asList() is mutable 426 otherWay.set(0, "FOO"); 427 assertEquals("FOO", otherWay.get(0)); 428 429 // But it can't grow 430 try { 431 otherWay.add("nope"); 432 fail("no exception thrown"); 433 } catch (UnsupportedOperationException expected) { 434 } 435 436 // And it can't shrink 437 try { 438 otherWay.remove(2); 439 fail("no exception thrown"); 440 } catch (UnsupportedOperationException expected) { 441 } 442 } 443 444 @GwtIncompatible // SerializableTester testAsList1()445 public void testAsList1() { 446 List<String> list = Lists.asList("foo", new String[] {"bar", "baz"}); 447 checkFooBarBazList(list); 448 SerializableTester.reserializeAndAssert(list); 449 assertTrue(list instanceof RandomAccess); 450 451 new IteratorTester<String>( 452 5, UNMODIFIABLE, asList("foo", "bar", "baz"), IteratorTester.KnownOrder.KNOWN_ORDER) { 453 @Override 454 protected Iterator<String> newTargetIterator() { 455 return Lists.asList("foo", new String[] {"bar", "baz"}).iterator(); 456 } 457 }.test(); 458 } 459 checkFooBarBazList(List<String> list)460 private void checkFooBarBazList(List<String> list) { 461 assertThat(list).containsExactly("foo", "bar", "baz").inOrder(); 462 assertEquals(3, list.size()); 463 assertIndexIsOutOfBounds(list, -1); 464 assertEquals("foo", list.get(0)); 465 assertEquals("bar", list.get(1)); 466 assertEquals("baz", list.get(2)); 467 assertIndexIsOutOfBounds(list, 3); 468 } 469 testAsList1Small()470 public void testAsList1Small() { 471 List<String> list = Lists.asList("foo", new String[0]); 472 assertThat(list).contains("foo"); 473 assertEquals(1, list.size()); 474 assertIndexIsOutOfBounds(list, -1); 475 assertEquals("foo", list.get(0)); 476 assertIndexIsOutOfBounds(list, 1); 477 assertTrue(list instanceof RandomAccess); 478 479 new IteratorTester<String>( 480 3, UNMODIFIABLE, singletonList("foo"), IteratorTester.KnownOrder.KNOWN_ORDER) { 481 @Override 482 protected Iterator<String> newTargetIterator() { 483 return Lists.asList("foo", new String[0]).iterator(); 484 } 485 }.test(); 486 } 487 testAsList2()488 public void testAsList2() { 489 List<String> list = Lists.asList("foo", "bar", new String[] {"baz"}); 490 checkFooBarBazList(list); 491 assertTrue(list instanceof RandomAccess); 492 493 new IteratorTester<String>( 494 5, UNMODIFIABLE, asList("foo", "bar", "baz"), IteratorTester.KnownOrder.KNOWN_ORDER) { 495 @Override 496 protected Iterator<String> newTargetIterator() { 497 return Lists.asList("foo", "bar", new String[] {"baz"}).iterator(); 498 } 499 }.test(); 500 } 501 502 @GwtIncompatible // SerializableTester testAsList2Small()503 public void testAsList2Small() { 504 List<String> list = Lists.asList("foo", "bar", new String[0]); 505 assertThat(list).containsExactly("foo", "bar").inOrder(); 506 assertEquals(2, list.size()); 507 assertIndexIsOutOfBounds(list, -1); 508 assertEquals("foo", list.get(0)); 509 assertEquals("bar", list.get(1)); 510 assertIndexIsOutOfBounds(list, 2); 511 SerializableTester.reserializeAndAssert(list); 512 assertTrue(list instanceof RandomAccess); 513 514 new IteratorTester<String>( 515 5, UNMODIFIABLE, asList("foo", "bar"), IteratorTester.KnownOrder.KNOWN_ORDER) { 516 @Override 517 protected Iterator<String> newTargetIterator() { 518 return Lists.asList("foo", "bar", new String[0]).iterator(); 519 } 520 }.test(); 521 } 522 assertIndexIsOutOfBounds(List<String> list, int index)523 private static void assertIndexIsOutOfBounds(List<String> list, int index) { 524 try { 525 list.get(index); 526 fail(); 527 } catch (IndexOutOfBoundsException expected) { 528 } 529 } 530 testReverseViewRandomAccess()531 public void testReverseViewRandomAccess() { 532 List<Integer> fromList = Lists.newArrayList(SOME_LIST); 533 List<Integer> toList = Lists.reverse(fromList); 534 assertReverseView(fromList, toList); 535 } 536 testReverseViewSequential()537 public void testReverseViewSequential() { 538 List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST); 539 List<Integer> toList = Lists.reverse(fromList); 540 assertReverseView(fromList, toList); 541 } 542 assertReverseView(List<Integer> fromList, List<Integer> toList)543 private static void assertReverseView(List<Integer> fromList, List<Integer> toList) { 544 /* fromList modifications reflected in toList */ 545 fromList.set(0, 5); 546 assertEquals(asList(4, 3, 2, 5), toList); 547 fromList.add(6); 548 assertEquals(asList(6, 4, 3, 2, 5), toList); 549 fromList.add(2, 9); 550 assertEquals(asList(6, 4, 3, 9, 2, 5), toList); 551 fromList.remove(Integer.valueOf(2)); 552 assertEquals(asList(6, 4, 3, 9, 5), toList); 553 fromList.remove(3); 554 assertEquals(asList(6, 3, 9, 5), toList); 555 556 /* toList modifications reflected in fromList */ 557 toList.remove(0); 558 assertEquals(asList(5, 9, 3), fromList); 559 toList.add(7); 560 assertEquals(asList(7, 5, 9, 3), fromList); 561 toList.add(5); 562 assertEquals(asList(5, 7, 5, 9, 3), fromList); 563 toList.remove(Integer.valueOf(5)); 564 assertEquals(asList(5, 7, 9, 3), fromList); 565 toList.set(1, 8); 566 assertEquals(asList(5, 7, 8, 3), fromList); 567 toList.clear(); 568 assertEquals(Collections.emptyList(), fromList); 569 } 570 571 @SafeVarargs list(E... elements)572 private static <E> List<E> list(E... elements) { 573 return ImmutableList.copyOf(elements); 574 } 575 576 @SuppressWarnings("unchecked") // varargs! testCartesianProduct_binary1x1()577 public void testCartesianProduct_binary1x1() { 578 assertThat(Lists.cartesianProduct(list(1), list(2))).contains(list(1, 2)); 579 } 580 581 @SuppressWarnings("unchecked") // varargs! testCartesianProduct_binary1x2()582 public void testCartesianProduct_binary1x2() { 583 assertThat(Lists.cartesianProduct(list(1), list(2, 3))) 584 .containsExactly(list(1, 2), list(1, 3)) 585 .inOrder(); 586 } 587 588 @SuppressWarnings("unchecked") // varargs! testCartesianProduct_binary2x2()589 public void testCartesianProduct_binary2x2() { 590 assertThat(Lists.cartesianProduct(list(1, 2), list(3, 4))) 591 .containsExactly(list(1, 3), list(1, 4), list(2, 3), list(2, 4)) 592 .inOrder(); 593 } 594 595 @SuppressWarnings("unchecked") // varargs! testCartesianProduct_2x2x2()596 public void testCartesianProduct_2x2x2() { 597 assertThat(Lists.cartesianProduct(list(0, 1), list(0, 1), list(0, 1))) 598 .containsExactly( 599 list(0, 0, 0), 600 list(0, 0, 1), 601 list(0, 1, 0), 602 list(0, 1, 1), 603 list(1, 0, 0), 604 list(1, 0, 1), 605 list(1, 1, 0), 606 list(1, 1, 1)) 607 .inOrder(); 608 } 609 610 @SuppressWarnings("unchecked") // varargs! testCartesianProduct_contains()611 public void testCartesianProduct_contains() { 612 List<List<Integer>> actual = Lists.cartesianProduct(list(1, 2), list(3, 4)); 613 assertTrue(actual.contains(list(1, 3))); 614 assertTrue(actual.contains(list(1, 4))); 615 assertTrue(actual.contains(list(2, 3))); 616 assertTrue(actual.contains(list(2, 4))); 617 assertFalse(actual.contains(list(3, 1))); 618 } 619 testCartesianProduct_indexOf()620 public void testCartesianProduct_indexOf() { 621 List<List<Integer>> actual = Lists.cartesianProduct(list(1, 2), list(3, 4)); 622 assertEquals(actual.indexOf(list(1, 3)), 0); 623 assertEquals(actual.indexOf(list(1, 4)), 1); 624 assertEquals(actual.indexOf(list(2, 3)), 2); 625 assertEquals(actual.indexOf(list(2, 4)), 3); 626 assertEquals(actual.indexOf(list(3, 1)), -1); 627 628 assertEquals(actual.indexOf(list(1)), -1); 629 assertEquals(actual.indexOf(list(1, 1, 1)), -1); 630 } 631 testCartesianProduct_lastIndexOf()632 public void testCartesianProduct_lastIndexOf() { 633 List<List<Integer>> actual = Lists.cartesianProduct(list(1, 1), list(2, 3)); 634 assertThat(actual.lastIndexOf(list(1, 2))).isEqualTo(2); 635 assertThat(actual.lastIndexOf(list(1, 3))).isEqualTo(3); 636 assertThat(actual.lastIndexOf(list(1, 1))).isEqualTo(-1); 637 638 assertThat(actual.lastIndexOf(list(1))).isEqualTo(-1); 639 assertThat(actual.lastIndexOf(list(1, 1, 1))).isEqualTo(-1); 640 } 641 642 @SuppressWarnings("unchecked") // varargs! testCartesianProduct_unrelatedTypes()643 public void testCartesianProduct_unrelatedTypes() { 644 List<Integer> x = list(1, 2); 645 List<String> y = list("3", "4"); 646 647 List<Object> exp1 = list((Object) 1, "3"); 648 List<Object> exp2 = list((Object) 1, "4"); 649 List<Object> exp3 = list((Object) 2, "3"); 650 List<Object> exp4 = list((Object) 2, "4"); 651 652 assertThat(Lists.<Object>cartesianProduct(x, y)) 653 .containsExactly(exp1, exp2, exp3, exp4) 654 .inOrder(); 655 } 656 657 @SuppressWarnings("unchecked") // varargs! testCartesianProductTooBig()658 public void testCartesianProductTooBig() { 659 List<String> list = Collections.nCopies(10000, "foo"); 660 try { 661 Lists.cartesianProduct(list, list, list, list, list); 662 fail("Expected IAE"); 663 } catch (IllegalArgumentException expected) { 664 } 665 } 666 testTransformHashCodeRandomAccess()667 public void testTransformHashCodeRandomAccess() { 668 List<String> list = Lists.transform(SOME_LIST, SOME_FUNCTION); 669 assertEquals(SOME_STRING_LIST.hashCode(), list.hashCode()); 670 } 671 testTransformHashCodeSequential()672 public void testTransformHashCodeSequential() { 673 List<String> list = Lists.transform(SOME_SEQUENTIAL_LIST, SOME_FUNCTION); 674 assertEquals(SOME_STRING_LIST.hashCode(), list.hashCode()); 675 } 676 testTransformModifiableRandomAccess()677 public void testTransformModifiableRandomAccess() { 678 List<Integer> fromList = Lists.newArrayList(SOME_LIST); 679 List<String> list = Lists.transform(fromList, SOME_FUNCTION); 680 assertTransformModifiable(list); 681 } 682 testTransformModifiableSequential()683 public void testTransformModifiableSequential() { 684 List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST); 685 List<String> list = Lists.transform(fromList, SOME_FUNCTION); 686 assertTransformModifiable(list); 687 } 688 assertTransformModifiable(List<String> list)689 private static void assertTransformModifiable(List<String> list) { 690 try { 691 list.add("5"); 692 fail("transformed list is addable"); 693 } catch (UnsupportedOperationException expected) { 694 } 695 list.remove(0); 696 assertEquals(asList("2", "3", "4"), list); 697 list.remove("3"); 698 assertEquals(asList("2", "4"), list); 699 try { 700 list.set(0, "5"); 701 fail("transformed list is setable"); 702 } catch (UnsupportedOperationException expected) { 703 } 704 list.clear(); 705 assertEquals(Collections.emptyList(), list); 706 } 707 testTransformViewRandomAccess()708 public void testTransformViewRandomAccess() { 709 List<Integer> fromList = Lists.newArrayList(SOME_LIST); 710 List<String> toList = Lists.transform(fromList, SOME_FUNCTION); 711 assertTransformView(fromList, toList); 712 } 713 testTransformViewSequential()714 public void testTransformViewSequential() { 715 List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST); 716 List<String> toList = Lists.transform(fromList, SOME_FUNCTION); 717 assertTransformView(fromList, toList); 718 } 719 assertTransformView(List<Integer> fromList, List<String> toList)720 private static void assertTransformView(List<Integer> fromList, List<String> toList) { 721 /* fromList modifications reflected in toList */ 722 fromList.set(0, 5); 723 assertEquals(asList("5", "2", "3", "4"), toList); 724 fromList.add(6); 725 assertEquals(asList("5", "2", "3", "4", "6"), toList); 726 fromList.remove(Integer.valueOf(2)); 727 assertEquals(asList("5", "3", "4", "6"), toList); 728 fromList.remove(2); 729 assertEquals(asList("5", "3", "6"), toList); 730 731 /* toList modifications reflected in fromList */ 732 toList.remove(2); 733 assertEquals(asList(5, 3), fromList); 734 toList.remove("5"); 735 assertEquals(asList(3), fromList); 736 toList.clear(); 737 assertEquals(Collections.emptyList(), fromList); 738 } 739 testTransformRandomAccess()740 public void testTransformRandomAccess() { 741 List<String> list = Lists.transform(SOME_LIST, SOME_FUNCTION); 742 assertTrue(list instanceof RandomAccess); 743 } 744 testTransformSequential()745 public void testTransformSequential() { 746 List<String> list = Lists.transform(SOME_SEQUENTIAL_LIST, SOME_FUNCTION); 747 assertFalse(list instanceof RandomAccess); 748 } 749 testTransformListIteratorRandomAccess()750 public void testTransformListIteratorRandomAccess() { 751 List<Integer> fromList = Lists.newArrayList(SOME_LIST); 752 List<String> list = Lists.transform(fromList, SOME_FUNCTION); 753 assertTransformListIterator(list); 754 } 755 testTransformListIteratorSequential()756 public void testTransformListIteratorSequential() { 757 List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST); 758 List<String> list = Lists.transform(fromList, SOME_FUNCTION); 759 assertTransformListIterator(list); 760 } 761 testTransformPreservesIOOBEsThrownByFunction()762 public void testTransformPreservesIOOBEsThrownByFunction() { 763 try { 764 Lists.transform( 765 ImmutableList.of("foo", "bar"), 766 new Function<String, String>() { 767 @Override 768 public String apply(String input) { 769 throw new IndexOutOfBoundsException(); 770 } 771 }) 772 .toArray(); 773 fail(); 774 } catch (IndexOutOfBoundsException expected) { 775 // success 776 } 777 } 778 assertTransformListIterator(List<String> list)779 private static void assertTransformListIterator(List<String> list) { 780 ListIterator<String> iterator = list.listIterator(1); 781 assertEquals(1, iterator.nextIndex()); 782 assertEquals("2", iterator.next()); 783 assertEquals("3", iterator.next()); 784 assertEquals("4", iterator.next()); 785 assertEquals(4, iterator.nextIndex()); 786 try { 787 iterator.next(); 788 fail("did not detect end of list"); 789 } catch (NoSuchElementException expected) { 790 } 791 assertEquals(3, iterator.previousIndex()); 792 assertEquals("4", iterator.previous()); 793 assertEquals("3", iterator.previous()); 794 assertEquals("2", iterator.previous()); 795 assertTrue(iterator.hasPrevious()); 796 assertEquals("1", iterator.previous()); 797 assertFalse(iterator.hasPrevious()); 798 assertEquals(-1, iterator.previousIndex()); 799 try { 800 iterator.previous(); 801 fail("did not detect beginning of list"); 802 } catch (NoSuchElementException expected) { 803 } 804 iterator.remove(); 805 assertEquals(asList("2", "3", "4"), list); 806 assertFalse(list.isEmpty()); 807 808 // An UnsupportedOperationException or IllegalStateException may occur. 809 try { 810 iterator.add("1"); 811 fail("transformed list iterator is addable"); 812 } catch (UnsupportedOperationException expected) { 813 } catch (IllegalStateException expected) { 814 } 815 try { 816 iterator.set("1"); 817 fail("transformed list iterator is settable"); 818 } catch (UnsupportedOperationException expected) { 819 } catch (IllegalStateException expected) { 820 } 821 } 822 testTransformIteratorRandomAccess()823 public void testTransformIteratorRandomAccess() { 824 List<Integer> fromList = Lists.newArrayList(SOME_LIST); 825 List<String> list = Lists.transform(fromList, SOME_FUNCTION); 826 assertTransformIterator(list); 827 } 828 testTransformIteratorSequential()829 public void testTransformIteratorSequential() { 830 List<Integer> fromList = Lists.newLinkedList(SOME_SEQUENTIAL_LIST); 831 List<String> list = Lists.transform(fromList, SOME_FUNCTION); 832 assertTransformIterator(list); 833 } 834 835 /** 836 * This test depends on the fact that {@code AbstractSequentialList.iterator} transforms the 837 * {@code iterator()} call into a call on {@code listIterator(int)}. This is fine because the 838 * behavior is clearly documented so it's not expected to change. 839 */ testTransformedSequentialIterationUsesBackingListIterationOnly()840 public void testTransformedSequentialIterationUsesBackingListIterationOnly() { 841 List<Integer> randomAccessList = Lists.newArrayList(SOME_SEQUENTIAL_LIST); 842 List<Integer> listIteratorOnlyList = new ListIterationOnlyList<>(randomAccessList); 843 List<String> transform = Lists.transform(listIteratorOnlyList, SOME_FUNCTION); 844 assertTrue( 845 Iterables.elementsEqual(transform, Lists.transform(randomAccessList, SOME_FUNCTION))); 846 } 847 848 private static class ListIterationOnlyList<E> extends ForwardingList<E> { 849 private final List<E> realDelegate; 850 ListIterationOnlyList(List<E> realDelegate)851 private ListIterationOnlyList(List<E> realDelegate) { 852 this.realDelegate = realDelegate; 853 } 854 855 @Override size()856 public int size() { 857 return realDelegate.size(); 858 } 859 860 @Override listIterator(int index)861 public ListIterator<E> listIterator(int index) { 862 return realDelegate.listIterator(index); 863 } 864 865 @Override delegate()866 protected List<E> delegate() { 867 throw new UnsupportedOperationException("This list only supports ListIterator"); 868 } 869 } 870 assertTransformIterator(List<String> list)871 private static void assertTransformIterator(List<String> list) { 872 Iterator<String> iterator = list.iterator(); 873 assertTrue(iterator.hasNext()); 874 assertEquals("1", iterator.next()); 875 assertTrue(iterator.hasNext()); 876 assertEquals("2", iterator.next()); 877 assertTrue(iterator.hasNext()); 878 assertEquals("3", iterator.next()); 879 assertTrue(iterator.hasNext()); 880 assertEquals("4", iterator.next()); 881 assertFalse(iterator.hasNext()); 882 try { 883 iterator.next(); 884 fail("did not detect end of list"); 885 } catch (NoSuchElementException expected) { 886 } 887 iterator.remove(); 888 assertEquals(asList("1", "2", "3"), list); 889 assertFalse(iterator.hasNext()); 890 } 891 testPartition_badSize()892 public void testPartition_badSize() { 893 List<Integer> source = Collections.singletonList(1); 894 try { 895 Lists.partition(source, 0); 896 fail(); 897 } catch (IllegalArgumentException expected) { 898 } 899 } 900 testPartition_empty()901 public void testPartition_empty() { 902 List<Integer> source = Collections.emptyList(); 903 List<List<Integer>> partitions = Lists.partition(source, 1); 904 assertTrue(partitions.isEmpty()); 905 assertEquals(0, partitions.size()); 906 } 907 testPartition_1_1()908 public void testPartition_1_1() { 909 List<Integer> source = Collections.singletonList(1); 910 List<List<Integer>> partitions = Lists.partition(source, 1); 911 assertEquals(1, partitions.size()); 912 assertEquals(Collections.singletonList(1), partitions.get(0)); 913 } 914 testPartition_1_2()915 public void testPartition_1_2() { 916 List<Integer> source = Collections.singletonList(1); 917 List<List<Integer>> partitions = Lists.partition(source, 2); 918 assertEquals(1, partitions.size()); 919 assertEquals(Collections.singletonList(1), partitions.get(0)); 920 } 921 testPartition_2_1()922 public void testPartition_2_1() { 923 List<Integer> source = asList(1, 2); 924 List<List<Integer>> partitions = Lists.partition(source, 1); 925 assertEquals(2, partitions.size()); 926 assertEquals(Collections.singletonList(1), partitions.get(0)); 927 assertEquals(Collections.singletonList(2), partitions.get(1)); 928 } 929 testPartition_3_2()930 public void testPartition_3_2() { 931 List<Integer> source = asList(1, 2, 3); 932 List<List<Integer>> partitions = Lists.partition(source, 2); 933 assertEquals(2, partitions.size()); 934 assertEquals(asList(1, 2), partitions.get(0)); 935 assertEquals(asList(3), partitions.get(1)); 936 } 937 938 @GwtIncompatible // ArrayList.subList doesn't implement RandomAccess in GWT. testPartitionRandomAccessTrue()939 public void testPartitionRandomAccessTrue() { 940 List<Integer> source = asList(1, 2, 3); 941 List<List<Integer>> partitions = Lists.partition(source, 2); 942 943 assertTrue( 944 "partition should be RandomAccess, but not: " + partitions.getClass(), 945 partitions instanceof RandomAccess); 946 947 assertTrue( 948 "partition[0] should be RandomAccess, but not: " + partitions.get(0).getClass(), 949 partitions.get(0) instanceof RandomAccess); 950 951 assertTrue( 952 "partition[1] should be RandomAccess, but not: " + partitions.get(1).getClass(), 953 partitions.get(1) instanceof RandomAccess); 954 } 955 testPartitionRandomAccessFalse()956 public void testPartitionRandomAccessFalse() { 957 List<Integer> source = Lists.newLinkedList(asList(1, 2, 3)); 958 List<List<Integer>> partitions = Lists.partition(source, 2); 959 assertFalse(partitions instanceof RandomAccess); 960 assertFalse(partitions.get(0) instanceof RandomAccess); 961 assertFalse(partitions.get(1) instanceof RandomAccess); 962 } 963 964 // TODO: use the ListTestSuiteBuilder 965 testPartition_view()966 public void testPartition_view() { 967 List<Integer> list = asList(1, 2, 3); 968 List<List<Integer>> partitions = Lists.partition(list, 3); 969 970 // Changes before the partition is retrieved are reflected 971 list.set(0, 3); 972 973 Iterator<List<Integer>> iterator = partitions.iterator(); 974 975 // Changes before the partition is retrieved are reflected 976 list.set(1, 4); 977 978 List<Integer> first = iterator.next(); 979 980 // Changes after are too (unlike Iterables.partition) 981 list.set(2, 5); 982 983 assertEquals(asList(3, 4, 5), first); 984 985 // Changes to a sublist also write through to the original list 986 first.set(1, 6); 987 assertEquals(asList(3, 6, 5), list); 988 } 989 testPartitionSize_1()990 public void testPartitionSize_1() { 991 List<Integer> list = asList(1, 2, 3); 992 assertEquals(1, Lists.partition(list, Integer.MAX_VALUE).size()); 993 assertEquals(1, Lists.partition(list, Integer.MAX_VALUE - 1).size()); 994 } 995 996 @GwtIncompatible // cannot do such a big explicit copy testPartitionSize_2()997 public void testPartitionSize_2() { 998 assertEquals(2, Lists.partition(Collections.nCopies(0x40000001, 1), 0x40000000).size()); 999 } 1000 } 1001