changeset 8102:9b175472f0c6

More spliterator tests; fix bugs in SpinedBuffer spliterators; comment out TreeMap spliterator pending analysis of failures
author briangoetz
date Fri, 12 Apr 2013 16:43:57 -0400
parents 75605b4fdcf9
children f0d92ef92690
files src/share/classes/java/util/TreeMap.java src/share/classes/java/util/stream/SpinedBuffer.java test-ng/bootlib/java/util/stream/DoubleStreamTestScenario.java test-ng/bootlib/java/util/stream/IntStreamTestScenario.java test-ng/bootlib/java/util/stream/LongStreamTestScenario.java test-ng/bootlib/java/util/stream/SpliteratorTestHelper.java test-ng/bootlib/java/util/stream/StreamTestScenario.java
diffstat 7 files changed, 194 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/TreeMap.java	Fri Apr 12 15:30:04 2013 -0400
+++ b/src/share/classes/java/util/TreeMap.java	Fri Apr 12 16:43:57 2013 -0400
@@ -2627,20 +2627,21 @@
         }
 
         public KeySpliterator<K,V> trySplit() {
-            if (est < 0)
-                getEstimate(); // force initialization
-            int d = side;
-            TreeMap.Entry<K,V> e = current, f = fence,
-                    s = ((e == null || e == f) ? null :      // empty
-                         (d == 0)              ? tree.root : // was top
-                         (d >  0)              ? e.right :   // was right
-                         (d <  0 && f != null) ? f.left :    // was left
-                         null);
-            if (s != null && s != e && s != f) {
-                side = 1;
-                return new KeySpliterator<>
-                        (tree, e, current = s, -1, est >>>= 1, expectedModCount);
-            }
+            // @@@ Commented out pending fixes of issues found by StreamSpliteratorTest
+//            if (est < 0)
+//                getEstimate(); // force initialization
+//            int d = side;
+//            TreeMap.Entry<K,V> e = current, f = fence,
+//                    s = ((e == null || e == f) ? null :      // empty
+//                         (d == 0)              ? tree.root : // was top
+//                         (d >  0)              ? e.right :   // was right
+//                         (d <  0 && f != null) ? f.left :    // was left
+//                         null);
+//            if (s != null && s != e && s != f) {
+//                side = 1;
+//                return new KeySpliterator<>
+//                        (tree, e, current = s, -1, est >>>= 1, expectedModCount);
+//            }
             return null;
         }
 
--- a/src/share/classes/java/util/stream/SpinedBuffer.java	Fri Apr 12 15:30:04 2013 -0400
+++ b/src/share/classes/java/util/stream/SpinedBuffer.java	Fri Apr 12 16:43:57 2013 -0400
@@ -326,8 +326,10 @@
             @Override
             public Spliterator<E> trySplit() {
                 if (splSpineIndex < spineIndex) {
-                    Spliterator<E> ret = Arrays.spliterator(spine[splSpineIndex], 0, spine[splSpineIndex].length);
+                    Spliterator<E> ret = Arrays.spliterator(spine[splSpineIndex],
+                                                            splElementIndex, spine[splSpineIndex].length);
                     splChunk = spine[++splSpineIndex];
+                    splElementIndex = 0;
                     return ret;
                 }
                 else if (splSpineIndex == spineIndex) {
@@ -594,8 +596,9 @@
             @Override
             public T_SPLITER trySplit() {
                 if (splSpineIndex < spineIndex) {
-                    T_SPLITER ret = arraySpliterator(spine[splSpineIndex], 0, arrayLength(spine[splSpineIndex]));
+                    T_SPLITER ret = arraySpliterator(spine[splSpineIndex], splElementIndex, arrayLength(spine[splSpineIndex]) - splElementIndex);
                     splChunk = spine[++splSpineIndex];
+                    splElementIndex = 0;
                     return ret;
                 }
                 else if (splSpineIndex == spineIndex) {
--- a/test-ng/bootlib/java/util/stream/DoubleStreamTestScenario.java	Fri Apr 12 15:30:04 2013 -0400
+++ b/test-ng/bootlib/java/util/stream/DoubleStreamTestScenario.java	Fri Apr 12 16:43:57 2013 -0400
@@ -29,6 +29,7 @@
 import java.util.function.Consumer;
 import java.util.function.DoubleConsumer;
 import java.util.function.Function;
+import java.util.function.IntConsumer;
 
 @SuppressWarnings({"rawtypes", "unchecked"})
 public enum DoubleStreamTestScenario implements OpTestCase.BaseStreamTestScenario {
@@ -66,6 +67,13 @@
         }
     },
 
+    // Wrap as stream, spliterate, then split a few times mixing advances with forEach
+    STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) {
+        <T, S_IN extends BaseStream<T, S_IN>> void _run(OpTestCase.TestData<T, S_IN> data, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
+            SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(data.stream()).spliterator());
+        }
+    },
+
     // Wrap as stream, and spliterate then iterate in pull mode
     STREAM_SPLITERATOR_FOREACH(false) {
         <T, S_IN extends BaseStream<T, S_IN>> void _run(OpTestCase.TestData<T, S_IN> data, DoubleConsumer b, Function<S_IN, DoubleStream> m) {
--- a/test-ng/bootlib/java/util/stream/IntStreamTestScenario.java	Fri Apr 12 15:30:04 2013 -0400
+++ b/test-ng/bootlib/java/util/stream/IntStreamTestScenario.java	Fri Apr 12 16:43:57 2013 -0400
@@ -66,6 +66,13 @@
         }
     },
 
+    // Wrap as stream, spliterate, then split a few times mixing advances with forEach
+    STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) {
+        <T, S_IN extends BaseStream<T, S_IN>> void _run(OpTestCase.TestData<T, S_IN> data, IntConsumer b, Function<S_IN, IntStream> m) {
+            SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(data.stream()).spliterator());
+        }
+    },
+
     // Wrap as stream, and spliterate then iterate in pull mode
     STREAM_SPLITERATOR_FOREACH(false) {
         <T, S_IN extends BaseStream<T, S_IN>> void _run(OpTestCase.TestData<T, S_IN> data, IntConsumer b, Function<S_IN, IntStream> m) {
--- a/test-ng/bootlib/java/util/stream/LongStreamTestScenario.java	Fri Apr 12 15:30:04 2013 -0400
+++ b/test-ng/bootlib/java/util/stream/LongStreamTestScenario.java	Fri Apr 12 16:43:57 2013 -0400
@@ -28,6 +28,7 @@
 import java.util.Spliterator;
 import java.util.function.Consumer;
 import java.util.function.Function;
+import java.util.function.IntConsumer;
 import java.util.function.LongConsumer;
 
 @SuppressWarnings({"rawtypes", "unchecked"})
@@ -66,6 +67,13 @@
         }
     },
 
