changeset 5878:9dd0188c1229 it2-bootstrap

More test framework refactoring; more tests; more bugfixes
author briangoetz
date Thu, 30 Aug 2012 11:42:29 -0400
parents 439e8ac5079d
children be97f25c86f1 76ff1fc6f813
files src/share/classes/java/util/streams/ops/IntermediateOp.java src/share/classes/java/util/streams/ops/MapExtractKeysOp.java src/share/classes/java/util/streams/ops/MapExtractValuesOp.java src/share/classes/java/util/streams/ops/MappedOp.java test-ng/tests/org/openjdk/tests/java/util/IterableTest.java test-ng/tests/org/openjdk/tests/java/util/IterablesTest.java test-ng/tests/org/openjdk/tests/java/util/IteratorsTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/CumulateOpTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/FilterOpTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/FlatMapOpTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/GroupByOpTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/MapExtractKeysOpTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/MapExtractValuesOpTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/MapOpTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/ReduceTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/SortedOpTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/StreamOpTestCase.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/ToArrayOpTest.java test-ng/tests/org/openjdk/tests/java/util/streams/ops/UniqOpTest.java
diffstat 19 files changed, 313 insertions(+), 194 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/streams/ops/IntermediateOp.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/src/share/classes/java/util/streams/ops/IntermediateOp.java	Thu Aug 30 11:42:29 2012 -0400
@@ -37,6 +37,7 @@
  * @author Brian Goetz
  */
 public interface IntermediateOp<T,U> {
+    public final static IntermediateOp<?,?>[] EMPTY_ARRAY = new IntermediateOp<?,?>[0];
 
     /**
      * Return the resultant state of a stream utilizing this operation
--- a/src/share/classes/java/util/streams/ops/MapExtractKeysOp.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/src/share/classes/java/util/streams/ops/MapExtractKeysOp.java	Thu Aug 30 11:42:29 2012 -0400
@@ -25,6 +25,7 @@
 package java.util.streams.ops;
 
 import java.util.Iterator;
+import java.util.MapIterator;
 import java.util.Mapping;
 import java.util.functions.BiSink;
 import java.util.functions.Sink;
@@ -43,7 +44,18 @@
 
     @Override
     public Iterator<K> iterator(Iterator<Mapping<K, V>> in) {
-        throw new UnsupportedOperationException("nyi");
+        final MapIterator<K,V> mapIterator = (MapIterator<K, V>) in;
+        return new Iterator<K>() {
+            @Override
+            public boolean hasNext() {
+                return mapIterator.hasNext();
+            }
+
+            @Override
+            public K next() {
+                return mapIterator.nextKey();
+            }
+        };
     }
 
     @Override
--- a/src/share/classes/java/util/streams/ops/MapExtractValuesOp.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/src/share/classes/java/util/streams/ops/MapExtractValuesOp.java	Thu Aug 30 11:42:29 2012 -0400
@@ -25,6 +25,7 @@
 package java.util.streams.ops;
 
 import java.util.Iterator;
+import java.util.MapIterator;
 import java.util.Mapping;
 import java.util.functions.BiSink;
 import java.util.functions.Sink;
@@ -43,7 +44,18 @@
 
     @Override
     public Iterator<V> iterator(Iterator<Mapping<K, V>> in) {
-        throw new UnsupportedOperationException("nyi");
+        final MapIterator<K,V> mapIterator = (MapIterator<K, V>) in;
+        return new Iterator<V>() {
+            @Override
+            public boolean hasNext() {
+                return mapIterator.hasNext();
+            }
+
+            @Override
+            public V next() {
+                return mapIterator.nextValue();
+            }
+        };
     }
 
     @Override
--- a/src/share/classes/java/util/streams/ops/MappedOp.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/src/share/classes/java/util/streams/ops/MappedOp.java	Thu Aug 30 11:42:29 2012 -0400
@@ -24,10 +24,7 @@
  */
 package java.util.streams.ops;
 
-import java.util.Iterator;
-import java.util.MapIterator;
-import java.util.Mapping;
-import java.util.Objects;
+import java.util.*;
 import java.util.functions.BiSink;
 import java.util.functions.Mapper;
 import java.util.functions.Sink;
@@ -51,8 +48,69 @@
     }
 
     @Override
