1 /* 2 * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @summary Spliterator traversing and splitting tests 27 * @library /lib/testlibrary/bootlib 28 * @modules java.base/jdk.internal.misc 29 * @build java.base/java.util.SpliteratorOfIntDataBuilder 30 * java.base/java.util.SpliteratorTestHelper 31 * @run testng SpliteratorTraversingAndSplittingTest 32 * @run testng/othervm --enable-preview SpliteratorTraversingAndSplittingTest 33 * @bug 8020016 8071477 8072784 8169838 8336672 34 */ 35 36 import jdk.internal.misc.PreviewFeatures; 37 38 import org.testng.annotations.DataProvider; 39 import org.testng.annotations.Test; 40 41 import java.nio.CharBuffer; 42 import java.util.AbstractCollection; 43 import java.util.AbstractList; 44 import java.util.AbstractSet; 45 import java.util.ArrayDeque; 46 import java.util.ArrayList; 47 import java.util.Arrays; 48 import java.util.Collection; 49 import java.util.Collections; 50 import java.util.Comparator; 51 import java.util.HashMap; 52 import java.util.HashSet; 53 import java.util.IdentityHashMap; 54 import java.util.Iterator; 55 import java.util.LinkedHashMap; 56 import java.util.LinkedHashSet; 57 import java.util.LinkedList; 58 import java.util.List; 59 import java.util.ListIterator; 60 import java.util.Map; 61 import java.util.PriorityQueue; 62 import java.util.RandomAccess; 63 import java.util.Set; 64 import java.util.SortedSet; 65 import java.util.Spliterator; 66 import java.util.SpliteratorOfIntDataBuilder; 67 import java.util.SpliteratorTestHelper; 68 import java.util.Spliterators; 69 import java.util.Stack; 70 import java.util.TreeMap; 71 import java.util.TreeSet; 72 import java.util.Vector; 73 import java.util.WeakHashMap; 74 import java.util.concurrent.ArrayBlockingQueue; 75 import java.util.concurrent.ConcurrentHashMap; 76 import java.util.concurrent.ConcurrentLinkedQueue; 77 import java.util.concurrent.ConcurrentSkipListMap; 78 import java.util.concurrent.ConcurrentSkipListSet; 79 import java.util.concurrent.CopyOnWriteArrayList; 80 import java.util.concurrent.CopyOnWriteArraySet; 81 import java.util.concurrent.LinkedBlockingDeque; 82 import java.util.concurrent.LinkedBlockingQueue; 83 import java.util.concurrent.LinkedTransferQueue; 84 import java.util.concurrent.PriorityBlockingQueue; 85 import java.util.function.Consumer; 86 import java.util.function.DoubleConsumer; 87 import java.util.function.Function; 88 import java.util.function.IntConsumer; 89 import java.util.function.LongConsumer; 90 import java.util.function.Supplier; 91 import java.util.function.UnaryOperator; 92 93 public class SpliteratorTraversingAndSplittingTest extends SpliteratorTestHelper { 94 95 private static final List<Integer> SIZES = Arrays.asList(0, 1, 10, 42); 96 97 private static final String LOW = new String(new char[] {Character.MIN_LOW_SURROGATE}); 98 private static final String HIGH = new String(new char[] {Character.MIN_HIGH_SURROGATE}); 99 private static final String HIGH_LOW = HIGH + LOW; 100 private static final String CHAR_HIGH_LOW = "A" + HIGH_LOW; 101 private static final String HIGH_LOW_CHAR = HIGH_LOW + "A"; 102 private static final String CHAR_HIGH_LOW_CHAR = "A" + HIGH_LOW + "A"; 103 104 private static final List<String> STRINGS = generateTestStrings(); 105 106 private static List<String> generateTestStrings() { 107 List<String> strings = new ArrayList<>(); 108 for (int n : Arrays.asList(1, 2, 3, 16, 17)) { 109 strings.add(generate("A", n)); 110 strings.add(generate(LOW, n)); 111 strings.add(generate(HIGH, n)); 112 strings.add(generate(HIGH_LOW, n)); 113 strings.add(generate(CHAR_HIGH_LOW, n)); 114 strings.add(generate(HIGH_LOW_CHAR, n)); 115 strings.add(generate(CHAR_HIGH_LOW_CHAR, n)); 116 } 117 return strings; 118 } 119 120 private static String generate(String s, int n) { 121 StringBuilder sb = new StringBuilder(); 122 for (int i = 0; i < n; i++) { 123 sb.append(s); 124 } 125 return sb.toString(); 126 } 127 128 private static class SpliteratorDataBuilder<T> { 129 List<Object[]> data; 130 131 List<T> exp; 132 133 Map<T, T> mExp; 134 135 SpliteratorDataBuilder(List<Object[]> data, List<T> exp) { 136 this.data = data; 137 this.exp = exp; 138 this.mExp = createMap(exp); 139 } 140 141 Map<T, T> createMap(List<T> l) { 142 Map<T, T> m = new LinkedHashMap<>(); 143 for (T t : l) { 144 m.put(t, t); 145 } 146 return m; 147 } 148 149 void add(String description, Collection<?> expected, Supplier<Spliterator<?>> s) { 150 description = joiner(description).toString(); 151 data.add(new Object[]{description, expected, s}); 152 } 153 154 void add(String description, Supplier<Spliterator<?>> s) { 155 add(description, exp, s); 156 } 157 158 void addCollection(Function<Collection<T>, ? extends Collection<T>> c) { 159 add("new " + c.apply(Collections.<T>emptyList()).getClass().getName() + ".spliterator()", 160 () -> c.apply(exp).spliterator()); 161 } 162 163 void addList(Function<Collection<T>, ? extends List<T>> l) { 164 addCollection(l); 165 addCollection(l.andThen(list -> list.subList(0, list.size()))); 166 } 167 168 void addMap(Function<Map<T, T>, ? extends Map<T, T>> m) { 169 String description = "new " + m.apply(Collections.<T, T>emptyMap()).getClass().getName(); 170 addMap(m, description); 171 } 172 173 void addMap(Function<Map<T, T>, ? extends Map<T, T>> m, String description) { 174 add(description + ".keySet().spliterator()", () -> m.apply(mExp).keySet().spliterator()); 175 add(description + ".values().spliterator()", () -> m.apply(mExp).values().spliterator()); 176 add(description + ".entrySet().spliterator()", mExp.entrySet(), () -> m.apply(mExp).entrySet().spliterator()); 177 } 178 179 StringBuilder joiner(String description) { 180 return new StringBuilder(description). 181 append(" {"). 182 append("size=").append(exp.size()). 183 append("}"); 184 } 185 } 186 187 static Object[][] spliteratorDataProvider; 188 189 @DataProvider(name = "Spliterator<Integer>") 190 public static Object[][] spliteratorDataProvider() { 191 if (spliteratorDataProvider != null) { 192 return spliteratorDataProvider; 193 } 194 195 List<Object[]> data = new ArrayList<>(); 196 for (int size : SIZES) { 197 List<Integer> exp = listIntRange(size); 198 SpliteratorDataBuilder<Integer> db = new SpliteratorDataBuilder<>(data, exp); 199 200 // Direct spliterator methods 201 202 db.add("Spliterators.spliterator(Collection, ...)", 203 () -> Spliterators.spliterator(exp, 0)); 204 205 db.add("Spliterators.spliterator(Iterator, ...)", 206 () -> Spliterators.spliterator(exp.iterator(), exp.size(), 0)); 207 208 db.add("Spliterators.spliteratorUnknownSize(Iterator, ...)", 209 () -> Spliterators.spliteratorUnknownSize(exp.iterator(), 0)); 210 211 db.add("Spliterators.spliterator(Spliterators.iteratorFromSpliterator(Spliterator ), ...)", 212 () -> Spliterators.spliterator(Spliterators.iterator(exp.spliterator()), exp.size(), 0)); 213 214 db.add("Spliterators.spliterator(T[], ...)", 215 () -> Spliterators.spliterator(exp.toArray(new Integer[0]), 0)); 216 217 db.add("Arrays.spliterator(T[], ...)", 218 () -> Arrays.spliterator(exp.toArray(new Integer[0]))); 219 220 class SpliteratorFromIterator extends Spliterators.AbstractSpliterator<Integer> { 221 Iterator<Integer> it; 222 223 SpliteratorFromIterator(Iterator<Integer> it, long est) { 224 super(est, Spliterator.SIZED); 225 this.it = it; 226 } 227 228 @Override 229 public boolean tryAdvance(Consumer<? super Integer> action) { 230 if (action == null) 231 throw new NullPointerException(); 232 if (it.hasNext()) { 233 action.accept(it.next()); 234 return true; 235 } 236 else { 237 return false; 238 } 239 } 240 } 241 db.add("new Spliterators.AbstractSpliterator()", 242 () -> new SpliteratorFromIterator(exp.iterator(), exp.size())); 243 244 // Collections 245 246 // default method implementations 247 248 class AbstractCollectionImpl extends AbstractCollection<Integer> { 249 Collection<Integer> c; 250 251 AbstractCollectionImpl(Collection<Integer> c) { 252 this.c = c; 253 } 254 255 @Override 256 public Iterator<Integer> iterator() { 257 return c.iterator(); 258 } 259 260 @Override 261 public int size() { 262 return c.size(); 263 } 264 } 265 db.addCollection( 266 c -> new AbstractCollectionImpl(c)); 267 268 class AbstractListImpl extends AbstractList<Integer> { 269 List<Integer> l; 270 271 AbstractListImpl(Collection<Integer> c) { 272 this.l = new ArrayList<>(c); 273 } 274 275 @Override 276 public Integer get(int index) { 277 return l.get(index); 278 } 279 280 @Override 281 public int size() { 282 return l.size(); 283 } 284 } 285 db.addCollection( 286 c -> new AbstractListImpl(c)); 287 288 class AbstractSetImpl extends AbstractSet<Integer> { 289 Set<Integer> s; 290 291 AbstractSetImpl(Collection<Integer> c) { 292 this.s = new HashSet<>(c); 293 } 294 295 @Override 296 public Iterator<Integer> iterator() { 297 return s.iterator(); 298 } 299 300 @Override 301 public int size() { 302 return s.size(); 303 } 304 } 305 db.addCollection( 306 c -> new AbstractSetImpl(c)); 307 308 class AbstractSortedSetImpl extends AbstractSet<Integer> implements SortedSet<Integer> { 309 SortedSet<Integer> s; 310 311 AbstractSortedSetImpl(Collection<Integer> c) { 312 this.s = new TreeSet<>(c); 313 } 314 315 @Override 316 public Iterator<Integer> iterator() { 317 return s.iterator(); 318 } 319 320 @Override 321 public int size() { 322 return s.size(); 323 } 324 325 @Override 326 public Comparator<? super Integer> comparator() { 327 return s.comparator(); 328 } 329 330 @Override 331 public SortedSet<Integer> subSet(Integer fromElement, Integer toElement) { 332 return s.subSet(fromElement, toElement); 333 } 334 335 @Override 336 public SortedSet<Integer> headSet(Integer toElement) { 337 return s.headSet(toElement); 338 } 339 340 @Override 341 public SortedSet<Integer> tailSet(Integer fromElement) { 342 return s.tailSet(fromElement); 343 } 344 345 @Override 346 public Integer first() { 347 return s.first(); 348 } 349 350 @Override 351 public Integer last() { 352 return s.last(); 353 } 354 355 @Override 356 public Spliterator<Integer> spliterator() { 357 return SortedSet.super.spliterator(); 358 } 359 } 360 db.addCollection( 361 c -> new AbstractSortedSetImpl(c)); 362 363 class IterableWrapper implements Iterable<Integer> { 364 final Iterable<Integer> it; 365 366 IterableWrapper(Iterable<Integer> it) { 367 this.it = it; 368 } 369 370 @Override 371 public Iterator<Integer> iterator() { 372 return it.iterator(); 373 } 374 } 375 db.add("new Iterable.spliterator()", 376 () -> new IterableWrapper(exp).spliterator()); 377 378 // 379 380 db.add("Arrays.asList().spliterator()", 381 () -> Spliterators.spliterator(Arrays.asList(exp.toArray(new Integer[0])), 0)); 382 383 db.addList(ArrayList::new); 384 385 db.addList(LinkedList::new); 386 387 db.addList(Vector::new); 388 389 class AbstractRandomAccessListImpl extends AbstractList<Integer> implements RandomAccess { 390 Integer[] ia; 391 392 AbstractRandomAccessListImpl(Collection<Integer> c) { 393 this.ia = c.toArray(new Integer[c.size()]); 394 } 395 396 @Override 397 public Integer get(int index) { 398 return ia[index]; 399 } 400 401 @Override 402 public int size() { 403 return ia.length; 404 } 405 } 406 db.addList(AbstractRandomAccessListImpl::new); 407 408 class RandomAccessListImpl implements List<Integer>, RandomAccess { 409 Integer[] ia; 410 List<Integer> l; 411 412 RandomAccessListImpl(Collection<Integer> c) { 413 this.ia = c.toArray(new Integer[c.size()]); 414 this.l = Arrays.asList(ia); 415 } 416 417 @Override 418 public Integer get(int index) { 419 return ia[index]; 420 } 421 422 @Override 423 public Integer set(int index, Integer element) { 424 throw new UnsupportedOperationException(); 425 } 426 427 @Override 428 public void add(int index, Integer element) { 429 throw new UnsupportedOperationException(); 430 } 431 432 @Override 433 public Integer remove(int index) { 434 throw new UnsupportedOperationException(); 435 } 436 437 @Override 438 public int indexOf(Object o) { 439 return l.indexOf(o); 440 } 441 442 @Override 443 public int lastIndexOf(Object o) { 444 return Arrays.asList(ia).lastIndexOf(o); 445 } 446 447 @Override 448 public ListIterator<Integer> listIterator() { 449 return l.listIterator(); 450 } 451 452 @Override 453 public ListIterator<Integer> listIterator(int index) { 454 return l.listIterator(index); 455 } 456 457 @Override 458 public List<Integer> subList(int fromIndex, int toIndex) { 459 return l.subList(fromIndex, toIndex); 460 } 461 462 @Override 463 public int size() { 464 return ia.length; 465 } 466 467 @Override 468 public boolean isEmpty() { 469 return size() != 0; 470 } 471 472 @Override 473 public boolean contains(Object o) { 474 return l.contains(o); 475 } 476 477 @Override 478 public Iterator<Integer> iterator() { 479 return l.iterator(); 480 } 481 482 @Override 483 public Object[] toArray() { 484 return l.toArray(); 485 } 486 487 @Override 488 public <T> T[] toArray(T[] a) { 489 return l.toArray(a); 490 } 491 492 @Override 493 public boolean add(Integer integer) { 494 throw new UnsupportedOperationException(); 495 } 496 497 @Override 498 public boolean remove(Object o) { 499 throw new UnsupportedOperationException(); 500 } 501 502 @Override 503 public boolean containsAll(Collection<?> c) { 504 return l.containsAll(c); 505 } 506 507 @Override 508 public boolean addAll(Collection<? extends Integer> c) { 509 throw new UnsupportedOperationException(); 510 } 511 512 @Override 513 public boolean addAll(int index, Collection<? extends Integer> c) { 514 throw new UnsupportedOperationException(); 515 } 516 517 @Override 518 public boolean removeAll(Collection<?> c) { 519 throw new UnsupportedOperationException(); 520 } 521 522 @Override 523 public boolean retainAll(Collection<?> c) { 524 throw new UnsupportedOperationException(); 525 } 526 527 @Override 528 public void clear() { 529 throw new UnsupportedOperationException(); 530 } 531 } 532 db.addList(RandomAccessListImpl::new); 533 534 db.addCollection(HashSet::new); 535 536 db.addCollection(LinkedHashSet::new); 537 538 db.addCollection(TreeSet::new); 539 540 541 db.addCollection(c -> { Stack<Integer> s = new Stack<>(); s.addAll(c); return s;}); 542 543 db.addCollection(PriorityQueue::new); 544 545 db.addCollection(ArrayDeque::new); 546 547 548 db.addCollection(ConcurrentSkipListSet::new); 549 550 if (size > 0) { 551 db.addCollection(c -> { 552 ArrayBlockingQueue<Integer> abq = new ArrayBlockingQueue<>(size); 553 abq.addAll(c); 554 return abq; 555 }); 556 } 557 558 db.addCollection(PriorityBlockingQueue::new); 559 560 db.addCollection(LinkedBlockingQueue::new); 561 562 db.addCollection(LinkedTransferQueue::new); 563 564 db.addCollection(ConcurrentLinkedQueue::new); 565 566 db.addCollection(LinkedBlockingDeque::new); 567 568 db.addCollection(CopyOnWriteArrayList::new); 569 570 db.addCollection(CopyOnWriteArraySet::new); 571 572 if (size == 0) { 573 db.addCollection(c -> Collections.<Integer>emptySet()); 574 db.addList(c -> Collections.<Integer>emptyList()); 575 } 576 else if (size == 1) { 577 db.addCollection(c -> Collections.singleton(exp.get(0))); 578 db.addCollection(c -> Collections.singletonList(exp.get(0))); 579 } 580 581 { 582 Integer[] ai = new Integer[size]; 583 Arrays.fill(ai, 1); 584 db.add(String.format("Collections.nCopies(%d, 1)", exp.size()), 585 Arrays.asList(ai), 586 () -> Collections.nCopies(exp.size(), 1).spliterator()); 587 } 588 589 // Collections.synchronized/unmodifiable/checked wrappers 590 db.addCollection(Collections::unmodifiableCollection); 591 db.addCollection(c -> Collections.unmodifiableSet(new HashSet<>(c))); 592 db.addCollection(c -> Collections.unmodifiableSortedSet(new TreeSet<>(c))); 593 db.addList(c -> Collections.unmodifiableList(new ArrayList<>(c))); 594 db.addMap(Collections::unmodifiableMap); 595 db.addMap(m -> Collections.unmodifiableSortedMap(new TreeMap<>(m))); 596 597 db.addCollection(Collections::synchronizedCollection); 598 db.addCollection(c -> Collections.synchronizedSet(new HashSet<>(c))); 599 db.addCollection(c -> Collections.synchronizedSortedSet(new TreeSet<>(c))); 600 db.addList(c -> Collections.synchronizedList(new ArrayList<>(c))); 601 db.addMap(Collections::synchronizedMap); 602 db.addMap(m -> Collections.synchronizedSortedMap(new TreeMap<>(m))); 603 604 db.addCollection(c -> Collections.checkedCollection(c, Integer.class)); 605 db.addCollection(c -> Collections.checkedQueue(new ArrayDeque<>(c), Integer.class)); 606 db.addCollection(c -> Collections.checkedSet(new HashSet<>(c), Integer.class)); 607 db.addCollection(c -> Collections.checkedSortedSet(new TreeSet<>(c), Integer.class)); 608 db.addList(c -> Collections.checkedList(new ArrayList<>(c), Integer.class)); 609 db.addMap(c -> Collections.checkedMap(c, Integer.class, Integer.class)); 610 db.addMap(m -> Collections.checkedSortedMap(new TreeMap<>(m), Integer.class, Integer.class)); 611 612 // Maps 613 614 db.addMap(HashMap::new); 615 616 db.addMap(m -> { 617 // Create a Map ensuring that for large sizes 618 // buckets will contain 2 or more entries 619 HashMap<Integer, Integer> cm = new HashMap<>(1, m.size() + 1); 620 // Don't use putAll which inflates the table by 621 // m.size() * loadFactor, thus creating a very sparse 622 // map for 1000 entries defeating the purpose of this test, 623 // in addition it will cause the split until null test to fail 624 // because the number of valid splits is larger than the 625 // threshold 626 for (Map.Entry<Integer, Integer> e : m.entrySet()) 627 cm.put(e.getKey(), e.getValue()); 628 return cm; 629 }, "new java.util.HashMap(1, size + 1)"); 630 631 db.addMap(LinkedHashMap::new); 632 633 db.addMap(IdentityHashMap::new); 634 635 if (!PreviewFeatures.isEnabled()) { 636 // With --enable-preview, WeakHashmap is not tested with Integer, a value class 637 db.addMap(WeakHashMap::new); 638 639 db.addMap(m -> { 640 // Create a Map ensuring that for large sizes 641 // buckets will consist of 2 or more entries 642 WeakHashMap<Integer, Integer> cm = new WeakHashMap<>(1, m.size() + 1); 643 for (Map.Entry<Integer, Integer> e : m.entrySet()) 644 cm.put(e.getKey(), e.getValue()); 645 return cm; 646 }, "new java.util.WeakHashMap(1, size + 1)"); 647 } 648 649 // @@@ Descending maps etc 650 db.addMap(TreeMap::new); 651 652 db.addMap(ConcurrentHashMap::new); 653 654 db.addMap(ConcurrentSkipListMap::new); 655 656 if (size == 0) { 657 db.addMap(m -> Collections.<Integer, Integer>emptyMap()); 658 } 659 else if (size == 1) { 660 db.addMap(m -> Collections.singletonMap(exp.get(0), exp.get(0))); 661 } 662 } 663 664 return spliteratorDataProvider = data.toArray(new Object[0][]); 665 } 666 667 private static List<Integer> listIntRange(int upTo) { 668 List<Integer> exp = new ArrayList<>(); 669 for (int i = 0; i < upTo; i++) 670 exp.add(i); 671 return Collections.unmodifiableList(exp); 672 } 673 674 @Test(dataProvider = "Spliterator<Integer>") 675 public void testNullPointerException(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) { 676 assertThrowsNPE(() -> s.get().forEachRemaining(null)); 677 assertThrowsNPE(() -> s.get().tryAdvance(null)); 678 } 679 680 @Test(dataProvider = "Spliterator<Integer>") 681 public void testForEach(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) { 682 testForEach(exp, s, UnaryOperator.identity()); 683 } 684 685 @Test(dataProvider = "Spliterator<Integer>") 686 public void testTryAdvance(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) { 687 testTryAdvance(exp, s, UnaryOperator.identity()); 688 } 689 690 @Test(dataProvider = "Spliterator<Integer>") 691 public void testMixedTryAdvanceForEach(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) { 692 testMixedTryAdvanceForEach(exp, s, UnaryOperator.identity()); 693 } 694 695 @Test(dataProvider = "Spliterator<Integer>") 696 public void testMixedTraverseAndSplit(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) { 697 testMixedTraverseAndSplit(exp, s, UnaryOperator.identity()); 698 } 699 700 @Test(dataProvider = "Spliterator<Integer>") 701 public void testSplitAfterFullTraversal(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) { 702 testSplitAfterFullTraversal(s, UnaryOperator.identity()); 703 } 704 705 @Test(dataProvider = "Spliterator<Integer>") 706 public void testSplitOnce(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) { 707 testSplitOnce(exp, s, UnaryOperator.identity()); 708 } 709 710 @Test(dataProvider = "Spliterator<Integer>") 711 public void testSplitSixDeep(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) { 712 testSplitSixDeep(exp, s, UnaryOperator.identity()); 713 } 714 715 @Test(dataProvider = "Spliterator<Integer>") 716 public void testSplitUntilNull(String description, Collection<Integer> exp, Supplier<Spliterator<Integer>> s) { 717 testSplitUntilNull(exp, s, UnaryOperator.identity()); 718 } 719 720 // 721 private static class SpliteratorOfIntCharDataBuilder { 722 List<Object[]> data; 723 724 String s; 725 726 List<Integer> expChars; 727 728 List<Integer> expCodePoints; 729 730 SpliteratorOfIntCharDataBuilder(List<Object[]> data, String s) { 731 this.data = data; 732 this.s = s; 733 this.expChars = transform(s, false); 734 this.expCodePoints = transform(s, true); 735 } 736 737 static List<Integer> transform(String s, boolean toCodePoints) { 738 List<Integer> l = new ArrayList<>(); 739 740 if (!toCodePoints) { 741 for (int i = 0; i < s.length(); i++) { 742 l.add((int) s.charAt(i)); 743 } 744 } 745 else { 746 for (int i = 0; i < s.length();) { 747 char c1 = s.charAt(i++); 748 int cp = c1; 749 if (Character.isHighSurrogate(c1) && i < s.length()) { 750 char c2 = s.charAt(i); 751 if (Character.isLowSurrogate(c2)) { 752 i++; 753 cp = Character.toCodePoint(c1, c2); 754 } 755 } 756 l.add(cp); 757 } 758 } 759 return l; 760 } 761 762 void add(String description, Function<String, CharSequence> f) { 763 description = description.replace("%s", s); 764 { 765 Supplier<Spliterator.OfInt> supplier = () -> f.apply(s).chars().spliterator(); 766 data.add(new Object[]{description + ".chars().spliterator()", expChars, supplier}); 767 } 768 { 769 Supplier<Spliterator.OfInt> supplier = () -> f.apply(s).codePoints().spliterator(); 770 data.add(new Object[]{description + ".codePoints().spliterator()", expCodePoints, supplier}); 771 } 772 } 773 } 774 775 static Object[][] spliteratorOfIntDataProvider; 776 777 @DataProvider(name = "Spliterator.OfInt") 778 public static Object[][] spliteratorOfIntDataProvider() { 779 if (spliteratorOfIntDataProvider != null) { 780 return spliteratorOfIntDataProvider; 781 } 782 783 List<Object[]> data = new ArrayList<>(); 784 for (int size : SIZES) { 785 int exp[] = arrayIntRange(size); 786 SpliteratorOfIntDataBuilder db = new SpliteratorOfIntDataBuilder(data, listIntRange(size)); 787 788 db.add("Spliterators.spliterator(int[], ...)", 789 () -> Spliterators.spliterator(exp, 0)); 790 791 db.add("Arrays.spliterator(int[], ...)", 792 () -> Arrays.spliterator(exp)); 793 794 db.add("Spliterators.spliterator(PrimitiveIterator.OfInt, ...)", 795 () -> Spliterators.spliterator(Spliterators.iterator(Arrays.spliterator(exp)), exp.length, 0)); 796 797 db.add("Spliterators.spliteratorUnknownSize(PrimitiveIterator.OfInt, ...)", 798 () -> Spliterators.spliteratorUnknownSize(Spliterators.iterator(Arrays.spliterator(exp)), 0)); 799 800 class IntSpliteratorFromArray extends Spliterators.AbstractIntSpliterator { 801 int[] a; 802 int index = 0; 803 804 IntSpliteratorFromArray(int[] a) { 805 super(a.length, Spliterator.SIZED); 806 this.a = a; 807 } 808 809 @Override 810 public boolean tryAdvance(IntConsumer action) { 811 if (action == null) 812 throw new NullPointerException(); 813 if (index < a.length) { 814 action.accept(a[index++]); 815 return true; 816 } 817 else { 818 return false; 819 } 820 } 821 } 822 db.add("new Spliterators.AbstractIntAdvancingSpliterator()", 823 () -> new IntSpliteratorFromArray(exp)); 824 } 825 826 // Class for testing default methods 827 class CharSequenceImpl implements CharSequence { 828 final String s; 829 830 public CharSequenceImpl(String s) { 831 this.s = s; 832 } 833 834 @Override 835 public int length() { 836 return s.length(); 837 } 838 839 @Override 840 public char charAt(int index) { 841 return s.charAt(index); 842 } 843 844 @Override 845 public CharSequence subSequence(int start, int end) { 846 return s.subSequence(start, end); 847 } 848 849 @Override 850 public String toString() { 851 return s; 852 } 853 } 854 855 for (String string : STRINGS) { 856 SpliteratorOfIntCharDataBuilder cdb = new SpliteratorOfIntCharDataBuilder(data, string); 857 cdb.add("\"%s\"", s -> s); 858 cdb.add("new CharSequenceImpl(\"%s\")", CharSequenceImpl::new); 859 cdb.add("new StringBuilder(\"%s\")", StringBuilder::new); 860 cdb.add("new StringBuffer(\"%s\")", StringBuffer::new); 861 cdb.add("CharBuffer.wrap(\"%s\".toCharArray())", s -> CharBuffer.wrap(s.toCharArray())); 862 } 863 864 return spliteratorOfIntDataProvider = data.toArray(new Object[0][]); 865 } 866 867 private static int[] arrayIntRange(int upTo) { 868 int[] exp = new int[upTo]; 869 for (int i = 0; i < upTo; i++) 870 exp[i] = i; 871 return exp; 872 } 873 874 @Test(dataProvider = "Spliterator.OfInt") 875 public void testIntNullPointerException(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { 876 assertThrowsNPE(() -> s.get().forEachRemaining((IntConsumer) null)); 877 assertThrowsNPE(() -> s.get().tryAdvance((IntConsumer) null)); 878 } 879 880 @Test(dataProvider = "Spliterator.OfInt") 881 public void testIntForEach(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { 882 testForEach(exp, s, intBoxingConsumer()); 883 } 884 885 @Test(dataProvider = "Spliterator.OfInt") 886 public void testIntTryAdvance(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { 887 testTryAdvance(exp, s, intBoxingConsumer()); 888 } 889 890 @Test(dataProvider = "Spliterator.OfInt") 891 public void testIntMixedTryAdvanceForEach(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { 892 testMixedTryAdvanceForEach(exp, s, intBoxingConsumer()); 893 } 894 895 @Test(dataProvider = "Spliterator.OfInt") 896 public void testIntMixedTraverseAndSplit(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { 897 testMixedTraverseAndSplit(exp, s, intBoxingConsumer()); 898 } 899 900 @Test(dataProvider = "Spliterator.OfInt") 901 public void testIntSplitAfterFullTraversal(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { 902 testSplitAfterFullTraversal(s, intBoxingConsumer()); 903 } 904 905 @Test(dataProvider = "Spliterator.OfInt") 906 public void testIntSplitOnce(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { 907 testSplitOnce(exp, s, intBoxingConsumer()); 908 } 909 910 @Test(dataProvider = "Spliterator.OfInt") 911 public void testIntSplitSixDeep(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { 912 testSplitSixDeep(exp, s, intBoxingConsumer()); 913 } 914 915 @Test(dataProvider = "Spliterator.OfInt") 916 public void testIntSplitUntilNull(String description, Collection<Integer> exp, Supplier<Spliterator.OfInt> s) { 917 testSplitUntilNull(exp, s, intBoxingConsumer()); 918 } 919 920 // 921 922 private static class SpliteratorOfLongDataBuilder { 923 List<Object[]> data; 924 925 List<Long> exp; 926 927 SpliteratorOfLongDataBuilder(List<Object[]> data, List<Long> exp) { 928 this.data = data; 929 this.exp = exp; 930 } 931 932 void add(String description, List<Long> expected, Supplier<Spliterator.OfLong> s) { 933 description = joiner(description).toString(); 934 data.add(new Object[]{description, expected, s}); 935 } 936 937 void add(String description, Supplier<Spliterator.OfLong> s) { 938 add(description, exp, s); 939 } 940 941 StringBuilder joiner(String description) { 942 return new StringBuilder(description). 943 append(" {"). 944 append("size=").append(exp.size()). 945 append("}"); 946 } 947 } 948 949 static Object[][] spliteratorOfLongDataProvider; 950 951 @DataProvider(name = "Spliterator.OfLong") 952 public static Object[][] spliteratorOfLongDataProvider() { 953 if (spliteratorOfLongDataProvider != null) { 954 return spliteratorOfLongDataProvider; 955 } 956 957 List<Object[]> data = new ArrayList<>(); 958 for (int size : SIZES) { 959 long exp[] = arrayLongRange(size); 960 SpliteratorOfLongDataBuilder db = new SpliteratorOfLongDataBuilder(data, listLongRange(size)); 961 962 db.add("Spliterators.spliterator(long[], ...)", 963 () -> Spliterators.spliterator(exp, 0)); 964 965 db.add("Arrays.spliterator(long[], ...)", 966 () -> Arrays.spliterator(exp)); 967 968 db.add("Spliterators.spliterator(PrimitiveIterator.OfLong, ...)", 969 () -> Spliterators.spliterator(Spliterators.iterator(Arrays.spliterator(exp)), exp.length, 0)); 970 971 db.add("Spliterators.spliteratorUnknownSize(PrimitiveIterator.OfLong, ...)", 972 () -> Spliterators.spliteratorUnknownSize(Spliterators.iterator(Arrays.spliterator(exp)), 0)); 973 974 class LongSpliteratorFromArray extends Spliterators.AbstractLongSpliterator { 975 long[] a; 976 int index = 0; 977 978 LongSpliteratorFromArray(long[] a) { 979 super(a.length, Spliterator.SIZED); 980 this.a = a; 981 } 982 983 @Override 984 public boolean tryAdvance(LongConsumer action) { 985 if (action == null) 986 throw new NullPointerException(); 987 if (index < a.length) { 988 action.accept(a[index++]); 989 return true; 990 } 991 else { 992 return false; 993 } 994 } 995 } 996 db.add("new Spliterators.AbstractLongAdvancingSpliterator()", 997 () -> new LongSpliteratorFromArray(exp)); 998 } 999 1000 return spliteratorOfLongDataProvider = data.toArray(new Object[0][]); 1001 } 1002 1003 private static List<Long> listLongRange(int upTo) { 1004 List<Long> exp = new ArrayList<>(); 1005 for (long i = 0; i < upTo; i++) 1006 exp.add(i); 1007 return Collections.unmodifiableList(exp); 1008 } 1009 1010 private static long[] arrayLongRange(int upTo) { 1011 long[] exp = new long[upTo]; 1012 for (int i = 0; i < upTo; i++) 1013 exp[i] = i; 1014 return exp; 1015 } 1016 1017 @Test(dataProvider = "Spliterator.OfLong") 1018 public void testLongNullPointerException(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) { 1019 assertThrowsNPE(() -> s.get().forEachRemaining((LongConsumer) null)); 1020 assertThrowsNPE(() -> s.get().tryAdvance((LongConsumer) null)); 1021 } 1022 1023 @Test(dataProvider = "Spliterator.OfLong") 1024 public void testLongForEach(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) { 1025 testForEach(exp, s, longBoxingConsumer()); 1026 } 1027 1028 @Test(dataProvider = "Spliterator.OfLong") 1029 public void testLongTryAdvance(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) { 1030 testTryAdvance(exp, s, longBoxingConsumer()); 1031 } 1032 1033 @Test(dataProvider = "Spliterator.OfLong") 1034 public void testLongMixedTryAdvanceForEach(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) { 1035 testMixedTryAdvanceForEach(exp, s, longBoxingConsumer()); 1036 } 1037 1038 @Test(dataProvider = "Spliterator.OfLong") 1039 public void testLongMixedTraverseAndSplit(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) { 1040 testMixedTraverseAndSplit(exp, s, longBoxingConsumer()); 1041 } 1042 1043 @Test(dataProvider = "Spliterator.OfLong") 1044 public void testLongSplitAfterFullTraversal(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) { 1045 testSplitAfterFullTraversal(s, longBoxingConsumer()); 1046 } 1047 1048 @Test(dataProvider = "Spliterator.OfLong") 1049 public void testLongSplitOnce(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) { 1050 testSplitOnce(exp, s, longBoxingConsumer()); 1051 } 1052 1053 @Test(dataProvider = "Spliterator.OfLong") 1054 public void testLongSplitSixDeep(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) { 1055 testSplitSixDeep(exp, s, longBoxingConsumer()); 1056 } 1057 1058 @Test(dataProvider = "Spliterator.OfLong") 1059 public void testLongSplitUntilNull(String description, Collection<Long> exp, Supplier<Spliterator.OfLong> s) { 1060 testSplitUntilNull(exp, s, longBoxingConsumer()); 1061 } 1062 1063 // 1064 1065 private static class SpliteratorOfDoubleDataBuilder { 1066 List<Object[]> data; 1067 1068 List<Double> exp; 1069 1070 SpliteratorOfDoubleDataBuilder(List<Object[]> data, List<Double> exp) { 1071 this.data = data; 1072 this.exp = exp; 1073 } 1074 1075 void add(String description, List<Double> expected, Supplier<Spliterator.OfDouble> s) { 1076 description = joiner(description).toString(); 1077 data.add(new Object[]{description, expected, s}); 1078 } 1079 1080 void add(String description, Supplier<Spliterator.OfDouble> s) { 1081 add(description, exp, s); 1082 } 1083 1084 StringBuilder joiner(String description) { 1085 return new StringBuilder(description). 1086 append(" {"). 1087 append("size=").append(exp.size()). 1088 append("}"); 1089 } 1090 } 1091 1092 static Object[][] spliteratorOfDoubleDataProvider; 1093 1094 @DataProvider(name = "Spliterator.OfDouble") 1095 public static Object[][] spliteratorOfDoubleDataProvider() { 1096 if (spliteratorOfDoubleDataProvider != null) { 1097 return spliteratorOfDoubleDataProvider; 1098 } 1099 1100 List<Object[]> data = new ArrayList<>(); 1101 for (int size : SIZES) { 1102 double exp[] = arrayDoubleRange(size); 1103 SpliteratorOfDoubleDataBuilder db = new SpliteratorOfDoubleDataBuilder(data, listDoubleRange(size)); 1104 1105 db.add("Spliterators.spliterator(double[], ...)", 1106 () -> Spliterators.spliterator(exp, 0)); 1107 1108 db.add("Arrays.spliterator(double[], ...)", 1109 () -> Arrays.spliterator(exp)); 1110 1111 db.add("Spliterators.spliterator(PrimitiveIterator.OfDouble, ...)", 1112 () -> Spliterators.spliterator(Spliterators.iterator(Arrays.spliterator(exp)), exp.length, 0)); 1113 1114 db.add("Spliterators.spliteratorUnknownSize(PrimitiveIterator.OfDouble, ...)", 1115 () -> Spliterators.spliteratorUnknownSize(Spliterators.iterator(Arrays.spliterator(exp)), 0)); 1116 1117 class DoubleSpliteratorFromArray extends Spliterators.AbstractDoubleSpliterator { 1118 double[] a; 1119 int index = 0; 1120 1121 DoubleSpliteratorFromArray(double[] a) { 1122 super(a.length, Spliterator.SIZED); 1123 this.a = a; 1124 } 1125 1126 @Override 1127 public boolean tryAdvance(DoubleConsumer action) { 1128 if (action == null) 1129 throw new NullPointerException(); 1130 if (index < a.length) { 1131 action.accept(a[index++]); 1132 return true; 1133 } 1134 else { 1135 return false; 1136 } 1137 } 1138 } 1139 db.add("new Spliterators.AbstractDoubleAdvancingSpliterator()", 1140 () -> new DoubleSpliteratorFromArray(exp)); 1141 } 1142 1143 return spliteratorOfDoubleDataProvider = data.toArray(new Object[0][]); 1144 } 1145 1146 private static List<Double> listDoubleRange(int upTo) { 1147 List<Double> exp = new ArrayList<>(); 1148 for (double i = 0; i < upTo; i++) 1149 exp.add(i); 1150 return Collections.unmodifiableList(exp); 1151 } 1152 1153 private static double[] arrayDoubleRange(int upTo) { 1154 double[] exp = new double[upTo]; 1155 for (int i = 0; i < upTo; i++) 1156 exp[i] = i; 1157 return exp; 1158 } 1159 1160 @Test(dataProvider = "Spliterator.OfDouble") 1161 public void testDoubleNullPointerException(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) { 1162 assertThrowsNPE(() -> s.get().forEachRemaining((DoubleConsumer) null)); 1163 assertThrowsNPE(() -> s.get().tryAdvance((DoubleConsumer) null)); 1164 } 1165 1166 @Test(dataProvider = "Spliterator.OfDouble") 1167 public void testDoubleForEach(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) { 1168 testForEach(exp, s, doubleBoxingConsumer()); 1169 } 1170 1171 @Test(dataProvider = "Spliterator.OfDouble") 1172 public void testDoubleTryAdvance(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) { 1173 testTryAdvance(exp, s, doubleBoxingConsumer()); 1174 } 1175 1176 @Test(dataProvider = "Spliterator.OfDouble") 1177 public void testDoubleMixedTryAdvanceForEach(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) { 1178 testMixedTryAdvanceForEach(exp, s, doubleBoxingConsumer()); 1179 } 1180 1181 @Test(dataProvider = "Spliterator.OfDouble") 1182 public void testDoubleMixedTraverseAndSplit(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) { 1183 testMixedTraverseAndSplit(exp, s, doubleBoxingConsumer()); 1184 } 1185 1186 @Test(dataProvider = "Spliterator.OfDouble") 1187 public void testDoubleSplitAfterFullTraversal(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) { 1188 testSplitAfterFullTraversal(s, doubleBoxingConsumer()); 1189 } 1190 1191 @Test(dataProvider = "Spliterator.OfDouble") 1192 public void testDoubleSplitOnce(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) { 1193 testSplitOnce(exp, s, doubleBoxingConsumer()); 1194 } 1195 1196 @Test(dataProvider = "Spliterator.OfDouble") 1197 public void testDoubleSplitSixDeep(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) { 1198 testSplitSixDeep(exp, s, doubleBoxingConsumer()); 1199 } 1200 1201 @Test(dataProvider = "Spliterator.OfDouble") 1202 public void testDoubleSplitUntilNull(String description, Collection<Double> exp, Supplier<Spliterator.OfDouble> s) { 1203 testSplitUntilNull(exp, s, doubleBoxingConsumer()); 1204 } 1205 1206 }