1 /* 2 * Copyright (c) 2012, 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 package java.util; 24 25 import java.util.function.*; 26 import java.util.stream.LambdaTestHelpers; 27 28 import static org.testng.Assert.*; 29 import static org.testng.Assert.assertEquals; 30 import static org.testng.Assert.fail; 31 32 /** 33 * Assertion methods for spliterators, to be called from other tests 34 */ 35 public class SpliteratorTestHelper { 36 37 public interface ContentAsserter<T> { 38 void assertContents(Collection<T> actual, Collection<T> expected, boolean isOrdered); 39 } 40 41 private static ContentAsserter<Object> DEFAULT_CONTENT_ASSERTER 42 = SpliteratorTestHelper::assertContents; 43 44 @SuppressWarnings("unchecked") 45 private static <T> ContentAsserter<T> defaultContentAsserter() { 46 return (ContentAsserter<T>) DEFAULT_CONTENT_ASSERTER; 47 } 48 49 public static void testSpliterator(Supplier<Spliterator<Integer>> supplier) { 50 testSpliterator(supplier, defaultContentAsserter()); 51 } 52 53 public static void testSpliterator(Supplier<Spliterator<Integer>> supplier, 54 ContentAsserter<Integer> asserter) { 55 testSpliterator(supplier, (Consumer<Integer> b) -> b, asserter); 56 } 57 58 public static void testIntSpliterator(Supplier<Spliterator.OfInt> supplier) { 59 testIntSpliterator(supplier, defaultContentAsserter()); 60 } 61 62 public static void testIntSpliterator(Supplier<Spliterator.OfInt> supplier, 63 ContentAsserter<Integer> asserter) { 64 testSpliterator(supplier, intBoxingConsumer(), asserter); 65 } 66 67 public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier) { 68 testLongSpliterator(supplier, defaultContentAsserter()); 69 } 70 71 public static void testLongSpliterator(Supplier<Spliterator.OfLong> supplier, 72 ContentAsserter<Long> asserter) { 73 testSpliterator(supplier, longBoxingConsumer(), asserter); 74 } 75 76 public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier) { 77 testDoubleSpliterator(supplier, defaultContentAsserter()); 78 } 79 80 public static void testDoubleSpliterator(Supplier<Spliterator.OfDouble> supplier, 81 ContentAsserter<Double> asserter) { 82 testSpliterator(supplier, doubleBoxingConsumer(), asserter); 83 } 84 85 public static UnaryOperator<Consumer<Integer>> intBoxingConsumer() { 86 class BoxingAdapter implements Consumer<Integer>, IntConsumer { 87 private final Consumer<Integer> b; 88 89 BoxingAdapter(Consumer<Integer> b) { 90 this.b = b; 91 } 92 93 @Override 94 public void accept(Integer value) { 95 throw new IllegalStateException(); 96 } 97 98 @Override 99 public void accept(int value) { 100 b.accept(value); 101 } 102 } 103 104 return b -> new BoxingAdapter(b); 105 } 106 107 public static UnaryOperator<Consumer<Long>> longBoxingConsumer() { 108 class BoxingAdapter implements Consumer<Long>, LongConsumer { 109 private final Consumer<Long> b; 110 111 BoxingAdapter(Consumer<Long> b) { 112 this.b = b; 113 } 114 115 @Override 116 public void accept(Long value) { 117 throw new IllegalStateException(); 118 } 119 120 @Override 121 public void accept(long value) { 122 b.accept(value); 123 } 124 } 125 126 return b -> new BoxingAdapter(b); 127 } 128 129 public static UnaryOperator<Consumer<Double>> doubleBoxingConsumer() { 130 class BoxingAdapter implements Consumer<Double>, DoubleConsumer { 131 private final Consumer<Double> b; 132 133 BoxingAdapter(Consumer<Double> b) { 134 this.b = b; 135 } 136 137 @Override 138 public void accept(Double value) { 139 throw new IllegalStateException(); 140 } 141 142 @Override 143 public void accept(double value) { 144 b.accept(value); 145 } 146 } 147 148 return b -> new BoxingAdapter(b); 149 } 150 151 public static <T, S extends Spliterator<T>> void testSpliterator(Supplier<S> supplier, 152 UnaryOperator<Consumer<T>> boxingAdapter, 153 ContentAsserter<T> asserter) { 154 ArrayList<T> fromForEach = new ArrayList<>(); 155 Spliterator<T> spliterator = supplier.get(); 156 Consumer<T> addToFromForEach = boxingAdapter.apply(fromForEach::add); 157 spliterator.forEachRemaining(addToFromForEach); 158 159 Collection<T> exp = Collections.unmodifiableList(fromForEach); 160 161 testNullPointerException(supplier); 162 testForEach(exp, supplier, boxingAdapter, asserter); 163 testTryAdvance(exp, supplier, boxingAdapter, asserter); 164 testMixedTryAdvanceForEach(exp, supplier, boxingAdapter, asserter); 165 testMixedTraverseAndSplit(exp, supplier, boxingAdapter, asserter); 166 testSplitAfterFullTraversal(supplier, boxingAdapter); 167 testSplitOnce(exp, supplier, boxingAdapter, asserter); 168 testSplitSixDeep(exp, supplier, boxingAdapter, asserter); 169 testSplitUntilNull(exp, supplier, boxingAdapter, asserter); 170 } 171 172 public static <T, S extends Spliterator<T>> void testForEach( 173 Collection<T> exp, 174 Supplier<S> supplier, 175 UnaryOperator<Consumer<T>> boxingAdapter) { 176 testForEach(exp, supplier, boxingAdapter, defaultContentAsserter()); 177 } 178 179 public static <T, S extends Spliterator<T>> void testTryAdvance( 180 Collection<T> exp, 181 Supplier<S> supplier, 182 UnaryOperator<Consumer<T>> boxingAdapter) { 183 testTryAdvance(exp, supplier, boxingAdapter, defaultContentAsserter()); 184 } 185 186 public static <T, S extends Spliterator<T>> void testMixedTryAdvanceForEach( 187 Collection<T> exp, 188 Supplier<S> supplier, 189 UnaryOperator<Consumer<T>> boxingAdapter) { 190 testMixedTryAdvanceForEach(exp, supplier, boxingAdapter, defaultContentAsserter()); 191 } 192 193 public static <T, S extends Spliterator<T>> void testMixedTraverseAndSplit( 194 Collection<T> exp, 195 Supplier<S> supplier, 196 UnaryOperator<Consumer<T>> boxingAdapter) { 197 testMixedTraverseAndSplit(exp, supplier, boxingAdapter, defaultContentAsserter()); 198 } 199 200 public static <T, S extends Spliterator<T>> void testSplitOnce( 201 Collection<T> exp, 202 Supplier<S> supplier, 203 UnaryOperator<Consumer<T>> boxingAdapter) { 204 testSplitOnce(exp, supplier, boxingAdapter, defaultContentAsserter()); 205 } 206 207 public static <T, S extends Spliterator<T>> void testSplitSixDeep( 208 Collection<T> exp, 209 Supplier<S> supplier, 210 UnaryOperator<Consumer<T>> boxingAdapter) { 211 testSplitSixDeep(exp, supplier, boxingAdapter, defaultContentAsserter()); 212 } 213 214 public static <T, S extends Spliterator<T>> void testSplitUntilNull( 215 Collection<T> exp, 216 Supplier<S> supplier, 217 UnaryOperator<Consumer<T>> boxingAdapter) { 218 testSplitUntilNull(exp, supplier, boxingAdapter, defaultContentAsserter()); 219 } 220 221 private static <T, S extends Spliterator<T>> void testNullPointerException(Supplier<S> s) { 222 S sp = s.get(); 223 // Have to check instances and use casts to avoid tripwire messages and 224 // directly test the primitive methods 225 if (sp instanceof Spliterator.OfInt) { 226 Spliterator.OfInt psp = (Spliterator.OfInt) sp; 227 executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((IntConsumer) null)); 228 executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((IntConsumer) null)); 229 } 230 else if (sp instanceof Spliterator.OfLong) { 231 Spliterator.OfLong psp = (Spliterator.OfLong) sp; 232 executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((LongConsumer) null)); 233 executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((LongConsumer) null)); 234 } 235 else if (sp instanceof Spliterator.OfDouble) { 236 Spliterator.OfDouble psp = (Spliterator.OfDouble) sp; 237 executeAndCatch(NullPointerException.class, () -> psp.forEachRemaining((DoubleConsumer) null)); 238 executeAndCatch(NullPointerException.class, () -> psp.tryAdvance((DoubleConsumer) null)); 239 } 240 else { 241 executeAndCatch(NullPointerException.class, () -> sp.forEachRemaining(null)); 242 executeAndCatch(NullPointerException.class, () -> sp.tryAdvance(null)); 243 } 244 } 245 246 private static <T, S extends Spliterator<T>> void testForEach( 247 Collection<T> exp, 248 Supplier<S> supplier, 249 UnaryOperator<Consumer<T>> boxingAdapter, 250 ContentAsserter<T> asserter) { 251 S spliterator = supplier.get(); 252 long sizeIfKnown = spliterator.getExactSizeIfKnown(); 253 boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); 254 255 ArrayList<T> fromForEach = new ArrayList<>(); 256 spliterator = supplier.get(); 257 Consumer<T> addToFromForEach = boxingAdapter.apply(fromForEach::add); 258 spliterator.forEachRemaining(addToFromForEach); 259 260 // Assert that forEach now produces no elements 261 spliterator.forEachRemaining(boxingAdapter.apply( 262 e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); 263 // Assert that tryAdvance now produce no elements 264 spliterator.tryAdvance(boxingAdapter.apply( 265 e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); 266 267 // assert that size, tryAdvance, and forEach are consistent 268 if (sizeIfKnown >= 0) { 269 assertEquals(sizeIfKnown, exp.size()); 270 } 271 if (exp.contains(null)) { 272 assertTrue(fromForEach.contains(null)); 273 } 274 assertEquals(fromForEach.size(), exp.size()); 275 276 asserter.assertContents(fromForEach, exp, isOrdered); 277 } 278 279 private static <T, S extends Spliterator<T>> void testTryAdvance( 280 Collection<T> exp, 281 Supplier<S> supplier, 282 UnaryOperator<Consumer<T>> boxingAdapter, 283 ContentAsserter<T> asserter) { 284 S spliterator = supplier.get(); 285 long sizeIfKnown = spliterator.getExactSizeIfKnown(); 286 boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); 287 288 spliterator = supplier.get(); 289 ArrayList<T> fromTryAdvance = new ArrayList<>(); 290 Consumer<T> addToFromTryAdvance = boxingAdapter.apply(fromTryAdvance::add); 291 while (spliterator.tryAdvance(addToFromTryAdvance)) { } 292 293 // Assert that forEach now produces no elements 294 spliterator.forEachRemaining(boxingAdapter.apply( 295 e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); 296 // Assert that tryAdvance now produce no elements 297 spliterator.tryAdvance(boxingAdapter.apply( 298 e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); 299 300 // assert that size, tryAdvance, and forEach are consistent 301 if (sizeIfKnown >= 0) { 302 assertEquals(sizeIfKnown, exp.size()); 303 } 304 assertEquals(fromTryAdvance.size(), exp.size()); 305 306 asserter.assertContents(fromTryAdvance, exp, isOrdered); 307 } 308 309 private static <T, S extends Spliterator<T>> void testMixedTryAdvanceForEach( 310 Collection<T> exp, 311 Supplier<S> supplier, 312 UnaryOperator<Consumer<T>> boxingAdapter, 313 ContentAsserter<T> asserter) { 314 S spliterator = supplier.get(); 315 long sizeIfKnown = spliterator.getExactSizeIfKnown(); 316 boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); 317 318 // tryAdvance first few elements, then forEach rest 319 ArrayList<T> dest = new ArrayList<>(); 320 spliterator = supplier.get(); 321 Consumer<T> addToDest = boxingAdapter.apply(dest::add); 322 for (int i = 0; i < 10 && spliterator.tryAdvance(addToDest); i++) { } 323 spliterator.forEachRemaining(addToDest); 324 325 // Assert that forEach now produces no elements 326 spliterator.forEachRemaining(boxingAdapter.apply( 327 e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); 328 // Assert that tryAdvance now produce no elements 329 spliterator.tryAdvance(boxingAdapter.apply( 330 e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); 331 332 if (sizeIfKnown >= 0) { 333 assertEquals(sizeIfKnown, dest.size()); 334 } 335 assertEquals(dest.size(), exp.size()); 336 337 asserter.assertContents(dest, exp, isOrdered); 338 } 339 340 private static <T, S extends Spliterator<T>> void testMixedTraverseAndSplit( 341 Collection<T> exp, 342 Supplier<S> supplier, 343 UnaryOperator<Consumer<T>> boxingAdapter, 344 ContentAsserter<T> asserter) { 345 S spliterator = supplier.get(); 346 long sizeIfKnown = spliterator.getExactSizeIfKnown(); 347 boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); 348 349 // tryAdvance first few elements, then forEach rest 350 ArrayList<T> dest = new ArrayList<>(); 351 spliterator = supplier.get(); 352 Consumer<T> b = boxingAdapter.apply(dest::add); 353 354 Spliterator<T> spl1, spl2, spl3; 355 spliterator.tryAdvance(b); 356 spl2 = spliterator.trySplit(); 357 if (spl2 != null) { 358 spl2.tryAdvance(b); 359 spl1 = spl2.trySplit(); 360 if (spl1 != null) { 361 spl1.tryAdvance(b); 362 spl1.forEachRemaining(b); 363 } 364 spl2.tryAdvance(b); 365 spl2.forEachRemaining(b); 366 } 367 spliterator.tryAdvance(b); 368 spl3 = spliterator.trySplit(); 369 if (spl3 != null) { 370 spl3.tryAdvance(b); 371 spl3.forEachRemaining(b); 372 } 373 spliterator.tryAdvance(b); 374 spliterator.forEachRemaining(b); 375 376 if (sizeIfKnown >= 0) { 377 assertEquals(sizeIfKnown, dest.size()); 378 } 379 assertEquals(dest.size(), exp.size()); 380 381 asserter.assertContents(dest, exp, isOrdered); 382 } 383 384 public static <T, S extends Spliterator<T>> void testSplitAfterFullTraversal( 385 Supplier<S> supplier, 386 UnaryOperator<Consumer<T>> boxingAdapter) { 387 // Full traversal using tryAdvance 388 Spliterator<T> spliterator = supplier.get(); 389 while (spliterator.tryAdvance(boxingAdapter.apply(e -> { }))) { } 390 Spliterator<T> split = spliterator.trySplit(); 391 assertNull(split); 392 393 // Full traversal using forEach 394 spliterator = supplier.get(); 395 spliterator.forEachRemaining(boxingAdapter.apply(e -> { })); 396 split = spliterator.trySplit(); 397 assertNull(split); 398 399 // Full traversal using tryAdvance then forEach 400 spliterator = supplier.get(); 401 spliterator.tryAdvance(boxingAdapter.apply(e -> { })); 402 spliterator.forEachRemaining(boxingAdapter.apply(e -> { })); 403 split = spliterator.trySplit(); 404 assertNull(split); 405 } 406 407 private static <T, S extends Spliterator<T>> void testSplitOnce( 408 Collection<T> exp, 409 Supplier<S> supplier, 410 UnaryOperator<Consumer<T>> boxingAdapter, 411 ContentAsserter<T> asserter) { 412 S spliterator = supplier.get(); 413 long sizeIfKnown = spliterator.getExactSizeIfKnown(); 414 boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); 415 416 ArrayList<T> fromSplit = new ArrayList<>(); 417 Spliterator<T> s1 = supplier.get(); 418 Spliterator<T> s2 = s1.trySplit(); 419 long s1Size = s1.getExactSizeIfKnown(); 420 long s2Size = (s2 != null) ? s2.getExactSizeIfKnown() : 0; 421 Consumer<T> addToFromSplit = boxingAdapter.apply(fromSplit::add); 422 if (s2 != null) 423 s2.forEachRemaining(addToFromSplit); 424 s1.forEachRemaining(addToFromSplit); 425 426 if (sizeIfKnown >= 0) { 427 assertEquals(sizeIfKnown, fromSplit.size()); 428 if (s1Size >= 0 && s2Size >= 0) 429 assertEquals(sizeIfKnown, s1Size + s2Size); 430 } 431 432 asserter.assertContents(fromSplit, exp, isOrdered); 433 } 434 435 private static <T, S extends Spliterator<T>> void testSplitSixDeep( 436 Collection<T> exp, 437 Supplier<S> supplier, 438 UnaryOperator<Consumer<T>> boxingAdapter, 439 ContentAsserter<T> asserter) { 440 S spliterator = supplier.get(); 441 boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); 442 443 for (int depth=0; depth < 6; depth++) { 444 List<T> dest = new ArrayList<>(); 445 spliterator = supplier.get(); 446 447 assertSpliterator(spliterator); 448 449 // verify splitting with forEach 450 splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false); 451 asserter.assertContents(dest, exp, isOrdered); 452 453 // verify splitting with tryAdvance 454 dest.clear(); 455 spliterator = supplier.get(); 456 splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), true); 457 asserter.assertContents(dest, exp, isOrdered); 458 } 459 } 460 461 private static <T, S extends Spliterator<T>> 462 void splitSixDeepVisitor(int depth, int curLevel, 463 List<T> dest, S spliterator, UnaryOperator<Consumer<T>> boxingAdapter, 464 int rootCharacteristics, boolean useTryAdvance) { 465 if (curLevel < depth) { 466 long beforeSize = spliterator.getExactSizeIfKnown(); 467 Spliterator<T> split = spliterator.trySplit(); 468 if (split != null) { 469 assertSpliterator(split, rootCharacteristics); 470 assertSpliterator(spliterator, rootCharacteristics); 471 472 if ((rootCharacteristics & Spliterator.SUBSIZED) != 0 && 473 (rootCharacteristics & Spliterator.SIZED) != 0) { 474 assertEquals(beforeSize, split.estimateSize() + spliterator.estimateSize()); 475 } 476 splitSixDeepVisitor(depth, curLevel + 1, dest, split, boxingAdapter, rootCharacteristics, useTryAdvance); 477 } 478 splitSixDeepVisitor(depth, curLevel + 1, dest, spliterator, boxingAdapter, rootCharacteristics, useTryAdvance); 479 } 480 else { 481 long sizeIfKnown = spliterator.getExactSizeIfKnown(); 482 if (useTryAdvance) { 483 Consumer<T> addToDest = boxingAdapter.apply(dest::add); 484 int count = 0; 485 while (spliterator.tryAdvance(addToDest)) { 486 ++count; 487 } 488 489 if (sizeIfKnown >= 0) 490 assertEquals(sizeIfKnown, count); 491 492 // Assert that forEach now produces no elements 493 spliterator.forEachRemaining(boxingAdapter.apply( 494 e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); 495 496 Spliterator<T> split = spliterator.trySplit(); 497 assertNull(split); 498 } 499 else { 500 List<T> leafDest = new ArrayList<>(); 501 Consumer<T> addToLeafDest = boxingAdapter.apply(leafDest::add); 502 spliterator.forEachRemaining(addToLeafDest); 503 504 if (sizeIfKnown >= 0) 505 assertEquals(sizeIfKnown, leafDest.size()); 506 507 // Assert that forEach now produces no elements 508 spliterator.tryAdvance(boxingAdapter.apply( 509 e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); 510 511 Spliterator<T> split = spliterator.trySplit(); 512 assertNull(split); 513 514 dest.addAll(leafDest); 515 } 516 } 517 } 518 519 private static <T, S extends Spliterator<T>> void testSplitUntilNull( 520 Collection<T> exp, 521 Supplier<S> supplier, 522 UnaryOperator<Consumer<T>> boxingAdapter, 523 ContentAsserter<T> asserter) { 524 Spliterator<T> s = supplier.get(); 525 boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED); 526 assertSpliterator(s); 527 528 List<T> splits = new ArrayList<>(); 529 Consumer<T> c = boxingAdapter.apply(splits::add); 530 531 testSplitUntilNull(new SplitNode<T>(c, s)); 532 asserter.assertContents(splits, exp, isOrdered); 533 } 534 535 private static class SplitNode<T> { 536 // Constant for every node 537 final Consumer<T> c; 538 final int rootCharacteristics; 539 540 final Spliterator<T> s; 541 542 SplitNode(Consumer<T> c, Spliterator<T> s) { 543 this(c, s.characteristics(), s); 544 } 545 546 private SplitNode(Consumer<T> c, int rootCharacteristics, Spliterator<T> s) { 547 this.c = c; 548 this.rootCharacteristics = rootCharacteristics; 549 this.s = s; 550 } 551 552 SplitNode<T> fromSplit(Spliterator<T> split) { 553 return new SplitNode<>(c, rootCharacteristics, split); 554 } 555 } 556 557 /** 558 * Set the maximum stack capacity to 0.25MB. This should be more than enough to detect a bad spliterator 559 * while not unduly disrupting test infrastructure given the test data sizes that are used are small. 560 * Note that j.u.c.ForkJoinPool sets the max queue size to 64M (1 << 26). 561 */ 562 private static final int MAXIMUM_STACK_CAPACITY = 1 << 18; // 0.25MB 563 564 private static <T> void testSplitUntilNull(SplitNode<T> e) { 565 // Use an explicit stack to avoid a StackOverflowException when testing a Spliterator 566 // that when repeatedly split produces a right-balanced (and maybe degenerate) tree, or 567 // for a spliterator that is badly behaved. 568 Deque<SplitNode<T>> stack = new ArrayDeque<>(); 569 stack.push(e); 570 571 int iteration = 0; 572 while (!stack.isEmpty()) { 573 assertTrue(iteration++ < MAXIMUM_STACK_CAPACITY, "Exceeded maximum stack modification count of 1 << 18"); 574 575 e = stack.pop(); 576 Spliterator<T> parentAndRightSplit = e.s; 577 578 long parentEstimateSize = parentAndRightSplit.estimateSize(); 579 assertTrue(parentEstimateSize >= 0, 580 String.format("Split size estimate %d < 0", parentEstimateSize)); 581 582 long parentSize = parentAndRightSplit.getExactSizeIfKnown(); 583 Spliterator<T> leftSplit = parentAndRightSplit.trySplit(); 584 if (leftSplit == null) { 585 parentAndRightSplit.forEachRemaining(e.c); 586 continue; 587 } 588 589 assertSpliterator(leftSplit, e.rootCharacteristics); 590 assertSpliterator(parentAndRightSplit, e.rootCharacteristics); 591 592 if (parentEstimateSize != Long.MAX_VALUE && leftSplit.estimateSize() > 0 593 && parentAndRightSplit.estimateSize() > 0) { 594 assertTrue(leftSplit.estimateSize() < parentEstimateSize, 595 String.format("Left split size estimate %d >= parent split size estimate %d", 596 leftSplit.estimateSize(), parentEstimateSize)); 597 assertTrue(parentAndRightSplit.estimateSize() < parentEstimateSize, 598 String.format("Right split size estimate %d >= parent split size estimate %d", 599 leftSplit.estimateSize(), parentEstimateSize)); 600 } 601 else { 602 assertTrue(leftSplit.estimateSize() <= parentEstimateSize, 603 String.format("Left split size estimate %d > parent split size estimate %d", 604 leftSplit.estimateSize(), parentEstimateSize)); 605 assertTrue(parentAndRightSplit.estimateSize() <= parentEstimateSize, 606 String.format("Right split size estimate %d > parent split size estimate %d", 607 leftSplit.estimateSize(), parentEstimateSize)); 608 } 609 610 long leftSize = leftSplit.getExactSizeIfKnown(); 611 long rightSize = parentAndRightSplit.getExactSizeIfKnown(); 612 if (parentSize >= 0 && leftSize >= 0 && rightSize >= 0) 613 assertEquals(parentSize, leftSize + rightSize, 614 String.format("exact left split size %d + exact right split size %d != parent exact split size %d", 615 leftSize, rightSize, parentSize)); 616 617 // Add right side to stack first so left side is popped off first 618 stack.push(e.fromSplit(parentAndRightSplit)); 619 stack.push(e.fromSplit(leftSplit)); 620 } 621 } 622 623 private static void assertSpliterator(Spliterator<?> s, int rootCharacteristics) { 624 if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) { 625 assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED), 626 "Child split is not SUBSIZED when root split is SUBSIZED"); 627 } 628 assertSpliterator(s); 629 } 630 631 private static void assertSpliterator(Spliterator<?> s) { 632 if (s.hasCharacteristics(Spliterator.SUBSIZED)) { 633 assertTrue(s.hasCharacteristics(Spliterator.SIZED)); 634 } 635 if (s.hasCharacteristics(Spliterator.SIZED)) { 636 assertTrue(s.estimateSize() != Long.MAX_VALUE); 637 assertTrue(s.getExactSizeIfKnown() >= 0); 638 } 639 try { 640 s.getComparator(); 641 assertTrue(s.hasCharacteristics(Spliterator.SORTED)); 642 } catch (IllegalStateException e) { 643 assertFalse(s.hasCharacteristics(Spliterator.SORTED)); 644 } 645 } 646 647 private static<T> void assertContents(Collection<T> actual, Collection<T> expected, boolean isOrdered) { 648 if (isOrdered) { 649 assertEquals(actual, expected); 650 } 651 else { 652 LambdaTestHelpers.assertContentsUnordered(actual, expected); 653 } 654 } 655 656 public static void executeAndCatch(Class<? extends Exception> expected, Runnable r) { 657 Exception caught = null; 658 try { 659 r.run(); 660 } 661 catch (Exception e) { 662 caught = e; 663 } 664 665 assertNotNull(caught, 666 String.format("No Exception was thrown, expected an Exception of %s to be thrown", 667 expected.getName())); 668 assertTrue(expected.isInstance(caught), 669 String.format("Exception thrown %s not an instance of %s", 670 caught.getClass().getName(), expected.getName())); 671 } 672 673 public static<U> void mixedTraverseAndSplit(Consumer<U> b, Spliterator<U> splTop) { 674 Spliterator<U> spl1, spl2, spl3; 675 splTop.tryAdvance(b); 676 spl2 = splTop.trySplit(); 677 if (spl2 != null) { 678 spl2.tryAdvance(b); 679 spl1 = spl2.trySplit(); 680 if (spl1 != null) { 681 spl1.tryAdvance(b); 682 spl1.forEachRemaining(b); 683 } 684 spl2.tryAdvance(b); 685 spl2.forEachRemaining(b); 686 } 687 splTop.tryAdvance(b); 688 spl3 = splTop.trySplit(); 689 if (spl3 != null) { 690 spl3.tryAdvance(b); 691 spl3.forEachRemaining(b); 692 } 693 splTop.tryAdvance(b); 694 splTop.forEachRemaining(b); 695 } 696 697 public static void mixedTraverseAndSplit(IntConsumer b, Spliterator.OfInt splTop) { 698 Spliterator.OfInt spl1, spl2, spl3; 699 splTop.tryAdvance(b); 700 spl2 = splTop.trySplit(); 701 if (spl2 != null) { 702 spl2.tryAdvance(b); 703 spl1 = spl2.trySplit(); 704 if (spl1 != null) { 705 spl1.tryAdvance(b); 706 spl1.forEachRemaining(b); 707 } 708 spl2.tryAdvance(b); 709 spl2.forEachRemaining(b); 710 } 711 splTop.tryAdvance(b); 712 spl3 = splTop.trySplit(); 713 if (spl3 != null) { 714 spl3.tryAdvance(b); 715 spl3.forEachRemaining(b); 716 } 717 splTop.tryAdvance(b); 718 splTop.forEachRemaining(b); 719 } 720 721 public static void mixedTraverseAndSplit(LongConsumer b, Spliterator.OfLong splTop) { 722 Spliterator.OfLong spl1, spl2, spl3; 723 splTop.tryAdvance(b); 724 spl2 = splTop.trySplit(); 725 if (spl2 != null) { 726 spl2.tryAdvance(b); 727 spl1 = spl2.trySplit(); 728 if (spl1 != null) { 729 spl1.tryAdvance(b); 730 spl1.forEachRemaining(b); 731 } 732 spl2.tryAdvance(b); 733 spl2.forEachRemaining(b); 734 } 735 splTop.tryAdvance(b); 736 spl3 = splTop.trySplit(); 737 if (spl3 != null) { 738 spl3.tryAdvance(b); 739 spl3.forEachRemaining(b); 740 } 741 splTop.tryAdvance(b); 742 splTop.forEachRemaining(b); 743 } 744 745 public static void mixedTraverseAndSplit(DoubleConsumer b, Spliterator.OfDouble splTop) { 746 Spliterator.OfDouble spl1, spl2, spl3; 747 splTop.tryAdvance(b); 748 spl2 = splTop.trySplit(); 749 if (spl2 != null) { 750 spl2.tryAdvance(b); 751 spl1 = spl2.trySplit(); 752 if (spl1 != null) { 753 spl1.tryAdvance(b); 754 spl1.forEachRemaining(b); 755 } 756 spl2.tryAdvance(b); 757 spl2.forEachRemaining(b); 758 } 759 splTop.tryAdvance(b); 760 spl3 = splTop.trySplit(); 761 if (spl3 != null) { 762 spl3.tryAdvance(b); 763 spl3.forEachRemaining(b); 764 } 765 splTop.tryAdvance(b); 766 splTop.forEachRemaining(b); 767 } 768 769 }