-    public MapIterator<T, R> iterator(Iterator<T> in) {
-        throw new UnsupportedOperationException("nyi");
+    public MapIterator<T, R> iterator(final Iterator<T> in) {
+        return new MapIterator<T, R>() {
+            boolean hasCurrent;
+            T currentKey;
+            R currentValue;
+
+            private void advance() {
+                if (!in.hasNext())
+                    throw new NoSuchElementException();
+                hasCurrent = true;
+                currentKey = in.next();
+                currentValue = mapper.map(currentKey);
+            }
+
+            @Override
+            public T nextKey() {
+                advance();
+                return currentKey;
+            }
+
+            @Override
+            public R nextValue() {
+                advance();
+                return currentValue;
+            }
+
+            @Override
+            public T curKey() {
+                if (hasCurrent)
+                    return currentKey;
+                else
+                    throw new NoSuchElementException();
+            }
+
+            @Override
+            public R curValue() {
+                if (hasCurrent)
+                    return currentValue;
+                else
+                    throw new NoSuchElementException();
+            }
+
+            @Override
+            public boolean hasNext() {
+                return in.hasNext();
+            }
+
+            @Override
+            public Mapping<T, R> next() {
+                advance();
+                return new Mapping.AbstractMapping<T,R>() {
+                    @Override
+                    public T getKey() {
+                        return currentKey;
+                    }
+
+                    @Override
+                    public R getValue() {
+                        return currentValue;
+                    }
+                };
+            }
+        };
     }
 
     @Override
--- a/test-ng/tests/org/openjdk/tests/java/util/IterableTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/IterableTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -96,36 +96,6 @@
         assertEquals(sum, accumulator.get());
     }
 
-    public void testReduce() {
-        List<Integer> list = countTo(10);
-
-        assertEquals(55, (int) list.reduce(0, rPlus));
-        assertEquals(10, (int) list.reduce(0, rMax));
-        assertEquals(1, (int) list.reduce(1000, rMin));
-
-        assertEquals(0, (int) countTo(0).reduce(0, rPlus));
-    }
-
-    public void testCumulate() {
-        assertTrue(countTo(0).cumulate(Math::max).isEmpty());
-        assertContents(countTo(10), countTo(10).cumulate(Math::max));
-        assertContents(countTo(10).cumulate(rPlus), Arrays.asList(1, 3, 6, 10, 15, 21, 28, 36, 45, 55));
-    }
-
-    // This test used to fail due to a weaver bug having to do with local variable table offsets in the presence of longs
-    // If you find this test failing, you need to update your jsr335-agent.jar
-    public void testMapReduce() {
-        List<Integer> list = countTo(10);
-
-        assertEquals(110, (int) list.mapReduce(mDoubler, 0, rPlus));
-        assertEquals(20, (int) list.mapReduce(mDoubler, 0, rMax));
-        assertEquals(2, (int) list.mapReduce(mDoubler, 1000, rMin));
-
-        assertEquals(110, list.mapReduce(imDoubler, 0, irPlus));
-        assertEquals(110.0D, asDoubles(list).mapReduce(dmDoubler, 0.0D, drPlus));
-        assertEquals(110L, asLongs(list).mapReduce(lmDoubler, 0L, lrPlus));
-    }
-
     public void testXxxMatch() {
         List<Integer> empty = countTo(0);
         assertFalse(empty.anyMatch( pTrue));
@@ -244,40 +214,5 @@
         Collections.reverse(list);
         assertSorted(list.sorted(cInteger));
     }