+    // Wrap as stream, spliterate, then split a few times mixing advances with forEach
+    STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) {
+        <T, S_IN extends BaseStream<T, S_IN>> void _run(OpTestCase.TestData<T, S_IN> data, LongConsumer b, Function<S_IN, LongStream> m) {
+            SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(data.stream()).spliterator());
+        }
+    },
+
     // Wrap as stream, and spliterate then iterate in pull mode
     STREAM_SPLITERATOR_FOREACH(false) {
         <T, S_IN extends BaseStream<T, S_IN>> void _run(OpTestCase.TestData<T, S_IN> data, LongConsumer b, Function<S_IN, LongStream> m) {
--- a/test-ng/bootlib/java/util/stream/SpliteratorTestHelper.java	Fri Apr 12 15:30:04 2013 -0400
+++ b/test-ng/bootlib/java/util/stream/SpliteratorTestHelper.java	Fri Apr 12 16:43:57 2013 -0400
@@ -134,6 +134,7 @@
         testForEach(exp, supplier, boxingAdapter);
         testTryAdvance(exp, supplier, boxingAdapter);
         testMixedTryAdvanceForEach(exp, supplier, boxingAdapter);
+        testMixedTraverseAndSplit(exp, supplier, boxingAdapter);
         testSplitAfterFullTraversal(supplier, boxingAdapter);
         testSplitOnce(exp, supplier, boxingAdapter);
         testSplitSixDeep(exp, supplier, boxingAdapter);
@@ -229,6 +230,54 @@
         }
     }
 
+    private static <T, S extends Spliterator<T>> void testMixedTraverseAndSplit(
+            Collection<T> exp,
+            Supplier<S> supplier,
+            UnaryOperator<Consumer<T>> boxingAdapter) {
+        S spliterator = supplier.get();
+        long sizeIfKnown = spliterator.getExactSizeIfKnown();
+        boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED);
+
+        // tryAdvance first few elements, then forEach rest
+        ArrayList<T> dest = new ArrayList<>();
+        spliterator = supplier.get();
+        Consumer<T> b = boxingAdapter.apply(dest::add);
+
+        Spliterator<T> spl1, spl2, spl3;
+        spliterator.tryAdvance(b);
+        spl2 = spliterator.trySplit();
+        if (spl2 != null) {
+            spl2.tryAdvance(b);
+            spl1 = spl2.trySplit();
+            if (spl1 != null) {
+                spl1.tryAdvance(b);
+                spl1.forEachRemaining(b);
+            }
+            spl2.tryAdvance(b);
+            spl2.forEachRemaining(b);
+        }
+        spliterator.tryAdvance(b);
+        spl3 = spliterator.trySplit();
+        if (spl3 != null) {
+            spl3.tryAdvance(b);
+            spl3.forEachRemaining(b);
+        }
+        spliterator.tryAdvance(b);
+        spliterator.forEachRemaining(b);
+
+        if (sizeIfKnown >= 0) {
+            assertEquals(sizeIfKnown, dest.size());
+        }
+        assertEquals(dest.size(), exp.size());
+
+        if (isOrdered) {
+            assertEquals(dest, exp);
+        }
+        else {
+            assertContentsUnordered(dest, exp);
+        }
+    }
+
     private static <T, S extends Spliterator<T>> void testSplitAfterFullTraversal(
             Supplier<S> supplier,
             UnaryOperator<Consumer<T>> boxingAdapter) {
@@ -504,4 +553,98 @@
         return result;
     }
 
