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