-
-    public void testUnique() {
-        List<Integer> list = countTo(100);
-        List<Integer> unique = list.uniqueElements().into(new ArrayList<Integer>());
-        assertEquals(list.size(), unique.size());
-        for (Integer i : list)
-            assertTrue(unique.contains(i));
-        for (Integer i : unique)
-            assertTrue(list.contains(i));
-
-        List<Integer> twice = new ArrayList<>();
-        list.into(twice);
-        list.into(twice);
-        assertEquals(200, twice.size());
-        unique = twice.uniqueElements().into(new ArrayList<Integer>());
-        assertEquals(100, unique.size());
-        for (Integer i : twice)
-            assertTrue(unique.contains(i));
-        for (Integer i : unique)
-            assertTrue(list.contains(i));
-
-        List<Integer> empty = new ArrayList<>();
-        unique = empty.uniqueElements().into(new ArrayList<Integer>());
-        assertEquals(0, unique.size());
-
-        List<Integer> repeated = Arrays.asList(1, 1, 1, 1, 1, 1);
-        unique = repeated.uniqueElements().into(new ArrayList<Integer>());
-        assertEquals(1, unique.size());
-        assertEquals(Integer.valueOf(1), unique.get(0));
-
-        List<Integer> last = Arrays.asList(2, 2, 2, 2, 3);
-        unique = last.uniqueElements().into(new ArrayList<Integer>());
-        assertEquals(2, unique.size());
-        assertTrue(unique.equals(Arrays.asList(2, 3)));
-    }
 */
 }
--- a/test-ng/tests/org/openjdk/tests/java/util/IterablesTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/IterablesTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -82,28 +82,6 @@
         assertEquals(sum, accumulator.get());
     }
 
-    public void testReduce() {
-        List<Integer> list = countTo(10);
-
-        assertEquals(55, (int) Iterables.reduce(list, 0, rPlus));
-        assertEquals(10, (int) Iterables.reduce(list, 0, rMax));
-        assertEquals(1, (int) Iterables.reduce(list, 1000, rMin));
-
-        assertEquals(0, (int) Iterables.reduce(countTo(0), 0, rPlus));
-    }
-
-    public void testMapReduce() {
-        List<Integer> list = countTo(10);
-
-        assertEquals(110, (int) Iterables.mapReduce(list, mDoubler, 0, rPlus));
-        assertEquals(20, (int) Iterables.mapReduce(list, mDoubler, 0, rMax));
-        assertEquals(2, (int) Iterables.mapReduce(list, mDoubler, 1000, rMin));
-
-        assertEquals(110, Iterables.mapReduce(list, imDoubler, 0, irPlus));
-        assertEquals(110.0D, Iterables.mapReduce(asDoubles(list), dmDoubler, 0, drPlus));
-        assertEquals(110L, Iterables.mapReduce(asLongs(list), lmDoubler, 0, lrPlus));
-    }
-
     public void testXxxMatch() {
         List<Integer> empty = countTo(0);
         assertFalse(Iterables.anyMatch(empty, pTrue));
--- a/test-ng/tests/org/openjdk/tests/java/util/IteratorsTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/IteratorsTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -37,18 +37,6 @@
  */
 @Test(groups = { "unit", "lambda" })
 public class IteratorsTest {
-    public void testMapReduce() {
-        List<Integer> list = countTo(10);
-
-        assertEquals(110, (int) Iterators.mapReduce(list.iterator(), mDoubler, 0, rPlus));
-        assertEquals(20, (int) Iterators.mapReduce(list.iterator(), mDoubler, 0, rMax));
-        assertEquals(2, (int) Iterators.mapReduce(list.iterator(), mDoubler, 1000, rMin));
-
-        assertEquals(110, Iterators.mapReduce(list.iterator(), imDoubler, 0, irPlus));
-        assertEquals(110.0D, Iterators.mapReduce(asDoubles(list).iterator(), dmDoubler, 0, drPlus));
-        assertEquals(110L, Iterators.mapReduce(asLongs(list).iterator(), lmDoubler, 0, lrPlus));
-    }
-
     public void testXxxMatch() {
         List<Integer> empty = countTo(0);
         assertFalse(AnyMatchOp.anyMatch(empty.iterator(), pTrue));
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/CumulateOpTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/CumulateOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -54,8 +54,13 @@
 
     @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, TestData<Integer> data) {
-        exerciseOps(data, l -> l, new CumulateOp<>(rPlus));
-        exerciseOps(data, l -> l, new CumulateOp<>(rMin));
-        exerciseOps(data, l -> l, new CumulateOp<>(rMax));
+        StreamResult<Integer> result = exerciseOps(data, new CumulateOp<>(rPlus));
+        assertEquals(result.size(), data.size());
+
+        result = exerciseOps(data, new CumulateOp<>(rMin));
+        assertEquals(result.size(), data.size());
+
+        result = exerciseOps(data, new CumulateOp<>(rMax));
+        assertEquals(result.size(), data.size());
     }
 }
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/FilterOpTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/FilterOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -58,11 +58,19 @@
 
     @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, TestData<Integer> data) {
-        exerciseOps(data, l -> l, new FilterOp<>(pTrue));
-        exerciseOps(data, l -> 0, new FilterOp<>(pFalse));
+        StreamResult<Integer> result = exerciseOps(data, new FilterOp<>(pTrue));
+        assertEquals(result.size(), data.size());
+
+        result = exerciseOps(data, new FilterOp<>(pFalse));
+        assertEquals(result.size(), 0);
+
         exerciseOps(data, new FilterOp<>(pEven));
         exerciseOps(data, new FilterOp<>(pOdd));
-        exerciseOps(data, l -> 0, new FilterOp<>(pOdd.and(pEven)));
-        exerciseOps(data, l -> l, new FilterOp<>(pOdd.or(pEven)));
+
+        result = exerciseOps(data, new FilterOp<>(pOdd.and(pEven)));
+        assertEquals(result.size(), 0);
+
+        result = exerciseOps(data, new FilterOp<>(pOdd.or(pEven)));
+        assertEquals(result.size(), data.size());
     }
 }
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/FlatMapOpTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/FlatMapOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -66,14 +66,18 @@
         assertCountSum(countTo(10).stream().flatMap(mfNull), 0, 0);
         assertCountSum(countTo(3).stream().flatMap(mfLt), 6, 4);
 
