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