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 }