-        exerciseOps(new ArrayTestData<>(stringsArray), null, new FlatMapOp<>(flattenChars));
-        exerciseOps(new ArrayTestData<>(new String[]{LONG_STRING}), null, new FlatMapOp<>(flattenChars));
+        exerciseOps(new ArrayTestData<>(stringsArray), new FlatMapOp<>(flattenChars));
+        exerciseOps(new ArrayTestData<>(new String[]{LONG_STRING}), new FlatMapOp<>(flattenChars));
     }
 
     @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, TestData<Integer> data) {
-        exerciseOps(data, l -> l, new FlatMapOp<>(mfId));
-        exerciseOps(data, l -> 0, new FlatMapOp<>(mfNull));
+        StreamResult<Integer> result = exerciseOps(data, new FlatMapOp<>(mfId));
+        assertEquals(data.size(), result.size());
+
+        result = exerciseOps(data, new FlatMapOp<>(mfNull));
+        assertEquals(0, result.size());
+
         exerciseOps(data, new FlatMapOp<>(mfLt));
         exerciseOps(data, new FlatMapOp<>(mfIntToBits));
     }
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/GroupByOpTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/GroupByOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -27,6 +27,7 @@
 import org.openjdk.tests.java.util.streams.StreamTestDataProvider;
 import org.testng.annotations.Test;
 
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.functions.Mappers;
@@ -35,7 +36,6 @@
 import java.util.streams.ops.GroupByOp;
 
 import static org.openjdk.tests.java.util.LambdaTestHelpers.*;