+    static<U> void mixedTraverseAndSplit(Consumer<U> b, Spliterator<U> splTop) {
+        Spliterator<U> spl1, spl2, spl3;
+        splTop.tryAdvance(b);
+        spl2 = splTop.trySplit();
+        if (spl2 != null) {
+            spl2.tryAdvance(b);
+            spl1 = spl2.trySplit();
+            if (spl1 != null) {
+                spl1.tryAdvance(b);
+                spl1.forEachRemaining(b);
+            }
+            spl2.tryAdvance(b);
+            spl2.forEachRemaining(b);
+        }
+        splTop.tryAdvance(b);
+        spl3 = splTop.trySplit();
+        if (spl3 != null) {
+            spl3.tryAdvance(b);
+            spl3.forEachRemaining(b);
+        }
+        splTop.tryAdvance(b);
+        splTop.forEachRemaining(b);
+    }
+
+    static void mixedTraverseAndSplit(IntConsumer b, Spliterator.OfInt splTop) {
+        Spliterator.OfInt spl1, spl2, spl3;
+        splTop.tryAdvance(b);
+        spl2 = splTop.trySplit();
+        if (spl2 != null) {
+            spl2.tryAdvance(b);
+            spl1 = spl2.trySplit();
+            if (spl1 != null) {
+                spl1.tryAdvance(b);
+                spl1.forEachRemaining(b);
+            }
+            spl2.tryAdvance(b);
+            spl2.forEachRemaining(b);
+        }
+        splTop.tryAdvance(b);
+        spl3 = splTop.trySplit();
+        if (spl3 != null) {
+            spl3.tryAdvance(b);
+            spl3.forEachRemaining(b);
+        }
+        splTop.tryAdvance(b);
+        splTop.forEachRemaining(b);
+    }
+    static void mixedTraverseAndSplit(LongConsumer b, Spliterator.OfLong splTop) {
+        Spliterator.OfLong spl1, spl2, spl3;
+        splTop.tryAdvance(b);
+        spl2 = splTop.trySplit();
+        if (spl2 != null) {
+            spl2.tryAdvance(b);
+            spl1 = spl2.trySplit();
+            if (spl1 != null) {
+                spl1.tryAdvance(b);
+                spl1.forEachRemaining(b);
+            }
+            spl2.tryAdvance(b);
+            spl2.forEachRemaining(b);
+        }
+        splTop.tryAdvance(b);
+        spl3 = splTop.trySplit();
+        if (spl3 != null) {
+            spl3.tryAdvance(b);
+            spl3.forEachRemaining(b);
+        }
+        splTop.tryAdvance(b);
+        splTop.forEachRemaining(b);
+    }
+
+    static void mixedTraverseAndSplit(DoubleConsumer b, Spliterator.OfDouble splTop) {
+        Spliterator.OfDouble spl1, spl2, spl3;
+        splTop.tryAdvance(b);
+        spl2 = splTop.trySplit();
+        if (spl2 != null) {
+            spl2.tryAdvance(b);
+            spl1 = spl2.trySplit();
+            if (spl1 != null) {
+                spl1.tryAdvance(b);
+                spl1.forEachRemaining(b);
+            }
+            spl2.tryAdvance(b);
+            spl2.forEachRemaining(b);
+        }
+        splTop.tryAdvance(b);
+        spl3 = splTop.trySplit();
+        if (spl3 != null) {
+            spl3.tryAdvance(b);
+            spl3.forEachRemaining(b);
+        }
+        splTop.tryAdvance(b);
+        splTop.forEachRemaining(b);
+    }
 }
--- a/test-ng/bootlib/java/util/stream/StreamTestScenario.java	Fri Apr 12 15:30:04 2013 -0400
+++ b/test-ng/bootlib/java/util/stream/StreamTestScenario.java	Fri Apr 12 16:43:57 2013 -0400
@@ -75,6 +75,13 @@
         }
     },
 
+    // Wrap as stream, spliterate, then split a few times mixing advances with forEach
+    STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) {
+        <T, U, S_IN extends BaseStream<T, S_IN>> void _run(OpTestCase.TestData<T, S_IN> data, Consumer<U> b, Function<S_IN, Stream<U>> m) {
+            SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(data.stream()).spliterator());
+        }
+    },
+
     // Wrap as stream, and spliterate then iterate in pull mode
     STREAM_SPLITERATOR_FOREACH(false) {
         <T, U, S_IN extends BaseStream<T, S_IN>> void _run(OpTestCase.TestData<T, S_IN> data, Consumer<U> b, Function<S_IN, Stream<U>> m) {
@@ -174,7 +181,6 @@
                 b.accept(u);
         }
     },
-
     ;
 
     private boolean isParallel;
@@ -196,4 +202,5 @@
     }
 
     abstract <T, U, S_IN extends BaseStream<T, S_IN>> void _run(OpTestCase.TestData<T, S_IN> data, Consumer<U> b, Function<S_IN, Stream<U>> m);
+
 }