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