-import static org.testng.Assert.assertEquals;
 
 /**
  * GroupByOpTest
@@ -80,14 +80,37 @@
 
     @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, TestData<Integer> data) {
-        exerciseOps(data, new GroupByOp<>(mId));
-        exerciseOps(data, new GroupByOp<>(mZero));
-        exerciseOps(data, new GroupByOp<>(mDoubler));
-        exerciseOps(data, new GroupByOp<>(mId.compose(mDoubler)));
-        exerciseOps(data, new GroupByOp<>(mDoubler.compose(mDoubler)));
-        exerciseOps(data, new GroupByOp<>(Mappers.forPredicate(pFalse, true, false)));
-        exerciseOps(data, new GroupByOp<>(Mappers.forPredicate(pTrue, true, false)));
-        exerciseOps(data, new GroupByOp<>(Mappers.forPredicate(pEven, true, false)));
-        exerciseOps(data, new GroupByOp<>(Mappers.forPredicate(pOdd, true, false)));
+        // @@@ More things to test here:
+        //     - Every value in data is present in right bucket
+        //     - Total number of values equals size of data
+
+        int uniqueSize = data.into(new HashSet<Integer>()).size();
+
+        Map<Integer, Streamable<Integer>> miResult = exerciseOps(data, new GroupByOp<>(mId));
+        assertEquals(miResult.keySet().size(), uniqueSize);
+
+        miResult = exerciseOps(data, new GroupByOp<>(mZero));
+        assertEquals(miResult.keySet().size(), Math.min(1, data.size()));
+
+        miResult = exerciseOps(data, new GroupByOp<>(mDoubler));
+        assertEquals(miResult.keySet().size(), uniqueSize);
+
+        miResult = exerciseOps(data, new GroupByOp<>(mId.compose(mDoubler)));
+        assertEquals(miResult.keySet().size(), uniqueSize);
+
+        miResult = exerciseOps(data, new GroupByOp<>(mDoubler.compose(mDoubler)));
+        assertEquals(miResult.keySet().size(), uniqueSize);
+
+        Map<Boolean, Streamable<Integer>> mbResult = exerciseOps(data, new GroupByOp<>(Mappers.forPredicate(pFalse, true, false)));
+        assertEquals(mbResult.keySet().size(), Math.min(1, uniqueSize));
+
+        mbResult = exerciseOps(data, new GroupByOp<>(Mappers.forPredicate(pTrue, true, false)));
+        assertEquals(mbResult.keySet().size(), Math.min(1, uniqueSize));
+
+        mbResult = exerciseOps(data, new GroupByOp<>(Mappers.forPredicate(pEven, true, false)));
+        assertEquals(mbResult.keySet().size(), Math.min(2, uniqueSize));
+
+        mbResult = exerciseOps(data, new GroupByOp<>(Mappers.forPredicate(pOdd, true, false)));
+        assertEquals(mbResult.keySet().size(), Math.min(2, uniqueSize));
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/MapExtractKeysOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.tests.java.util.streams.ops;
+
+import org.openjdk.tests.java.util.streams.StreamTestDataProvider;
+import org.testng.annotations.Test;
+
+import java.util.streams.ops.MapExtractKeysOp;
+import java.util.streams.ops.MappedOp;
+
+import static org.openjdk.tests.java.util.LambdaTestHelpers.mDoubler;
+
+/**
+ * MapExtractKeysOpTest
+ *
+ * @author Brian Goetz
+ */
+public class MapExtractKeysOpTest extends StreamOpTestCase {
+    @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
+    public void testOps(String name, TestData<Integer> data) {
+        StreamResult<Integer> ref = exerciseOps(data);
+        StreamResult<Integer> result = exerciseOps(data, new MappedOp<>(mDoubler), new MapExtractKeysOp<>());
+        assertEquals(ref, result);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/MapExtractValuesOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.tests.java.util.streams.ops;
+
+import org.openjdk.tests.java.util.streams.StreamTestDataProvider;
+import org.testng.annotations.Test;
+
+import java.util.streams.ops.MapExtractKeysOp;
+import java.util.streams.ops.MapExtractValuesOp;
+import java.util.streams.ops.MapOp;
+import java.util.streams.ops.MappedOp;
+
+import static org.openjdk.tests.java.util.LambdaTestHelpers.mDoubler;
+
+/**
+ * MapExtractValuesTest
+ *
+ * @author Brian Goetz
+ */
+public class MapExtractValuesOpTest extends StreamOpTestCase {
+    @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
+    public void testOps(String name, TestData<Integer> data) {
+        StreamResult<Integer> ref = exerciseOps(data, new MapOp<>(mDoubler));
+        StreamResult<Integer> result = exerciseOps(data, new MappedOp<>(mDoubler), new MapExtractValuesOp<>());
+        assertEquals(ref, result);
+    }
+}
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/MapOpTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/MapOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -57,10 +57,19 @@
 
     @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, TestData<Integer> data) {
-        exerciseOps(data, l -> l, new MapOp<>(mId));
-        exerciseOps(data, l -> l, new MapOp<>(mZero));
-        exerciseOps(data, l -> l, new MapOp<>(mDoubler));
-        exerciseOps(data, l -> l, new MapOp<>(mId.compose(mDoubler)));
-        exerciseOps(data, l -> l, new MapOp<>(mDoubler.compose(mDoubler)));
+        StreamResult<Integer> result = exerciseOps(data, new MapOp<>(mId));
+        assertEquals(data.size(), result.size());
+
+        result = exerciseOps(data, new MapOp<>(mZero));
+        assertEquals(data.size(), result.size());
+
+        result = exerciseOps(data, new MapOp<>(mDoubler));
+        assertEquals(data.size(), result.size());
+
+        result = exerciseOps(data, new MapOp<>(mId.compose(mDoubler)));
+        assertEquals(data.size(), result.size());
+
+        result = exerciseOps(data, new MapOp<>(mDoubler.compose(mDoubler)));
+        assertEquals(data.size(), result.size());
     }
 }
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/ReduceTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/ReduceTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -25,21 +25,14 @@
 package org.openjdk.tests.java.util.streams.ops;
 
 import org.openjdk.tests.java.util.streams.StreamTestDataProvider;
