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