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 }