-import org.openjdk.tests.java.util.streams.ops.StreamOpTestCase;
 import org.testng.annotations.Test;
 
-import java.util.Iterators;
 import java.util.List;
-import java.util.Optional;
 import java.util.streams.ops.FoldOp;
 import java.util.streams.ops.MapOp;
 import java.util.streams.ops.SeedlessFoldOp;
 
 import static org.openjdk.tests.java.util.LambdaTestHelpers.*;
-import static org.openjdk.tests.java.util.LambdaTestHelpers.countTo;
-import static org.openjdk.tests.java.util.LambdaTestHelpers.rPlus;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
 
 /**
  * ReduceOpTest
@@ -58,6 +51,10 @@
 
         assertEquals(0, (int) countTo(0).stream().reduce(0, rPlus));
         assertTrue(!countTo(0).stream().reduce(rPlus).isPresent());
+
+        assertEquals(110, (int) list.stream().map(mDoubler).reduce(rPlus).get());
+        assertEquals(20, (int) list.stream().map(mDoubler).reduce(rMax).get());
+        assertEquals(2, (int) list.stream().map(mDoubler).reduce(rMin).get());
     }
 
     @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/SortedOpTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/SortedOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -25,17 +25,15 @@
 package org.openjdk.tests.java.util.streams.ops;
 
 import org.openjdk.tests.java.util.streams.StreamTestDataProvider;
+import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparators;
 import java.util.List;
 import java.util.streams.ops.SortedOp;
 
 import static org.openjdk.tests.java.util.LambdaTestHelpers.*;
-import static org.openjdk.tests.java.util.LambdaTestHelpers.assertSorted;
-import static org.testng.Assert.assertTrue;
 
 /**
  * SortedOpTest
@@ -104,8 +102,12 @@
     @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, TestData<Integer> data) {
         SortedOp<Integer> op = new SortedOp<>(cInteger);
-        assertSorted((stream(data.seq(op))).into(new ArrayList<Integer>()).iterator());
-        exerciseOps(data, l -> l, op);
-        exerciseOps(data, l -> l, new SortedOp<>(cInteger.reverse()));
+
+        StreamResult<Integer> result = exerciseOps(data, op);
+        assertSorted(result.iterator());
+        Assert.assertEquals(result.size(), data.size());
+
+        result = exerciseOps(data, new SortedOp<>(cInteger.reverse()));
+        Assert.assertEquals(result.size(), data.size());
     }
 }
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/StreamOpTestCase.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/StreamOpTestCase.java	Thu Aug 30 11:42:29 2012 -0400
@@ -32,7 +32,6 @@
 import java.util.concurrent.ForkJoinUtils;
 import java.util.functions.BiPredicate;
 import java.util.functions.Block;
-import java.util.functions.Mapper;
 import java.util.functions.Sink;
 import java.util.streams.*;
 import java.util.streams.ops.IntermediateOp;
@@ -40,16 +39,13 @@
 import java.util.streams.ops.StatefulOp;
 import java.util.streams.ops.TerminalOp;
 
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
 /**
  * StreamOpTestCase
  *
  * @author Brian Goetz
  */
 @Test
-public abstract class StreamOpTestCase {
+public abstract class StreamOpTestCase extends Assert {
 
     protected static<T> void assertMatches(StreamResult<T> refResult, Block<Sink<T>> block) {
         StreamResult<T> newResult = new StreamResult<>();
@@ -58,9 +54,8 @@
     }
 
     protected static <T, U> StreamResult<U> exerciseOps(TestData<T> data,
-                                                        Mapper<Integer, Integer> lengthMapper,
                                                         IntermediateOp<T, U> op) {
-        StreamResult<U> refResult = exerciseOps(data, lengthMapper, new IntermediateOp[] { op });
+        StreamResult<U> refResult = exerciseOps(data, new IntermediateOp[] { op });
 
         // For stateful ops, validate Node contents with fake ParallelHelper
         if (op.isStateful()) {
@@ -75,22 +70,14 @@
     }
 
     protected static <T, U> StreamResult<U> exerciseOps(TestData<T> data,
-                                                        Mapper<Integer, Integer> lengthMapper,
                                                         IntermediateOp... ops) {
-        int length = (lengthMapper == null) ? 100 : lengthMapper.map(data.size());
-
-        StreamResult<U> refResult = new StreamResult<>(length);
+        StreamResult<U> refResult = new StreamResult<>(data.size());
 
         // First pass -- grab an iterator and wrap it, and call that the reference result
         Iterator<U> it = (Iterator<U>) data.iterator(ops);
         while (it.hasNext())
             refResult.accept(it.next());
 
-        // If a length mapper has been specified, make sure it is right
-        if (lengthMapper != null) {
-            Assert.assertEquals(refResult.size(), (int)lengthMapper.map(data.size()));
-        }
-
         // Second pass -- create a sink and wrap it
         assertMatches(refResult, sink -> {
             Sink<T> wrapped = sink(sink, ops);
@@ -143,64 +130,58 @@
         return refResult;
     }
 
-    protected <T, U> void exerciseOps(TestData<T> data, IntermediateOp<T, U> op) {
-        exerciseOps(data, null, op);
+    protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal) {
+        return exerciseOps(data, terminal, new IntermediateOp[0]);
     }
 
-    protected <T, U> void exerciseOps(TestData<T> data, IntermediateOp... ops) {
-        exerciseOps(data, (Mapper<Integer, Integer>) null, ops);
+    protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp... ops) {
+        return exerciseOps(data, (u, v) -> u.equals(v), terminal, ops);
     }
 
-    protected <T, U> void exerciseOps(TestData<T> data, TerminalOp<T, U> terminal) {
-        exerciseOps(data, terminal, new IntermediateOp[0]);
-    }
-
-    protected <T, U> void exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp... ops) {
-        exerciseOps(data, (u, v) -> u.equals(v), terminal, ops);
-    }
-
-    protected static <T, U> void exerciseOps(TestData<T> data,
-                                             BiPredicate<U, U> equalator,
-                                             TerminalOp<T, U> terminalOp,
-                                             IntermediateOp[] ops) {
-        final U answer1;
+    protected static <T, U> U exerciseOps(TestData<T> data,
+                                          BiPredicate<U, U> equalator,
+                                          TerminalOp<T, U> terminalOp,
+                                          IntermediateOp[] ops) {
+        final U answer;
 
         if (terminalOp.isShortCircuit()) {
             // First pass -- wrap Iterator
-            answer1 = terminalOp.evaluate(data.iterator());
+            answer = terminalOp.evaluate(data.iterator());
         }
         else {
             // First pass -- create a sink and evaluate, with no size advice
             StatefulSink<T, U> sink = terminalOp.sink();
             sink.begin(-1);
             data.forEach(sink);
-            answer1 = sink.end();
+            answer = sink.end();
 
             // Create a sink and evaluate, with size advice
             StatefulSink<T, U> sink2 = terminalOp.sink();
             sink2.begin(data.size());
             data.forEach(sink2);
             U answer2 = sink2.end();
-            Assert.assertTrue(equalator.test(answer1, answer2));
+            assertTrue(equalator.test(answer, answer2));
         }
 
         // Third pass -- wrap with SequentialPipeline.op
         U answer3 = data.seq(terminalOp);
-        Assert.assertTrue(equalator.test(answer1, answer3));
+        assertTrue(equalator.test(answer, answer3));
 
         // Fourth pass -- wrap with ParallelPipeline.op
         U answer4 = data.par(terminalOp);
-        Assert.assertTrue(equalator.test(answer1, answer4));
+        assertTrue(equalator.test(answer, answer4));
+
+        return answer;
     }
 
-    private static <U> void assertEquals(StreamResult<U> sink1, StreamResult<U> sink2) {
+    protected static <U> void assertEquals(StreamResult<U> sink1, StreamResult<U> sink2) {
         try {
-            Assert.assertEquals(sink1.size(), sink2.size());
+            assertEquals(sink1.size(), sink2.size());
             Iterator<U> it1 = sink1.iterator();
             Iterator<U> it2 = sink2.iterator();
             while (it1.hasNext()) {
                 assertTrue(it2.hasNext());
-                Assert.assertEquals(it1.next(), it2.next());
+                assertEquals(it1.next(), it2.next());
             }
             assertFalse(it2.hasNext());
         }
@@ -210,7 +191,7 @@
         }
     }
 
-    private static class StreamResult<T> implements Sink<T>, Traversable<T>, Sized {
+    static class StreamResult<T> implements Sink<T>, Traversable<T>, Sized {
 
         private Object[] array;
 
@@ -360,6 +341,13 @@
             return chain(par(), op);
         }
 
+        <A extends Collection<? super T>> A into(A target) default {
+            Iterator<T> iterator = iterator();
+            while (iterator.hasNext())
+                target.add(iterator.next());
+            return target;
+        }
+
         @SuppressWarnings({ "raw", "unchecked" })
         Iterator<?> iterator(IntermediateOp... ops) default {
             Iterator<T> iterator = iterator();
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/ToArrayOpTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/ToArrayOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -27,10 +27,9 @@
 import org.openjdk.tests.java.util.streams.StreamTestDataProvider;
 import org.testng.annotations.Test;
 
-import java.util.functions.BiPredicate;
+import java.util.Arrays;
 import java.util.streams.ops.IntermediateOp;
 import java.util.streams.ops.ToArrayOp;
-import java.util.Arrays;
 
 import static org.openjdk.tests.java.util.LambdaTestHelpers.*;
 
@@ -54,6 +53,6 @@
 
     @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, TestData<Integer> data) {
-        exerciseOps(data, Arrays::equals, ToArrayOp.<Integer>singleton(), new IntermediateOp[0]);
+        exerciseOps(data, Arrays::equals, ToArrayOp.<Integer>singleton(), IntermediateOp.EMPTY_ARRAY);
     }
 }
--- a/test-ng/tests/org/openjdk/tests/java/util/streams/ops/UniqOpTest.java	Wed Aug 29 17:12:18 2012 -0400
+++ b/test-ng/tests/org/openjdk/tests/java/util/streams/ops/UniqOpTest.java	Thu Aug 30 11:42:29 2012 -0400
@@ -27,7 +27,6 @@
 import org.openjdk.tests.java.util.streams.StreamTestDataProvider;
 import org.testng.annotations.Test;
 
-import java.util.ArrayList;
 import java.util.streams.ops.UniqOp;
 
 import static org.openjdk.tests.java.util.LambdaTestHelpers.*;
@@ -57,8 +56,13 @@
     @Test(dataProvider = "opArrays", dataProviderClass = StreamTestDataProvider.class)
     public void testOps(String name, TestData<Integer> data) {
         UniqOp<Integer> op = UniqOp.singleton();
-        ArrayList<Integer> result = (stream(data.seq(op))).into(new ArrayList<Integer>());
+
+        StreamResult<Integer> result = exerciseOps(data, op);
         assertUnique(result.iterator());
-        exerciseOps(data, null, op);
+        if (data.size() > 0)
+            assertTrue(result.size() > 0);
+        else
+            assertTrue(result.size() == 0);
+        assertTrue(result.size() <= data.size());
     }
 }