From 15adfafa5b6fbcd3fecab9d4b9095a475d224975 Mon Sep 17 00:00:00 2001 From: Brian Goetz Date: Mon, 6 May 2013 11:43:51 -0400 Subject: [PATCH] 8012664: Add tests for java.util.stream and lambda translation Co-authored-by: Paul Sandoz Co-authored-by: Mike Duigou Co-authored-by: Robert Field Co-authored-by: Jim Gish Reviewed-by: mduigou, briangoetz --- jdk/test/Makefile | 1 + .../atomic/AtomicReferenceTest.java | 58 + .../java/util/stream/bootlib/TEST.properties | 3 + .../java/util/stream/CollectorOps.java | 113 ++ .../stream/DoubleStreamTestDataProvider.java | 166 ++ .../util/stream/DoubleStreamTestScenario.java | 185 +++ .../java/util/stream/FlagDeclaringOp.java | 61 + .../stream/IntStreamTestDataProvider.java | 167 ++ .../util/stream/IntStreamTestScenario.java | 185 +++ .../java/util/stream/IntermediateTestOp.java | 41 + .../java/util/stream/LambdaTestHelpers.java | 471 ++++++ .../stream/LongStreamTestDataProvider.java | 166 ++ .../util/stream/LongStreamTestScenario.java | 185 +++ .../bootlib/java/util/stream/OpTestCase.java | 633 ++++++++ .../util/stream/SpliteratorTestHelper.java | 654 ++++++++ .../java/util/stream/StatefulTestOp.java | 138 ++ .../java/util/stream/StatelessTestOp.java | 73 + .../util/stream/StreamOpFlagTestHelper.java | 48 + .../util/stream/StreamTestDataProvider.java | 199 +++ .../java/util/stream/StreamTestScenario.java | 225 +++ .../bootlib/java/util/stream/TestData.java | 355 +++++ .../java/util/stream/TestFlagExpectedOp.java | 125 ++ .../java/util/stream/boottest/TEST.properties | 5 + .../java/util/stream/DoubleNodeTest.java | 165 ++ .../boottest/java/util/stream/FlagOpTest.java | 283 ++++ .../java/util/stream/IntNodeTest.java | 163 ++ .../java/util/stream/LongNodeTest.java | 164 ++ .../java/util/stream/NodeBuilderTest.java | 236 +++ .../boottest/java/util/stream/NodeTest.java | 140 ++ .../java/util/stream/SpinedBufferTest.java | 370 +++++ .../java/util/stream/StreamFlagsTest.java | 96 ++ .../java/util/stream/StreamOpFlagsTest.java | 381 +++++ .../java/util/stream/StreamReuseTest.java | 441 ++++++ .../java/util/stream/UnorderedTest.java | 267 ++++ .../java/util/stream/test/TEST.properties | 8 + .../lang/invoke/DeserializeMethodTest.java | 87 + .../tests/java/lang/invoke/MHProxiesTest.java | 49 + .../lang/invoke/SerializedLambdaTest.java | 280 ++++ .../tests/java/util/FillableStringTest.java | 56 + .../org/openjdk/tests/java/util/MapTest.java | 93 ++ .../tests/java/util/NullArgsTestCase.java | 70 + .../CollectionAndMapModifyStreamTest.java | 167 ++ .../java/util/stream/DistinctOpTest.java | 139 ++ .../util/stream/DoublePrimitiveOpsTests.java | 106 ++ .../tests/java/util/stream/ExplodeOpTest.java | 116 ++ .../tests/java/util/stream/FilterOpTest.java | 109 ++ .../tests/java/util/stream/FindAnyOpTest.java | 157 ++ .../java/util/stream/FindFirstOpTest.java | 132 ++ .../tests/java/util/stream/ForEachOpTest.java | 250 +++ .../tests/java/util/stream/GroupByOpTest.java | 166 ++ .../stream/InfiniteStreamWithLimitOpTest.java | 66 + .../util/stream/IntPrimitiveOpsTests.java | 183 +++ .../tests/java/util/stream/IntReduceTest.java | 81 + .../java/util/stream/IntSliceOpTest.java | 221 +++ .../tests/java/util/stream/IntUniqOpTest.java | 73 + .../util/stream/LongPrimitiveOpsTests.java | 183 +++ .../tests/java/util/stream/MapOpTest.java | 135 ++ .../tests/java/util/stream/MatchOpTest.java | 371 +++++ .../tests/java/util/stream/MinMaxTest.java | 92 ++ .../util/stream/PrimitiveAverageOpTest.java | 50 + .../java/util/stream/PrimitiveSumTest.java | 65 + .../tests/java/util/stream/RangeTest.java | 400 +++++ .../java/util/stream/ReduceByOpTest.java | 65 + .../tests/java/util/stream/ReduceTest.java | 87 + .../java/util/stream/SequentialOpTest.java | 118 ++ .../tests/java/util/stream/SliceOpTest.java | 247 +++ .../tests/java/util/stream/SortedOpTest.java | 259 +++ .../SpliteratorLateBindingFailFastTest.java | 358 +++++ .../java/util/stream/SpliteratorTest.java | 64 + ...SpliteratorTraversingAndSplittingTest.java | 1411 +++++++++++++++++ .../java/util/stream/StreamBuilderTest.java | 319 ++++ .../java/util/stream/StreamLinkTest.java | 100 ++ .../java/util/stream/StreamParSeqTest.java | 52 + .../util/stream/StreamSpliteratorTest.java | 596 +++++++ .../util/stream/SummaryStatisticsTest.java | 88 + .../java/util/stream/TabulatorsTest.java | 398 +++++ .../tests/java/util/stream/TeeOpTest.java | 139 ++ .../tests/java/util/stream/ToArrayOpTest.java | 379 +++++ jdk/test/jdk/lambda/ArrayCtorRefTest.java | 74 + jdk/test/jdk/lambda/FDTest.java | 192 +++ .../LambdaTranslationCompoundSamTest.java | 75 + .../lambda/LambdaTranslationInInterface.java | 59 + .../LambdaTranslationInnerConstructor.java | 70 + .../jdk/lambda/LambdaTranslationTest1.java | 232 +++ .../jdk/lambda/LambdaTranslationTest2.java | 347 ++++ .../jdk/lambda/MethodReferenceTestFDCCE.java | 146 ++ .../MethodReferenceTestInnerDefault.java | 79 + .../MethodReferenceTestInnerInstance.java | 86 + .../MethodReferenceTestInnerVarArgsThis.java | 241 +++ .../lambda/MethodReferenceTestInstance.java | 61 + .../MethodReferenceTestInstanceMethod.java | 59 + .../jdk/lambda/MethodReferenceTestKinds.java | 173 ++ .../jdk/lambda/MethodReferenceTestNew.java | 130 ++ .../lambda/MethodReferenceTestNewInner.java | 150 ++ .../lambda/MethodReferenceTestSueCase1.java | 46 + .../lambda/MethodReferenceTestSueCase2.java | 47 + .../lambda/MethodReferenceTestSueCase4.java | 52 + .../jdk/lambda/MethodReferenceTestSuper.java | 113 ++ .../MethodReferenceTestSuperDefault.java | 74 + .../MethodReferenceTestTypeConversion.java | 53 + .../lambda/MethodReferenceTestVarArgs.java | 195 +++ .../lambda/MethodReferenceTestVarArgsExt.java | 182 +++ .../MethodReferenceTestVarArgsSuper.java | 200 +++ ...ethodReferenceTestVarArgsSuperDefault.java | 181 +++ .../MethodReferenceTestVarArgsThis.java | 177 +++ jdk/test/jdk/lambda/TEST.properties | 5 + jdk/test/jdk/lambda/TestInnerCtorRef.java | 63 + jdk/test/jdk/lambda/TestPrivateCtorRef.java | 60 + .../lambda/separate/AttributeInjector.java | 71 + jdk/test/jdk/lambda/separate/ClassFile.java | 452 ++++++ .../separate/ClassFilePreprocessor.java | 28 + .../separate/ClassToInterfaceConverter.java | 92 ++ jdk/test/jdk/lambda/separate/Compiler.java | 257 +++ .../lambda/separate/DirectedClassLoader.java | 99 ++ jdk/test/jdk/lambda/separate/SourceModel.java | 560 +++++++ jdk/test/jdk/lambda/separate/TestHarness.java | 314 ++++ jdk/test/jdk/lambda/shapegen/ClassCase.java | 310 ++++ jdk/test/jdk/lambda/shapegen/Hierarchy.java | 207 +++ .../lambda/shapegen/HierarchyGenerator.java | 190 +++ jdk/test/jdk/lambda/shapegen/Rule.java | 46 + jdk/test/jdk/lambda/shapegen/RuleGroup.java | 204 +++ jdk/test/jdk/lambda/shapegen/TTNode.java | 124 ++ jdk/test/jdk/lambda/shapegen/TTParser.java | 98 ++ jdk/test/jdk/lambda/shapegen/TTShape.java | 102 ++ .../vm/DefaultMethodRegressionTests.java | 130 ++ .../jdk/lambda/vm/DefaultMethodsTest.java | 810 ++++++++++ .../lambda/vm/InterfaceAccessFlagsTest.java | 90 ++ jdk/test/jdk/lambda/vm/StrictfpDefault.java | 32 + 128 files changed, 23386 insertions(+) create mode 100644 jdk/test/java/util/concurrent/atomic/AtomicReferenceTest.java create mode 100644 jdk/test/java/util/stream/bootlib/TEST.properties create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/CollectorOps.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestDataProvider.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestScenario.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/FlagDeclaringOp.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestDataProvider.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestScenario.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/IntermediateTestOp.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/LambdaTestHelpers.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestDataProvider.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestScenario.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/OpTestCase.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/SpliteratorTestHelper.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/StatefulTestOp.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/StatelessTestOp.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/StreamOpFlagTestHelper.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestDataProvider.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/TestData.java create mode 100644 jdk/test/java/util/stream/bootlib/java/util/stream/TestFlagExpectedOp.java create mode 100644 jdk/test/java/util/stream/boottest/TEST.properties create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/DoubleNodeTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/FlagOpTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/IntNodeTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/LongNodeTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/NodeBuilderTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/NodeTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/SpinedBufferTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/StreamFlagsTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/StreamOpFlagsTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/StreamReuseTest.java create mode 100644 jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java create mode 100644 jdk/test/java/util/stream/test/TEST.properties create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/DeserializeMethodTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/MHProxiesTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/FillableStringTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/MapTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/NullArgsTestCase.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ExplodeOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FilterOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FindAnyOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FindFirstOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ForEachOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/GroupByOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntReduceTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntSliceOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntUniqOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MapOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MatchOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MinMaxTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveAverageOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveSumTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/RangeTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceByOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorLateBindingFailFastTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTraversingAndSplittingTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamLinkTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamParSeqTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SummaryStatisticsTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/TabulatorsTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/TeeOpTest.java create mode 100644 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ToArrayOpTest.java create mode 100644 jdk/test/jdk/lambda/ArrayCtorRefTest.java create mode 100644 jdk/test/jdk/lambda/FDTest.java create mode 100644 jdk/test/jdk/lambda/LambdaTranslationCompoundSamTest.java create mode 100644 jdk/test/jdk/lambda/LambdaTranslationInInterface.java create mode 100644 jdk/test/jdk/lambda/LambdaTranslationInnerConstructor.java create mode 100644 jdk/test/jdk/lambda/LambdaTranslationTest1.java create mode 100644 jdk/test/jdk/lambda/LambdaTranslationTest2.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestFDCCE.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestInnerDefault.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestInnerInstance.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestInnerVarArgsThis.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestInstance.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestInstanceMethod.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestKinds.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestNew.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestNewInner.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestSueCase1.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestSueCase2.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestSueCase4.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestSuper.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestSuperDefault.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestTypeConversion.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestVarArgs.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestVarArgsExt.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestVarArgsSuper.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestVarArgsSuperDefault.java create mode 100644 jdk/test/jdk/lambda/MethodReferenceTestVarArgsThis.java create mode 100644 jdk/test/jdk/lambda/TEST.properties create mode 100644 jdk/test/jdk/lambda/TestInnerCtorRef.java create mode 100644 jdk/test/jdk/lambda/TestPrivateCtorRef.java create mode 100644 jdk/test/jdk/lambda/separate/AttributeInjector.java create mode 100644 jdk/test/jdk/lambda/separate/ClassFile.java create mode 100644 jdk/test/jdk/lambda/separate/ClassFilePreprocessor.java create mode 100644 jdk/test/jdk/lambda/separate/ClassToInterfaceConverter.java create mode 100644 jdk/test/jdk/lambda/separate/Compiler.java create mode 100644 jdk/test/jdk/lambda/separate/DirectedClassLoader.java create mode 100644 jdk/test/jdk/lambda/separate/SourceModel.java create mode 100644 jdk/test/jdk/lambda/separate/TestHarness.java create mode 100644 jdk/test/jdk/lambda/shapegen/ClassCase.java create mode 100644 jdk/test/jdk/lambda/shapegen/Hierarchy.java create mode 100644 jdk/test/jdk/lambda/shapegen/HierarchyGenerator.java create mode 100644 jdk/test/jdk/lambda/shapegen/Rule.java create mode 100644 jdk/test/jdk/lambda/shapegen/RuleGroup.java create mode 100644 jdk/test/jdk/lambda/shapegen/TTNode.java create mode 100644 jdk/test/jdk/lambda/shapegen/TTParser.java create mode 100644 jdk/test/jdk/lambda/shapegen/TTShape.java create mode 100644 jdk/test/jdk/lambda/vm/DefaultMethodRegressionTests.java create mode 100644 jdk/test/jdk/lambda/vm/DefaultMethodsTest.java create mode 100644 jdk/test/jdk/lambda/vm/InterfaceAccessFlagsTest.java create mode 100644 jdk/test/jdk/lambda/vm/StrictfpDefault.java diff --git a/jdk/test/Makefile b/jdk/test/Makefile index 2edcc8ffddc..51529b7c5f5 100644 --- a/jdk/test/Makefile +++ b/jdk/test/Makefile @@ -517,6 +517,7 @@ jdk_other: $(call TestDirs, \ javax/xml/soap \ javax/xml/ws com/sun/internal/ws com/sun/org/glassfish \ jdk/asm \ + jdk/lambda \ com/sun/org/apache/xerces \ com/sun/corba \ com/sun/tracing \ diff --git a/jdk/test/java/util/concurrent/atomic/AtomicReferenceTest.java b/jdk/test/java/util/concurrent/atomic/AtomicReferenceTest.java new file mode 100644 index 00000000000..4a455d9e909 --- /dev/null +++ b/jdk/test/java/util/concurrent/atomic/AtomicReferenceTest.java @@ -0,0 +1,58 @@ +/* + * 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. + * + * 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. + */ + +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.UnaryOperator; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/* + * @test + * @summary Test Map default methods + * @run testng AtomicReferenceTest + * @author Jim Gish + */ +public class AtomicReferenceTest { + + /** + * Test of updateAndGet method, of class AtomicReference. + */ + @Test + public void testUpdateAndGet() { + AtomicReference instance = new AtomicReference<>(3); + assertEquals((int) instance.get(), 3); + assertEquals((int) instance.updateAndGet(x -> x + 2), 5); + assertEquals((int) instance.get(), 5); + } + + /** + * Test of getAndUpdate method, of class AtomicReference. + */ + @Test + public void testGetAndUpdate() { + AtomicReference instance = new AtomicReference<>(3); + assertEquals((int) instance.get(), 3); + assertEquals((int) instance.getAndUpdate(x -> x + 3), 3); + assertEquals((int) instance.get(), 6); + } +} diff --git a/jdk/test/java/util/stream/bootlib/TEST.properties b/jdk/test/java/util/stream/bootlib/TEST.properties new file mode 100644 index 00000000000..a50c2e89a8d --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/TEST.properties @@ -0,0 +1,3 @@ +# This file identifies root(s) of the test-ng hierarchy. + +bootclasspath.dirs = . diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/CollectorOps.java b/jdk/test/java/util/stream/bootlib/java/util/stream/CollectorOps.java new file mode 100644 index 00000000000..c8494150e41 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/CollectorOps.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import org.testng.Assert; + +import java.util.Spliterator; +import java.util.function.IntFunction; + +/** Test helper class for java.util.stream test framework */ +public final class CollectorOps { + private CollectorOps() { } + + public static StatefulTestOp collector() { + return new StatefulCollector<>(0, StreamShape.REFERENCE); + } + + /* Utility classes for collecting output of intermediate pipeline stages */ + public static class StatefulCollector implements StatefulTestOp { + private final int opFlags; + private final StreamShape inputShape; + + public StatefulCollector(int opFlags, StreamShape inputShape) { + this.opFlags = opFlags; + this.inputShape = inputShape; + } + + @Override + public StreamShape inputShape() { + return inputShape; + } + + @Override + public StreamShape outputShape() { + return inputShape; + } + + @Override + public int opGetFlags() { + return opFlags; + } + + @Override + public Sink opWrapSink(int flags, boolean parallel, Sink sink) { + return sink; + } + + @Override + public Node opEvaluateParallel(PipelineHelper helper, + Spliterator spliterator, + IntFunction generator) { + return helper.evaluate(spliterator, false, generator); + } + } + + public static class TestParallelSizedOp extends StatefulCollector { + public TestParallelSizedOp() { + this(StreamShape.REFERENCE); + } + + protected TestParallelSizedOp(StreamShape shape) { + super(0, shape); + } + + @Override + public Node opEvaluateParallel(PipelineHelper helper, + Spliterator spliterator, + IntFunction generator) { + int flags = helper.getStreamAndOpFlags(); + + Assert.assertTrue(StreamOpFlag.SIZED.isKnown(flags)); + return super.opEvaluateParallel(helper, spliterator, generator); + } + + public static class OfInt extends TestParallelSizedOp { + public OfInt() { + super(StreamShape.INT_VALUE); + } + } + + public static class OfLong extends TestParallelSizedOp { + public OfLong() { + super(StreamShape.LONG_VALUE); + } + } + + public static class OfDouble extends TestParallelSizedOp { + public OfDouble() { + super(StreamShape.DOUBLE_VALUE); + } + } + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestDataProvider.java new file mode 100644 index 00000000000..da108752d26 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestDataProvider.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2013, 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. + * + * 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 java.util.stream; + +import org.testng.annotations.DataProvider; + +import java.util.*; +import java.util.Spliterators; +import java.util.function.Supplier; + +/** TestNG DataProvider for double-valued streams */ +public class DoubleStreamTestDataProvider { + private static final double[] to0 = new double[0]; + private static final double[] to1 = new double[1]; + private static final double[] to10 = new double[10]; + private static final double[] to100 = new double[100]; + private static final double[] to1000 = new double[1000]; + private static final double[] reversed = new double[100]; + private static final double[] ones = new double[100]; + private static final double[] twice = new double[200]; + private static final double[] pseudoRandom; + + private static final Object[][] testData; + private static final Object[][] spliteratorTestData; + + static { + double[][] arrays = {to0, to1, to10, to100, to1000}; + for (double[] arr : arrays) { + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + } + for (int i = 0; i < reversed.length; i++) { + reversed[i] = reversed.length - i; + } + for (int i = 0; i < ones.length; i++) { + ones[i] = 1; + } + System.arraycopy(to100, 0, twice, 0, to100.length); + System.arraycopy(to100, 0, twice, to100.length, to100.length); + pseudoRandom = new double[LambdaTestHelpers.LONG_STRING.length()]; + for (int i = 0; i < LambdaTestHelpers.LONG_STRING.length(); i++) { + pseudoRandom[i] = (double) LambdaTestHelpers.LONG_STRING.charAt(i); + } + } + + static final Object[][] arrays = { + {"empty", to0}, + {"0..1", to1}, + {"0..10", to10}, + {"0..100", to100}, + {"0..1000", to1000}, + {"100x[1]", ones}, + {"2x[0..100]", twice}, + {"reverse 0..100", reversed}, + {"pseudorandom", pseudoRandom} + }; + + static { + { + List list = new ArrayList<>(); + for (Object[] data : arrays) { + final Object name = data[0]; + final double[] doubles = (double[]) data[1]; + + list.add(new Object[]{"array:" + name, + TestData.Factory.ofArray("array:" + name, doubles)}); + + SpinedBuffer.OfDouble isl = new SpinedBuffer.OfDouble(); + for (double i : doubles) { + isl.accept(i); + } + list.add(new Object[]{"SpinedList:" + name, + TestData.Factory.ofSpinedBuffer("SpinedList:" + name, isl)}); + + list.add(streamDataDescr("Primitives.range(0,l): " + doubles.length, + () -> DoubleStream.range(0, doubles.length))); + list.add(streamDataDescr("Primitives.range(0,l,2): " + doubles.length, + () -> DoubleStream.range(0, doubles.length, 2))); + list.add(streamDataDescr("Primitives.range(0,l,3): " + doubles.length, + () -> DoubleStream.range(0, doubles.length, 3))); + list.add(streamDataDescr("Primitives.range(0,l,7): " + doubles.length, + () -> DoubleStream.range(0, doubles.length, 7))); + } + testData = list.toArray(new Object[0][]); + } + + { + List spliterators = new ArrayList<>(); + for (Object[] data : arrays) { + final Object name = data[0]; + final double[] doubles = (double[]) data[1]; + + SpinedBuffer.OfDouble isl = new SpinedBuffer.OfDouble(); + for (double i : doubles) { + isl.accept(i); + } + + spliterators.add(splitDescr("Arrays.s(array):" + name, + () -> Arrays.spliterator(doubles))); + spliterators.add(splitDescr("Arrays.s(array,o,l):" + name, + () -> Arrays.spliterator(doubles, 0, doubles.length / 2))); + + spliterators.add(splitDescr("SpinedBuffer.s():" + name, + () -> isl.spliterator())); + + spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator(), size):" + name, + () -> Spliterators.spliterator(isl.iterator(), doubles.length, 0))); + spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name, + () -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0))); + + spliterators.add(splitDescr("Primitives.range(0,l):" + name, + () -> DoubleStream.range(0, doubles.length).spliterator())); + spliterators.add(splitDescr("Primitives.range(0,l,2):" + name, + () -> DoubleStream.range(0, doubles.length, 2).spliterator())); + spliterators.add(splitDescr("Primitives.range(0,l,3):" + name, + () -> DoubleStream.range(0, doubles.length, 3).spliterator())); + spliterators.add(splitDescr("Primitives.range(0,l,7):" + name, + () -> DoubleStream.range(0, doubles.length, 7).spliterator())); + // Need more! + } + spliteratorTestData = spliterators.toArray(new Object[0][]); + } + + } + + static Object[] streamDataDescr(String description, Supplier s) { + return new Object[] { description, TestData.Factory.ofDoubleSupplier(description, s) }; + } + + static Object[] splitDescr(String description, Supplier s) { + return new Object[] { description, s }; + } + + // Return an array of ( String name, DoubleStreamTestData ) + @DataProvider(name = "DoubleStreamTestData") + public static Object[][] makeDoubleStreamTestData() { + return testData; + } + + // returns an array of (String name, Supplier>) + @DataProvider(name = "DoubleSpliterator") + public static Object[][] spliteratorProvider() { + return spliteratorTestData; + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestScenario.java b/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestScenario.java new file mode 100644 index 00000000000..5e431b1325e --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestScenario.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2013, 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. + * + * 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 java.util.stream; + +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.Function; + +/** + * Test scenarios for double streams. + * + * Each scenario is provided with a data source, a function that maps a fresh + * stream (as provided by the data source) to a new stream, and a sink to + * receive results. Each scenario describes a different way of computing the + * stream contents. The test driver will ensure that all scenarios produce + * the same output (modulo allowable differences in ordering). + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public enum DoubleStreamTestScenario implements OpTestCase.BaseStreamTestScenario { + + STREAM_FOR_EACH(false) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + DoubleStream s = m.apply(data.stream()); + if (s.isParallel()) { + s = s.sequential(); + } + s.forEach(b); + } + }, + + STREAM_TO_ARRAY(false) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + for (double t : m.apply(data.stream()).toArray()) { + b.accept(t); + } + } + }, + + STREAM_ITERATOR(false) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + for (PrimitiveIterator.OfDouble seqIter = m.apply(data.stream()).iterator(); seqIter.hasNext(); ) + b.accept(seqIter.nextDouble()); + } + }, + + // Wrap as stream, and spliterate then iterate in pull mode + STREAM_SPLITERATOR(false) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + for (Spliterator.OfDouble spl = m.apply(data.stream()).spliterator(); spl.tryAdvance(b); ) { + } + } + }, + + // Wrap as stream, spliterate, then split a few times mixing advances with forEach + STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(data.stream()).spliterator()); + } + }, + + // Wrap as stream, and spliterate then iterate in pull mode + STREAM_SPLITERATOR_FOREACH(false) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + m.apply(data.stream()).spliterator().forEachRemaining(b); + } + }, + + PAR_STREAM_SEQUENTIAL_FOR_EACH(true) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + m.apply(data.parallelStream()).sequential().forEach(b); + } + }, + + // Wrap as parallel stream + forEachOrdered + PAR_STREAM_FOR_EACH_ORDERED(true) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + // @@@ Want to explicitly select ordered equalator + m.apply(data.parallelStream()).forEachOrdered(b); + } + }, + + // Wrap as stream, and spliterate then iterate sequentially + PAR_STREAM_SPLITERATOR(true) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + for (Spliterator.OfDouble spl = m.apply(data.parallelStream()).spliterator(); spl.tryAdvance(b); ) { + } + } + }, + + // Wrap as stream, and spliterate then iterate sequentially + PAR_STREAM_SPLITERATOR_FOREACH(true) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + m.apply(data.parallelStream()).spliterator().forEachRemaining(b); + } + }, + + PAR_STREAM_TO_ARRAY(true) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + for (double t : m.apply(data.parallelStream()).toArray()) + b.accept(t); + } + }, + + // Wrap as parallel stream, get the spliterator, wrap as a stream + toArray + PAR_STREAM_SPLITERATOR_STREAM_TO_ARRAY(true) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + DoubleStream s = m.apply(data.parallelStream()); + Spliterator.OfDouble sp = s.spliterator(); + DoubleStream ss = StreamSupport.doubleParallelStream(() -> sp, + StreamOpFlag.toCharacteristics(OpTestCase.getStreamFlags(s)) + | (sp.getExactSizeIfKnown() < 0 ? 0 : Spliterator.SIZED)); + for (double t : ss.toArray()) + b.accept(t); + } + }, + + PAR_STREAM_TO_ARRAY_CLEAR_SIZED(true) { + > + void _run(TestData data, DoubleConsumer b, Function m) { + S_IN pipe1 = (S_IN) OpTestCase.chain(data.parallelStream(), + new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape())); + DoubleStream pipe2 = m.apply(pipe1); + + for (double t : pipe2.toArray()) + b.accept(t); + } + },; + + private boolean isParallel; + + DoubleStreamTestScenario(boolean isParallel) { + this.isParallel = isParallel; + } + + public StreamShape getShape() { + return StreamShape.DOUBLE_VALUE; + } + + public boolean isParallel() { + return isParallel; + } + + public , S_OUT extends BaseStream> + void run(TestData data, Consumer b, Function m) { + _run(data, (DoubleConsumer) b, (Function) m); + } + + abstract > + void _run(TestData data, DoubleConsumer b, Function m); + +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/FlagDeclaringOp.java b/jdk/test/java/util/stream/bootlib/java/util/stream/FlagDeclaringOp.java new file mode 100644 index 00000000000..a9882c8b64c --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/FlagDeclaringOp.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +/** + * An operation that injects or clears flags but otherwise performs no operation on elements. + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public class FlagDeclaringOp implements StatelessTestOp { + private final int flags; + private final StreamShape shape; + + public FlagDeclaringOp(int flags) { + this(flags, StreamShape.REFERENCE); + } + + public FlagDeclaringOp(int flags, StreamShape shape) { + this.flags = flags; + this.shape = shape; + } + + @Override + public StreamShape outputShape() { + return shape; + } + + @Override + public StreamShape inputShape() { + return shape; + } + + @Override + public int opGetFlags() { + return flags; + } + + @Override + public Sink opWrapSink(int flags, boolean parallel, Sink sink) { + return sink; + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestDataProvider.java new file mode 100644 index 00000000000..3ef2acfbe34 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestDataProvider.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import org.testng.annotations.DataProvider; + +import java.util.*; +import java.util.Spliterators; +import java.util.function.Supplier; + +/** TestNG DataProvider for int-valued streams */ +public class IntStreamTestDataProvider { + private static final int[] to0 = new int[0]; + private static final int[] to1 = new int[1]; + private static final int[] to10 = new int[10]; + private static final int[] to100 = new int[100]; + private static final int[] to1000 = new int[1000]; + private static final int[] reversed = new int[100]; + private static final int[] ones = new int[100]; + private static final int[] twice = new int[200]; + private static final int[] pseudoRandom; + + private static final Object[][] testData; + private static final Object[][] spliteratorTestData; + + static { + int[][] arrays = {to0, to1, to10, to100, to1000}; + for (int[] arr : arrays) { + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + } + for (int i = 0; i < reversed.length; i++) { + reversed[i] = reversed.length - i; + } + for (int i = 0; i < ones.length; i++) { + ones[i] = 1; + } + System.arraycopy(to100, 0, twice, 0, to100.length); + System.arraycopy(to100, 0, twice, to100.length, to100.length); + pseudoRandom = new int[LambdaTestHelpers.LONG_STRING.length()]; + for (int i = 0; i < LambdaTestHelpers.LONG_STRING.length(); i++) { + pseudoRandom[i] = (int) LambdaTestHelpers.LONG_STRING.charAt(i); + } + } + + static final Object[][] arrays = { + {"empty", to0}, + {"0..1", to1}, + {"0..10", to10}, + {"0..100", to100}, + {"0..1000", to1000}, + {"100x[1]", ones}, + {"2x[0..100]", twice}, + {"reverse 0..100", reversed}, + {"pseudorandom", pseudoRandom} + }; + + static { + { + List list = new ArrayList<>(); + for (Object[] data : arrays) { + final Object name = data[0]; + final int[] ints = (int[]) data[1]; + + list.add(new Object[]{"array:" + + name, TestData.Factory.ofArray("array:" + name, ints)}); + + SpinedBuffer.OfInt isl = new SpinedBuffer.OfInt(); + for (int i : ints) { + isl.accept(i); + } + list.add(new Object[]{"SpinedList:" + name, + TestData.Factory.ofSpinedBuffer("SpinedList:" + name, isl)}); + + list.add(streamDataDescr("IntStream.intRange(0,l): " + ints.length, + () -> IntStream.range(0, ints.length))); + list.add(streamDataDescr("IntStream.intRange(0,l,2): " + ints.length, + () -> IntStream.range(0, ints.length, 2))); + list.add(streamDataDescr("IntStream.intRange(0,l,3): " + ints.length, + () -> IntStream.range(0, ints.length, 3))); + list.add(streamDataDescr("IntStream.intRange(0,l,7): " + ints.length, + () -> IntStream.range(0, ints.length, 7))); + } + testData = list.toArray(new Object[0][]); + } + + { + List spliterators = new ArrayList<>(); + for (Object[] data : arrays) { + final Object name = data[0]; + final int[] ints = (int[]) data[1]; + + SpinedBuffer.OfInt isl = new SpinedBuffer.OfInt(); + for (int i : ints) { + isl.accept(i); + } + + spliterators.add(splitDescr("Arrays.s(array):" + name, + () -> Arrays.spliterator(ints))); + spliterators.add(splitDescr("Arrays.s(array,o,l):" + name, + () -> Arrays.spliterator(ints, 0, ints.length / 2))); + + spliterators.add(splitDescr("SpinedBuffer.s():" + name, + () -> isl.spliterator())); + + spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator(), size):" + name, + () -> Spliterators.spliterator(isl.iterator(), ints.length, 0))); + spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name, + () -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0))); + + spliterators.add(splitDescr("IntStream.intRange(0,l):" + name, + () -> IntStream.range(0, ints.length).spliterator())); + spliterators.add(splitDescr("IntStream.intRange(0,l,2):" + name, + () -> IntStream.range(0, ints.length, 2).spliterator())); + spliterators.add(splitDescr("IntStream.intRange(0,l,3):" + name, + () -> IntStream.range(0, ints.length, 3).spliterator())); + spliterators.add(splitDescr("IntStream.intRange(0,l,7):" + name, + () -> IntStream.range(0, ints.length, 7).spliterator())); + + // Need more! + } + spliteratorTestData = spliterators.toArray(new Object[0][]); + } + + } + + static Object[] streamDataDescr(String description, Supplier s) { + return new Object[] { description, TestData.Factory.ofIntSupplier(description, s) }; + } + + static Object[] splitDescr(String description, Supplier s) { + return new Object[] { description, s }; + } + + // Return an array of ( String name, IntStreamTestData ) + @DataProvider(name = "IntStreamTestData") + public static Object[][] makeIntStreamTestData() { + return testData; + } + + // returns an array of (String name, Supplier>) + @DataProvider(name = "IntSpliterator") + public static Object[][] spliteratorProvider() { + return spliteratorTestData; + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestScenario.java b/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestScenario.java new file mode 100644 index 00000000000..c12a4ec1ec9 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestScenario.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.IntConsumer; + +/** + * Test scenarios for int streams. + * + * Each scenario is provided with a data source, a function that maps a fresh + * stream (as provided by the data source) to a new stream, and a sink to + * receive results. Each scenario describes a different way of computing the + * stream contents. The test driver will ensure that all scenarios produce + * the same output (modulo allowable differences in ordering). + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public enum IntStreamTestScenario implements OpTestCase.BaseStreamTestScenario { + + STREAM_FOR_EACH(false) { + > + void _run(TestData data, IntConsumer b, Function m) { + IntStream s = m.apply(data.stream()); + if (s.isParallel()) { + s = s.sequential(); + } + s.forEach(b); + } + }, + + STREAM_TO_ARRAY(false) { + > + void _run(TestData data, IntConsumer b, Function m) { + for (int t : m.apply(data.stream()).toArray()) { + b.accept(t); + } + } + }, + + STREAM_ITERATOR(false) { + > + void _run(TestData data, IntConsumer b, Function m) { + for (PrimitiveIterator.OfInt seqIter = m.apply(data.stream()).iterator(); seqIter.hasNext(); ) + b.accept(seqIter.nextInt()); + } + }, + + // Wrap as stream, and spliterate then iterate in pull mode + STREAM_SPLITERATOR(false) { + > + void _run(TestData data, IntConsumer b, Function m) { + for (Spliterator.OfInt spl = m.apply(data.stream()).spliterator(); spl.tryAdvance(b); ) { + } + } + }, + + // Wrap as stream, spliterate, then split a few times mixing advances with forEach + STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) { + > + void _run(TestData data, IntConsumer b, Function m) { + SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(data.stream()).spliterator()); + } + }, + + // Wrap as stream, and spliterate then iterate in pull mode + STREAM_SPLITERATOR_FOREACH(false) { + > + void _run(TestData data, IntConsumer b, Function m) { + m.apply(data.stream()).spliterator().forEachRemaining(b); + } + }, + + PAR_STREAM_SEQUENTIAL_FOR_EACH(true) { + > + void _run(TestData data, IntConsumer b, Function m) { + m.apply(data.parallelStream()).sequential().forEach(b); + } + }, + + // Wrap as parallel stream + forEachOrdered + PAR_STREAM_FOR_EACH_ORDERED(true) { + > + void _run(TestData data, IntConsumer b, Function m) { + // @@@ Want to explicitly select ordered equalator + m.apply(data.parallelStream()).forEachOrdered(b); + } + }, + + // Wrap as stream, and spliterate then iterate sequentially + PAR_STREAM_SPLITERATOR(true) { + > + void _run(TestData data, IntConsumer b, Function m) { + for (Spliterator.OfInt spl = m.apply(data.parallelStream()).spliterator(); spl.tryAdvance(b); ) { + } + } + }, + + // Wrap as stream, and spliterate then iterate sequentially + PAR_STREAM_SPLITERATOR_FOREACH(true) { + > + void _run(TestData data, IntConsumer b, Function m) { + m.apply(data.parallelStream()).spliterator().forEachRemaining(b); + } + }, + + PAR_STREAM_TO_ARRAY(true) { + > + void _run(TestData data, IntConsumer b, Function m) { + for (int t : m.apply(data.parallelStream()).toArray()) + b.accept(t); + } + }, + + // Wrap as parallel stream, get the spliterator, wrap as a stream + toArray + PAR_STREAM_SPLITERATOR_STREAM_TO_ARRAY(true) { + > + void _run(TestData data, IntConsumer b, Function m) { + IntStream s = m.apply(data.parallelStream()); + Spliterator.OfInt sp = s.spliterator(); + IntStream ss = StreamSupport.intParallelStream(() -> sp, + StreamOpFlag.toCharacteristics(OpTestCase.getStreamFlags(s)) + | (sp.getExactSizeIfKnown() < 0 ? 0 : Spliterator.SIZED)); + for (int t : ss.toArray()) + b.accept(t); + } + }, + + PAR_STREAM_TO_ARRAY_CLEAR_SIZED(true) { + > + void _run(TestData data, IntConsumer b, Function m) { + S_IN pipe1 = (S_IN) OpTestCase.chain(data.parallelStream(), + new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape())); + IntStream pipe2 = m.apply(pipe1); + + for (int t : pipe2.toArray()) + b.accept(t); + } + },; + + private boolean isParallel; + + IntStreamTestScenario(boolean isParallel) { + this.isParallel = isParallel; + } + + public StreamShape getShape() { + return StreamShape.INT_VALUE; + } + + public boolean isParallel() { + return isParallel; + } + + public , S_OUT extends BaseStream> + void run(TestData data, Consumer b, Function m) { + _run(data, (IntConsumer) b, (Function) m); + } + + abstract > + void _run(TestData data, IntConsumer b, Function m); + +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/IntermediateTestOp.java b/jdk/test/java/util/stream/bootlib/java/util/stream/IntermediateTestOp.java new file mode 100644 index 00000000000..1ed04c7d4e1 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/IntermediateTestOp.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +/** + * A base type for test operations + */ +interface IntermediateTestOp { + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static AbstractPipeline chain(AbstractPipeline upstream, + IntermediateTestOp op) { + if (op instanceof StatelessTestOp) + return StatelessTestOp.chain(upstream, (StatelessTestOp) op); + + if (op instanceof StatefulTestOp) + return StatefulTestOp.chain(upstream, (StatefulTestOp) op); + + throw new IllegalStateException("Unknown test op type: " + op.getClass().getName()); + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/LambdaTestHelpers.java b/jdk/test/java/util/stream/bootlib/java/util/stream/LambdaTestHelpers.java new file mode 100644 index 00000000000..f1d8ffe81c6 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/LambdaTestHelpers.java @@ -0,0 +1,471 @@ +/* + * Copyright (c) 1997, 2010, 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. + * + * 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 java.util.stream; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.BiPredicate; +import java.util.function.BinaryOperator; +import java.util.function.Consumer; +import java.util.function.DoubleBinaryOperator; +import java.util.function.DoubleConsumer; +import java.util.function.DoublePredicate; +import java.util.function.Function; +import java.util.function.IntBinaryOperator; +import java.util.function.IntConsumer; +import java.util.function.IntFunction; +import java.util.function.IntPredicate; +import java.util.function.IntUnaryOperator; +import java.util.function.LongBinaryOperator; +import java.util.function.LongConsumer; +import java.util.function.LongPredicate; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.function.ToDoubleFunction; +import java.util.function.ToIntFunction; +import java.util.function.ToLongFunction; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * LambdaTestHelpers -- assertion methods and useful objects for lambda test cases + */ +public class LambdaTestHelpers { + public static final String LONG_STRING = "When in the Course of human events it becomes necessary for one people to dissolve the political bands which have connected them with another and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation."; + + @SuppressWarnings("rawtypes") + public static final Consumer bEmpty = x -> { }; + @SuppressWarnings("rawtypes") + public static final IntConsumer bIntEmpty = x -> { }; + @SuppressWarnings("rawtypes") + public static final BiConsumer bBiEmpty = (x,y) -> { }; + @SuppressWarnings("rawtypes") + public static final Consumer bHashCode = x -> { Objects.hashCode(x); }; + @SuppressWarnings("rawtypes") + public static final BiConsumer bBiHashCode = (x,y) -> { Objects.hash(x, y); }; + public static final Function mZero = x -> 0; + public static final Function mId = x -> x; + public static final Function mDoubler = x -> x * 2; + public static final Function> mfId = e -> Collections.singletonList(e).stream(); + public static final Function> mfNull = e -> Collections.emptyList().stream(); + public static final Function> mfLt = e -> { + List l = new ArrayList<>(); + for (int i=0; i imDoubler = x -> x * 2; + public static final ToLongFunction lmDoubler = x -> x * 2; + public static final ToDoubleFunction dmDoubler = x -> x * 2; + public static final Predicate pFalse = x -> false; + public static final Predicate pTrue = x -> true; + public static final Predicate pEven = x -> 0 == x % 2; + public static final Predicate pOdd = x -> 1 == x % 2; + public static final IntPredicate ipFalse = x -> false; + public static final IntPredicate ipTrue = x -> true; + public static final IntPredicate ipEven = x -> 0 == x % 2; + public static final IntPredicate ipOdd = x -> 1 == x % 2; + public static final LongPredicate lpFalse = x -> false; + public static final LongPredicate lpTrue = x -> true; + public static final LongPredicate lpEven = x -> 0 == x % 2; + public static final LongPredicate lpOdd = x -> 1 == x % 2; + public static final DoublePredicate dpFalse = x -> false; + public static final DoublePredicate dpTrue = x -> true; + public static final DoublePredicate dpEven = x -> 0 == ((long) x) % 2; + public static final DoublePredicate dpOdd = x -> 1 == ((long) x) % 2; + public static final BinaryOperator rPlus = (x, y) -> x+y; + public static final BinaryOperator rMax = (x, y) -> Math.max(x, y); + public static final BinaryOperator rMin = (x, y) -> Math.min(x,y); + public static final IntBinaryOperator irPlus = (x, y) -> x+y; + public static final IntBinaryOperator irMax = (x, y) -> Math.max(x, y); + public static final IntBinaryOperator irMin = (x, y) -> Math.min(x,y); + public static final IntUnaryOperator irDoubler = x -> x * 2; + public static final LongBinaryOperator lrPlus = (x, y) -> x+y; + public static final DoubleBinaryOperator drPlus = (x, y) -> x+y; + public static final Comparator cInteger = (a, b) -> Integer.compare(a, b); + public static final BiPredicate bipFalse = (x, y) -> false; + public static final BiPredicate bipTrue = (x, y) -> true; + public static final BiPredicate bipBothEven = (x, y) -> 0 == (x % 2 + y % 2); + public static final BiPredicate bipBothOdd = (x, y) -> 2 == (x % 2 + y % 2); + public static final BiPredicate bipSameString = (x, y) -> String.valueOf(x).equals(String.valueOf(y)); + + public static final IntFunction integerArrayGenerator = s -> new Integer[s]; + + public static final IntFunction objectArrayGenerator = s -> new Object[s]; + + public static final Function> flattenChars = string -> { + List l = new ArrayList<>(); + for (int i=0; i flattenInt + = string -> IntStream.range(0, string.length()).map(string::charAt); + + public static Function forPredicate(Predicate predicate, R forTrue, R forFalse) { + Objects.requireNonNull(predicate); + + return t -> predicate.test(t) ? forTrue : forFalse; + } + + public static Function identity() { + return t -> t; + } + + public static Function compose(Function after, Function before) { + Objects.requireNonNull(before); + return (V v) -> after.apply(before.apply(v)); + } + + public static List empty() { + ArrayList list = new ArrayList<>(); + list.add(null); + return list; + } + + public static List countTo(int n) { + return range(1, n); + } + + public static List range(int l, int u) { + ArrayList list = new ArrayList<>(u - l + 1); + for (int i=l; i<=u; i++) { + list.add(i); + } + return list; + } + + public static List repeat(int value, int n) { + ArrayList list = new ArrayList<>(n); + for (int i=1; i<=n; i++) { + list.add(value); + } + return list; + } + + public static List asDoubles(List integers) { + ArrayList list = new ArrayList<>(); + for (Integer i : integers) { + list.add((double) i); + } + return list; + } + + public static List asLongs(List integers) { + ArrayList list = new ArrayList<>(); + for (Integer i : integers) { + list.add((long) i); + } + return list; + } + + public static void assertCountSum(Stream it, int count, int sum) { + assertCountSum(it.iterator(), count, sum); + } + + public static void assertCountSum(Iterable it, int count, int sum) { + assertCountSum(it.iterator(), count, sum); + } + + public static void assertCountSum(Iterator it, int count, int sum) { + int c = 0; + int s = 0; + while (it.hasNext()) { + int i = (Integer) it.next(); + c++; + s += i; + } + + assertEquals(c, count); + assertEquals(s, sum); + } + + public static void assertConcat(Iterator it, String result) { + StringBuilder sb = new StringBuilder(); + while (it.hasNext()) { + sb.append(it.next()); + } + + assertEquals(result, sb.toString()); + } + + public static> void assertSorted(Iterator i) { + i = toBoxedList(i).iterator(); + + if (!i.hasNext()) + return; + T last = i.next(); + while (i.hasNext()) { + T t = i.next(); + assertTrue(last.compareTo(t) <= 0); + assertTrue(t.compareTo(last) >= 0); + last = t; + } + } + + public static void assertSorted(Iterator i, Comparator comp) { + if (i instanceof PrimitiveIterator.OfInt + || i instanceof PrimitiveIterator.OfDouble + || i instanceof PrimitiveIterator.OfLong) { + i = toBoxedList(i).iterator(); + } + + if (!i.hasNext()) + return; + T last = i.next(); + while (i.hasNext()) { + T t = i.next(); + assertTrue(comp.compare(last, t) <= 0); + assertTrue(comp.compare(t, last) >= 0); + last = t; + } + } + + public static> void assertSorted(Iterable iter) { + assertSorted(iter.iterator()); + } + + public static void assertSorted(Iterable iter, Comparator comp) { + assertSorted(iter.iterator(), comp); + } + + public static void assertUnique(Iterable iter) { + assertUnique(iter.iterator()); + } + + public static void assertUnique(Iterator iter) { + if (!iter.hasNext()) { + return; + } + + if (iter instanceof PrimitiveIterator.OfInt + || iter instanceof PrimitiveIterator.OfDouble + || iter instanceof PrimitiveIterator.OfLong) { + iter = toBoxedList(iter).iterator(); + } + + Set uniq = new HashSet<>(); + while(iter.hasNext()) { + T each = iter.next(); + assertTrue(!uniq.contains(each)); + uniq.add(each); + } + } + + public static void assertContents(Iterable actual, Iterable expected) { + if (actual instanceof Collection && expected instanceof Collection) { + assertEquals(actual, expected); + } else { + assertContents(actual.iterator(), expected.iterator()); + } + } + + public static void assertContents(Iterator actual, Iterator expected) { + assertEquals(toBoxedList(actual), toBoxedList(expected)); + } + + @SafeVarargs + @SuppressWarnings("varargs") + public static void assertContents(Iterator actual, T... expected) { + assertContents(actual, Arrays.asList(expected).iterator()); + } + + /** + * The all consuming consumer (rampant capitalist) that can accepting a reference or any primitive value. + */ + private static interface OmnivorousConsumer + extends Consumer, IntConsumer, LongConsumer, DoubleConsumer { } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static Consumer toBoxingConsumer(Consumer c) { + return (Consumer) new OmnivorousConsumer() { + @Override + public void accept(Object t) { + c.accept((T) t); + } + + @Override + public void accept(int t) { + accept((Object) t); + } + + @Override + public void accept(long t) { + accept((Object) t); + } + + @Override + public void accept(double t) { + accept((Object) t); + } + }; + } + + /** + * Convert an iterator to a list using forEach with an implementation of + * {@link java.util.stream.LambdaTestHelpers.OmnivorousConsumer}. + * + * This ensures equality comparisons for test results do not trip + * the boxing trip-wires. + */ + private static List toBoxedList(Iterator it) { + List l = new ArrayList<>(); + it.forEachRemaining(toBoxingConsumer(l::add)); + return l; + } + + /** + * Convert a spliterator to a list using forEach with an implementation of + * {@link java.util.stream.LambdaTestHelpers.OmnivorousConsumer}. + * + * This ensures equality comparisons for test results do not trip + * the boxing trip-wires. + */ + public static List toBoxedList(Spliterator sp) { + List l = new ArrayList<>(); + sp.forEachRemaining(toBoxingConsumer(l::add)); + return l; + } + + /** + * Convert an iterator to a multi-set, represented as a Map, using forEach with an implementation of + * {@link java.util.stream.LambdaTestHelpers.OmnivorousConsumer}. + * + * This ensures equality comparisons for test results do not trip + * the boxing trip-wires. + */ + @SuppressWarnings("unchecked") + private static Map toBoxedMultiset(Iterator it) { + Map result = new HashMap<>(); + + it.forEachRemaining(new OmnivorousConsumer() { + @Override + public void accept(T t) { + add(t); + } + + @Override + public void accept(int value) { + add(value); + } + + @Override + public void accept(long value) { + add(value); + } + + @Override + public void accept(double value) { + add(value); + } + + void add(Object o) { + if (result.containsKey(o)) + result.put(o, result.get(o) + 1); + else + result.put(o, 1); + } + + }); + + return (Map) result; + } + + @SuppressWarnings("unchecked") + public static void assertContentsEqual(Object a, Object b) { + if (a instanceof Iterable && b instanceof Iterable) + assertContents((Iterable) a, (Iterable) b); + else + assertEquals(a, b); + } + + public static void assertContentsUnordered(Iterable actual, Iterable expected) { + assertContentsUnordered(actual.iterator(), expected.iterator()); + } + + public static void assertContentsUnordered(Iterator actual, Iterator expected) { + assertEquals(toBoxedMultiset(actual), toBoxedMultiset(expected)); + } + + public static void launderAssertion(Runnable r, Supplier additionalInfo) { + try { + r.run(); + } + catch (AssertionError ae) { + AssertionError cloned = new AssertionError(ae.getMessage() + String.format("%n%s", additionalInfo.get())); + cloned.setStackTrace(ae.getStackTrace()); + if (ae.getCause() != null) + cloned.initCause(ae.getCause()); + throw cloned; + } + } + + public static > + List> permuteStreamFunctions(List> opFunctions) { + List>> opFunctionPermutations = perm(opFunctions); + + List> appliedFunctions = new ArrayList<>(); + for (List> fs : opFunctionPermutations) { + Function applied = s -> { + for (Function f : fs) { + s = f.apply(s); + } + return s; + }; + appliedFunctions.add(applied); + } + + return appliedFunctions; + } + + private static List sub(List l, int index) { + List subL = new ArrayList<>(l); + subL.remove(index); + return subL; + } + + public static List> perm(List l) { + List> result = new ArrayList<>(); + for (int i = 0; i < l.size(); i++) { + for (List perm : perm(sub(l, i))) { + perm.add(0, l.get(i)); + result.add(perm); + } + } + result.add(new ArrayList()); + + return result; + } + + public static String flagsToString(int flags) { + StringJoiner sj = new StringJoiner(", ", "StreamOpFlag[", "]"); + if (StreamOpFlag.DISTINCT.isKnown(flags)) sj.add("IS_DISTINCT"); + if (StreamOpFlag.ORDERED.isKnown(flags)) sj.add("IS_ORDERED"); + if (StreamOpFlag.SIZED.isKnown(flags)) sj.add("IS_SIZED"); + if (StreamOpFlag.SORTED.isKnown(flags)) sj.add("IS_SORTED"); + if (StreamOpFlag.SHORT_CIRCUIT.isKnown(flags)) sj.add("IS_SHORT_CIRCUIT"); + return sj.toString(); + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestDataProvider.java new file mode 100644 index 00000000000..f37a1108c50 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestDataProvider.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2013, 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. + * + * 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 java.util.stream; + +import org.testng.annotations.DataProvider; + +import java.util.*; +import java.util.Spliterators; +import java.util.function.Supplier; + +/** TestNG DataProvider for long-valued streams */ +public class LongStreamTestDataProvider { + private static final long[] to0 = new long[0]; + private static final long[] to1 = new long[1]; + private static final long[] to10 = new long[10]; + private static final long[] to100 = new long[100]; + private static final long[] to1000 = new long[1000]; + private static final long[] reversed = new long[100]; + private static final long[] ones = new long[100]; + private static final long[] twice = new long[200]; + private static final long[] pseudoRandom; + + private static final Object[][] testData; + private static final Object[][] spliteratorTestData; + + static { + long[][] arrays = {to0, to1, to10, to100, to1000}; + for (long[] arr : arrays) { + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + } + for (int i = 0; i < reversed.length; i++) { + reversed[i] = reversed.length - i; + } + for (int i = 0; i < ones.length; i++) { + ones[i] = 1; + } + System.arraycopy(to100, 0, twice, 0, to100.length); + System.arraycopy(to100, 0, twice, to100.length, to100.length); + pseudoRandom = new long[LambdaTestHelpers.LONG_STRING.length()]; + for (int i = 0; i < LambdaTestHelpers.LONG_STRING.length(); i++) { + pseudoRandom[i] = (long) LambdaTestHelpers.LONG_STRING.charAt(i); + } + } + + static final Object[][] arrays = { + {"empty", to0}, + {"0..1", to1}, + {"0..10", to10}, + {"0..100", to100}, + {"0..1000", to1000}, + {"100x[1]", ones}, + {"2x[0..100]", twice}, + {"reverse 0..100", reversed}, + {"pseudorandom", pseudoRandom} + }; + + static { + { + List list = new ArrayList<>(); + for (Object[] data : arrays) { + final Object name = data[0]; + final long[] longs = (long[]) data[1]; + + list.add(new Object[]{"array:" + name, + TestData.Factory.ofArray("array:" + name, longs)}); + + SpinedBuffer.OfLong isl = new SpinedBuffer.OfLong(); + for (long i : longs) { + isl.accept(i); + } + list.add(new Object[]{"SpinedList:" + name, + TestData.Factory.ofSpinedBuffer("SpinedList:" + name, isl)}); + + list.add(streamDataDescr("LongStream.longRange(0,l): " + longs.length, + () -> LongStream.range(0, longs.length))); + list.add(streamDataDescr("LongStream.longRange(0,l,2): " + longs.length, + () -> LongStream.range(0, longs.length, 2))); + list.add(streamDataDescr("LongStream.longRange(0,l,3): " + longs.length, + () -> LongStream.range(0, longs.length, 3))); + list.add(streamDataDescr("LongStream.longRange(0,l,7): " + longs.length, + () -> LongStream.range(0, longs.length, 7))); + } + testData = list.toArray(new Object[0][]); + } + + { + List spliterators = new ArrayList<>(); + for (Object[] data : arrays) { + final Object name = data[0]; + final long[] longs = (long[]) data[1]; + + SpinedBuffer.OfLong isl = new SpinedBuffer.OfLong(); + for (long i : longs) { + isl.accept(i); + } + + spliterators.add(splitDescr("Arrays.s(array):" + name, + () -> Arrays.spliterator(longs))); + spliterators.add(splitDescr("Arrays.s(array,o,l):" + name, + () -> Arrays.spliterator(longs, 0, longs.length / 2))); + + spliterators.add(splitDescr("SpinedBuffer.s():" + name, + () -> isl.spliterator())); + + spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator(), size):" + name, + () -> Spliterators.spliterator(isl.iterator(), longs.length, 0))); + spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name, + () -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0))); + + spliterators.add(splitDescr("LongStream.longRange(0,l):" + name, + () -> LongStream.range(0, longs.length).spliterator())); + spliterators.add(splitDescr("LongStream.longRange(0,l,2):" + name, + () -> LongStream.range(0, longs.length, 2).spliterator())); + spliterators.add(splitDescr("LongStream.longRange(0,l,3):" + name, + () -> LongStream.range(0, longs.length, 3).spliterator())); + spliterators.add(splitDescr("LongStream.longRange(0,l,7):" + name, + () -> LongStream.range(0, longs.length, 7).spliterator())); + // Need more! + } + spliteratorTestData = spliterators.toArray(new Object[0][]); + } + + } + + static Object[] streamDataDescr(String description, Supplier s) { + return new Object[] { description, TestData.Factory.ofLongSupplier(description, s) }; + } + + static Object[] splitDescr(String description, Supplier s) { + return new Object[] { description, s }; + } + + // Return an array of ( String name, LongStreamTestData ) + @DataProvider(name = "LongStreamTestData") + public static Object[][] makeLongStreamTestData() { + return testData; + } + + // returns an array of (String name, Supplier>) + @DataProvider(name = "LongSpliterator") + public static Object[][] spliteratorProvider() { + return spliteratorTestData; + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestScenario.java b/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestScenario.java new file mode 100644 index 00000000000..c32d6e82425 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestScenario.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2013, 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. + * + * 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 java.util.stream; + +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.LongConsumer; + +/** + * Test scenarios for long streams. + * + * Each scenario is provided with a data source, a function that maps a fresh + * stream (as provided by the data source) to a new stream, and a sink to + * receive results. Each scenario describes a different way of computing the + * stream contents. The test driver will ensure that all scenarios produce + * the same output (modulo allowable differences in ordering). + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public enum LongStreamTestScenario implements OpTestCase.BaseStreamTestScenario { + + STREAM_FOR_EACH(false) { + > + void _run(TestData data, LongConsumer b, Function m) { + LongStream s = m.apply(data.stream()); + if (s.isParallel()) { + s = s.sequential(); + } + s.forEach(b); + } + }, + + STREAM_TO_ARRAY(false) { + > + void _run(TestData data, LongConsumer b, Function m) { + for (long t : m.apply(data.stream()).toArray()) { + b.accept(t); + } + } + }, + + STREAM_ITERATOR(false) { + > + void _run(TestData data, LongConsumer b, Function m) { + for (PrimitiveIterator.OfLong seqIter = m.apply(data.stream()).iterator(); seqIter.hasNext(); ) + b.accept(seqIter.nextLong()); + } + }, + + // Wrap as stream, and spliterate then iterate in pull mode + STREAM_SPLITERATOR(false) { + > + void _run(TestData data, LongConsumer b, Function m) { + for (Spliterator.OfLong spl = m.apply(data.stream()).spliterator(); spl.tryAdvance(b); ) { + } + } + }, + + // Wrap as stream, spliterate, then split a few times mixing advances with forEach + STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) { + > + void _run(TestData data, LongConsumer b, Function m) { + SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(data.stream()).spliterator()); + } + }, + + // Wrap as stream, and spliterate then iterate in pull mode + STREAM_SPLITERATOR_FOREACH(false) { + > + void _run(TestData data, LongConsumer b, Function m) { + m.apply(data.stream()).spliterator().forEachRemaining(b); + } + }, + + PAR_STREAM_SEQUENTIAL_FOR_EACH(true) { + > + void _run(TestData data, LongConsumer b, Function m) { + m.apply(data.parallelStream()).sequential().forEach(b); + } + }, + + // Wrap as parallel stream + forEachOrdered + PAR_STREAM_FOR_EACH_ORDERED(true) { + > + void _run(TestData data, LongConsumer b, Function m) { + // @@@ Want to explicitly select ordered equalator + m.apply(data.parallelStream()).forEachOrdered(b); + } + }, + + // Wrap as stream, and spliterate then iterate sequentially + PAR_STREAM_SPLITERATOR(true) { + > + void _run(TestData data, LongConsumer b, Function m) { + for (Spliterator.OfLong spl = m.apply(data.parallelStream()).spliterator(); spl.tryAdvance(b); ) { + } + } + }, + + // Wrap as stream, and spliterate then iterate sequentially + PAR_STREAM_SPLITERATOR_FOREACH(true) { + > + void _run(TestData data, LongConsumer b, Function m) { + m.apply(data.parallelStream()).spliterator().forEachRemaining(b); + } + }, + + PAR_STREAM_TO_ARRAY(true) { + > + void _run(TestData data, LongConsumer b, Function m) { + for (long t : m.apply(data.parallelStream()).toArray()) + b.accept(t); + } + }, + + // Wrap as parallel stream, get the spliterator, wrap as a stream + toArray + PAR_STREAM_SPLITERATOR_STREAM_TO_ARRAY(true) { + > + void _run(TestData data, LongConsumer b, Function m) { + LongStream s = m.apply(data.parallelStream()); + Spliterator.OfLong sp = s.spliterator(); + LongStream ss = StreamSupport.longParallelStream(() -> sp, + StreamOpFlag.toCharacteristics(OpTestCase.getStreamFlags(s)) + | (sp.getExactSizeIfKnown() < 0 ? 0 : Spliterator.SIZED)); + for (long t : ss.toArray()) + b.accept(t); + } + }, + + PAR_STREAM_TO_ARRAY_CLEAR_SIZED(true) { + > + void _run(TestData data, LongConsumer b, Function m) { + S_IN pipe1 = (S_IN) OpTestCase.chain(data.parallelStream(), + new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape())); + LongStream pipe2 = m.apply(pipe1); + + for (long t : pipe2.toArray()) + b.accept(t); + } + },; + + private boolean isParallel; + + LongStreamTestScenario(boolean isParallel) { + this.isParallel = isParallel; + } + + public StreamShape getShape() { + return StreamShape.LONG_VALUE; + } + + public boolean isParallel() { + return isParallel; + } + + public , S_OUT extends BaseStream> + void run(TestData data, Consumer b, Function m) { + _run(data, (LongConsumer) b, (Function) m); + } + + abstract > + void _run(TestData data, LongConsumer b, Function m); + +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/OpTestCase.java b/jdk/test/java/util/stream/bootlib/java/util/stream/OpTestCase.java new file mode 100644 index 00000000000..763b8838b5d --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/OpTestCase.java @@ -0,0 +1,633 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Base class for streams test cases. Provides 'exercise' methods for taking + * lambdas that construct and modify streams, and evaluates them in different + * ways and asserts that they produce equivalent results. + */ +@Test +public abstract class OpTestCase extends Assert { + + private final Map> testScenarios; + + protected OpTestCase() { + testScenarios = new EnumMap<>(StreamShape.class); + testScenarios.put(StreamShape.REFERENCE, Collections.unmodifiableSet(EnumSet.allOf(StreamTestScenario.class))); + testScenarios.put(StreamShape.INT_VALUE, Collections.unmodifiableSet(EnumSet.allOf(IntStreamTestScenario.class))); + testScenarios.put(StreamShape.LONG_VALUE, Collections.unmodifiableSet(EnumSet.allOf(LongStreamTestScenario.class))); + testScenarios.put(StreamShape.DOUBLE_VALUE, Collections.unmodifiableSet(EnumSet.allOf(DoubleStreamTestScenario.class))); + } + + @SuppressWarnings("rawtypes") + public static int getStreamFlags(BaseStream s) { + return ((AbstractPipeline) s).getStreamFlags(); + } + + // Exercise stream operations + + public interface BaseStreamTestScenario { + StreamShape getShape(); + + boolean isParallel(); + + abstract , S_OUT extends BaseStream> + void run(TestData data, Consumer b, Function m); + } + + public , S_OUT extends BaseStream> + Collection exerciseOps(TestData data, Function m) { + return withData(data).stream(m).exercise(); + } + + // Run multiple versions of exercise(), returning the result of the first, and asserting that others return the same result + // If the first version is s -> s.foo(), can be used with s -> s.mapToInt(i -> i).foo().mapToObj(i -> i) to test all shape variants + @SafeVarargs + public final, S_OUT extends BaseStream> + Collection exerciseOpsMulti(TestData data, + Function... ms) { + Collection result = null; + for (Function m : ms) { + if (result == null) + result = withData(data).stream(m).exercise(); + else { + Collection r2 = withData(data).stream(m).exercise(); + assertEquals(result, r2); + } + } + return result; + } + + // Run multiple versions of exercise() for an Integer stream, returning the result of the first, and asserting that others return the same result + // Automates the conversion between Stream and {Int,Long,Double}Stream and back, so client sites look like you are passing the same + // lambda four times, but in fact they are four different lambdas since they are transforming four different kinds of streams + public final + Collection exerciseOpsInt(TestData.OfRef data, + Function, Stream> mRef, + Function mInt, + Function mLong, + Function mDouble) { + @SuppressWarnings({ "rawtypes", "unchecked" }) + Function, Stream>[] ms = new Function[4]; + ms[0] = mRef; + ms[1] = s -> mInt.apply(s.mapToInt(e -> e)).mapToObj(e -> e); + ms[2] = s -> mLong.apply(s.mapToLong(e -> e)).mapToObj(e -> (int) e); + ms[3] = s -> mDouble.apply(s.mapToDouble(e -> e)).mapToObj(e -> (int) e); + return exerciseOpsMulti(data, ms); + } + + public > + Collection exerciseOps(Collection data, Function, S_OUT> m) { + TestData.OfRef data1 = TestData.Factory.ofCollection("Collection of type " + data.getClass().getName(), data); + return withData(data1).stream(m).exercise(); + } + + public , I extends Iterable> + Collection exerciseOps(Collection data, Function, S_OUT> m, I expected) { + TestData.OfRef data1 = TestData.Factory.ofCollection("Collection of type " + data.getClass().getName(), data); + return withData(data1).stream(m).expectedResult(expected).exercise(); + } + + @SuppressWarnings("unchecked") + public > + Collection exerciseOps(int[] data, Function m) { + return withData(TestData.Factory.ofArray("int array", data)).stream(m).exercise(); + } + + public Collection exerciseOps(int[] data, Function m, int[] expected) { + TestData.OfInt data1 = TestData.Factory.ofArray("int array", data); + return withData(data1).stream(m).expectedResult(expected).exercise(); + } + + public > DataStreamBuilder withData(TestData data) { + Objects.requireNonNull(data); + return new DataStreamBuilder<>(data); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public class DataStreamBuilder> { + final TestData data; + + private DataStreamBuilder(TestData data) { + this.data = Objects.requireNonNull(data); + } + + public > + ExerciseDataStreamBuilder ops(IntermediateTestOp... ops) { + return new ExerciseDataStreamBuilder<>(data, (S_IN s) -> (S_OUT) chain(s, ops)); + } + + public > ExerciseDataStreamBuilder + stream(Function m) { + return new ExerciseDataStreamBuilder<>(data, m); + } + + public > ExerciseDataStreamBuilder + stream(Function m, IntermediateTestOp additionalOp) { + return new ExerciseDataStreamBuilder<>(data, s -> (S_OUT) chain(m.apply(s), additionalOp)); + } + + public ExerciseDataTerminalBuilder + terminal(Function terminalF) { + return new ExerciseDataTerminalBuilder<>(data, s -> s, terminalF); + } + + public > ExerciseDataTerminalBuilder + terminal(Function streamF, Function terminalF) { + return new ExerciseDataTerminalBuilder<>(data, streamF, terminalF); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public class ExerciseDataStreamBuilder, S_OUT extends BaseStream> { + final TestData data; + final Function m; + final StreamShape shape; + + Set testSet = new HashSet<>(); + + Collection refResult; + boolean isOrdered; + + Consumer> before = LambdaTestHelpers.bEmpty; + + Consumer> after = LambdaTestHelpers.bEmpty; + + BiConsumer, Iterable> sequentialEqualityAsserter = LambdaTestHelpers::assertContentsEqual; + BiConsumer, Iterable> parallelEqualityAsserter = LambdaTestHelpers::assertContentsEqual; + + private ExerciseDataStreamBuilder(TestData data, Function m) { + this.data = data; + + this.m = Objects.requireNonNull(m); + + this.shape = ((AbstractPipeline) m.apply(data.stream())).getOutputShape(); + + // Have to initiate from the output shape of the last stream + // This means the stream mapper is required first rather than last + testSet.addAll(testScenarios.get(shape)); + } + + public BiConsumer, Iterable> getEqualityAsserter(BaseStreamTestScenario t) { + return t.isParallel() ? parallelEqualityAsserter : sequentialEqualityAsserter; + } + + // + + public > ExerciseDataStreamBuilder expectedResult(I expectedResult) { + List l = new ArrayList<>(); + expectedResult.forEach(l::add); + refResult = l; + return this; + } + + public ExerciseDataStreamBuilder expectedResult(int[] expectedResult) { + List l = new ArrayList(); + for (int anExpectedResult : expectedResult) { + l.add(anExpectedResult); + } + refResult = l; + return this; + } + + public ExerciseDataStreamBuilder expectedResult(long[] expectedResult) { + List l = new ArrayList(); + for (long anExpectedResult : expectedResult) { + l.add(anExpectedResult); + } + refResult = l; + return this; + } + + public ExerciseDataStreamBuilder expectedResult(double[] expectedResult) { + List l = new ArrayList(); + for (double anExpectedResult : expectedResult) { + l.add(anExpectedResult); + } + refResult = l; + return this; + } + + public ExerciseDataStreamBuilder before(Consumer> before) { + this.before = Objects.requireNonNull(before); + return this; + } + + public ExerciseDataStreamBuilder after(Consumer> after) { + this.after = Objects.requireNonNull(after); + return this; + } + + public ExerciseDataStreamBuilder without(BaseStreamTestScenario... tests) { + return without(Arrays.asList(tests)); + } + + public ExerciseDataStreamBuilder without(Collection tests) { + for (BaseStreamTestScenario ts : tests) { + if (ts.getShape() == shape) { + testSet.remove(ts); + } + } + + if (testSet.isEmpty()) { + throw new IllegalStateException("Test scenario set is empty"); + } + + return this; + } + + public ExerciseDataStreamBuilder with(BaseStreamTestScenario... tests) { + return with(Arrays.asList(tests)); + } + + public ExerciseDataStreamBuilder with(Collection tests) { + testSet = new HashSet<>(); + + for (BaseStreamTestScenario ts : tests) { + if (ts.getShape() == shape) { + testSet.add(ts); + } + } + + if (testSet.isEmpty()) { + throw new IllegalStateException("Test scenario set is empty"); + } + + return this; + } + + public ExerciseDataStreamBuilder sequentialEqualityAsserter(BiConsumer, Iterable> equalator) { + this.sequentialEqualityAsserter = equalator; + return this; + } + + public ExerciseDataStreamBuilder parallelEqualityAsserter(BiConsumer, Iterable> equalator) { + this.parallelEqualityAsserter = equalator; + return this; + } + + // Build method + + private long count(StreamShape shape, BaseStream s) { + switch (shape) { + case REFERENCE: return ((Stream) s).count(); + case INT_VALUE: return ((IntStream) s).count(); + case LONG_VALUE: return ((LongStream) s).count(); + case DOUBLE_VALUE: return ((DoubleStream) s).count(); + default: throw new IllegalStateException("Unknown shape: " + shape); + } + } + + public Collection exercise() { + if (refResult == null) { + // Induce the reference result + before.accept(data); + S_OUT sOut = m.apply(data.stream()); + isOrdered = StreamOpFlag.ORDERED.isKnown(((AbstractPipeline) sOut).getStreamFlags()); + Node refNodeResult = ((AbstractPipeline) sOut).evaluateToArrayNode(size -> (U[]) new Object[size]); + refResult = LambdaTestHelpers.toBoxedList(refNodeResult.spliterator()); + after.accept(data); + S_OUT anotherCopy = m.apply(data.stream()); + long count = count(((AbstractPipeline) anotherCopy).getOutputShape(), anotherCopy); + assertEquals(count, refNodeResult.count()); + } + + List errors = new ArrayList<>(); + for (BaseStreamTestScenario test : testSet) { + try { + before.accept(data); + + List result = new ArrayList<>(); + test.run(data, LambdaTestHelpers.toBoxingConsumer(result::add), m); + + Runnable asserter = () -> getEqualityAsserter(test).accept(result, refResult); + if (test.isParallel() && !isOrdered) + asserter = () -> LambdaTestHelpers.assertContentsUnordered(result, refResult); + LambdaTestHelpers.launderAssertion( + asserter, + () -> String.format("%n%s: %s != %s", test, refResult, result)); + + after.accept(data); +// } catch (AssertionError ae) { +// errors.add(ae); + } catch (Throwable t) { + errors.add(new Error(String.format("%s: %s", test, t), t)); + } + } + + if (!errors.isEmpty()) { + StringBuilder sb = new StringBuilder(); + int i = 1; + for (Error t : errors) { + sb.append(i++).append(": "); + if (t instanceof AssertionError) { + sb.append(t).append("\n"); + } + else { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + + t.getCause().printStackTrace(pw); + pw.flush(); + sb.append(t).append("\n").append(sw); + } + } + sb.append("--"); + + fail(String.format("%d failure(s) for test data: %s\n%s", i - 1, data.toString(), sb)); + } + + return refResult; + } + } + + // Exercise terminal operations + + static enum TerminalTestScenario { + SINGLE_SEQUENTIAL, + SINGLE_SEQUENTIAL_SHORT_CIRCUIT, + SINGLE_PARALLEL, + ALL_SEQUENTIAL, + ALL_SEQUENTIAL_SHORT_CIRCUIT, + ALL_PARALLEL, + ALL_PARALLEL_SEQUENTIAL, + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + public class ExerciseDataTerminalBuilder, S_OUT extends BaseStream> { + final TestData data; + final Function streamF; + final Function terminalF; + + R refResult; + + Set testSet = EnumSet.allOf(TerminalTestScenario.class); + + Function> sequentialEqualityAsserter = s -> LambdaTestHelpers::assertContentsEqual; + Function> parallelEqualityAsserter = s -> LambdaTestHelpers::assertContentsEqual; + + private ExerciseDataTerminalBuilder(TestData data, Function streamF, Function terminalF) { + this.data = data; + this.streamF = Objects.requireNonNull(streamF); + this.terminalF = Objects.requireNonNull(terminalF); + } + + // + + public ExerciseDataTerminalBuilder expectedResult(R expectedResult) { + this.refResult = expectedResult; + return this; + } + + public ExerciseDataTerminalBuilder equalator(BiConsumer equalityAsserter) { + this.sequentialEqualityAsserter = s -> equalityAsserter; + this.parallelEqualityAsserter = s -> equalityAsserter; + return this; + } + + public ExerciseDataTerminalBuilder sequentialEqualityAsserter(BiConsumer equalityAsserter) { + this.sequentialEqualityAsserter = s -> equalityAsserter; + return this; + } + + public ExerciseDataTerminalBuilder parallelEqualityAsserter(BiConsumer equalityAsserter) { + this.parallelEqualityAsserter = s -> equalityAsserter; + return this; + } + + public ExerciseDataTerminalBuilder parallelEqualityAsserter(Function> equalatorProvider) { + this.parallelEqualityAsserter = equalatorProvider; + return this; + } + + public ExerciseDataTerminalBuilder without(TerminalTestScenario... tests) { + return without(Arrays.asList(tests)); + } + + public ExerciseDataTerminalBuilder without(Collection tests) { + testSet.removeAll(tests); + if (testSet.isEmpty()) { + throw new IllegalStateException("Terminal test scenario set is empty"); + } + return this; + } + + public ExerciseDataTerminalBuilder with(TerminalTestScenario... tests) { + return with(Arrays.asList(tests)); + } + + public ExerciseDataTerminalBuilder with(Collection tests) { + testSet.addAll(tests); + return this; + } + + // Build method + + public R exercise() { + S_OUT out = streamF.apply(data.stream()); + AbstractPipeline ap = (AbstractPipeline) out; + StreamShape shape = ap.getOutputShape(); + + Node node = ap.evaluateToArrayNode(size -> (U[]) new Object[size]); + if (refResult == null) { + // Sequentially collect the output that will be input to the terminal op + refResult = terminalF.apply((S_OUT) createPipeline(shape, node.spliterator(), + StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SIZED, + false)); + } else if (testSet.contains(TerminalTestScenario.SINGLE_SEQUENTIAL)) { + S_OUT source = (S_OUT) createPipeline(shape, node.spliterator(), + StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SIZED, + false); + BiConsumer asserter = sequentialEqualityAsserter.apply(source); + R result = terminalF.apply(source); + LambdaTestHelpers.launderAssertion(() -> asserter.accept(refResult, result), + () -> String.format("Single sequential: %s != %s", refResult, result)); + } + + if (testSet.contains(TerminalTestScenario.SINGLE_SEQUENTIAL_SHORT_CIRCUIT)) { + S_OUT source = (S_OUT) createPipeline(shape, node.spliterator(), + StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SIZED, + false); + // Force short-curcuit + source = (S_OUT) chain(source, new ShortCircuitOp(shape)); + BiConsumer asserter = sequentialEqualityAsserter.apply(source); + R result = terminalF.apply(source); + LambdaTestHelpers.launderAssertion(() -> asserter.accept(refResult, result), + () -> String.format("Single sequential pull: %s != %s", refResult, result)); + } + + if (testSet.contains(TerminalTestScenario.SINGLE_PARALLEL)) { + S_OUT source = (S_OUT) createPipeline(shape, node.spliterator(), + StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SIZED, + true); + BiConsumer asserter = parallelEqualityAsserter.apply(source); + R result = terminalF.apply(source); + LambdaTestHelpers.launderAssertion(() -> asserter.accept(refResult, result), + () -> String.format("Single parallel: %s != %s", refResult, result)); + } + + if (testSet.contains(TerminalTestScenario.ALL_SEQUENTIAL)) { + // This may forEach or tryAdvance depending on the terminal op implementation + S_OUT source = streamF.apply(data.stream()); + BiConsumer asserter = sequentialEqualityAsserter.apply(source); + R result = terminalF.apply(source); + LambdaTestHelpers.launderAssertion(() -> asserter.accept(refResult, result), + () -> String.format("All sequential: %s != %s", refResult, result)); + } + + if (testSet.contains(TerminalTestScenario.ALL_SEQUENTIAL_SHORT_CIRCUIT)) { + S_OUT source = streamF.apply(data.stream()); + // Force short-curcuit + source = (S_OUT) chain(source, new ShortCircuitOp(shape)); + BiConsumer asserter = sequentialEqualityAsserter.apply(source); + R result = terminalF.apply(source); + LambdaTestHelpers.launderAssertion(() -> asserter.accept(refResult, result), + () -> String.format("All sequential pull: %s != %s", refResult, result)); + } + + if (testSet.contains(TerminalTestScenario.ALL_PARALLEL)) { + S_OUT source = streamF.apply(data.parallelStream()); + BiConsumer asserter = parallelEqualityAsserter.apply(source); + R result = terminalF.apply(source); + LambdaTestHelpers.launderAssertion(() -> asserter.accept(refResult, result), + () -> String.format("All parallel: %s != %s", refResult, result)); + } + + if (testSet.contains(TerminalTestScenario.ALL_PARALLEL_SEQUENTIAL)) { + S_OUT source = streamF.apply(data.parallelStream()); + BiConsumer asserter = parallelEqualityAsserter.apply(source); + R result = terminalF.apply(source.sequential()); + LambdaTestHelpers.launderAssertion(() -> asserter.accept(refResult, result), + () -> String.format("All parallel then sequential: %s != %s", refResult, result)); + } + + return refResult; + } + + AbstractPipeline createPipeline(StreamShape shape, Spliterator s, int flags, boolean parallel) { + switch (shape) { + case REFERENCE: return new ReferencePipeline.Head<>(s, flags, parallel); + case INT_VALUE: return new IntPipeline.Head(s, flags, parallel); + case LONG_VALUE: return new LongPipeline.Head(s, flags, parallel); + case DOUBLE_VALUE: return new DoublePipeline.Head(s, flags, parallel); + default: throw new IllegalStateException("Unknown shape: " + shape); + } + } + } + + public R exerciseTerminalOps(Collection data, Function, R> m, R expected) { + TestData.OfRef data1 + = TestData.Factory.ofCollection("Collection of type " + data.getClass().getName(), data); + return withData(data1).terminal(m).expectedResult(expected).exercise(); + } + + public > R + exerciseTerminalOps(TestData data, + Function terminalF) { + return withData(data).terminal(terminalF).exercise(); + } + + public , S_OUT extends BaseStream> R + exerciseTerminalOps(TestData data, + Function streamF, + Function terminalF) { + return withData(data).terminal(streamF, terminalF).exercise(); + } + + // + + @SuppressWarnings({"rawtypes", "unchecked"}) + private static AbstractPipeline chain(AbstractPipeline upstream, IntermediateTestOp op) { + return (AbstractPipeline) IntermediateTestOp.chain(upstream, op); + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private static AbstractPipeline chain(AbstractPipeline pipe, IntermediateTestOp... ops) { + for (IntermediateTestOp op : ops) + pipe = chain(pipe, op); + return pipe; + } + + @SuppressWarnings("rawtypes") + private static AbstractPipeline chain(BaseStream pipe, IntermediateTestOp op) { + return chain((AbstractPipeline) pipe, op); + } + + @SuppressWarnings("rawtypes") + public static AbstractPipeline chain(BaseStream pipe, IntermediateTestOp... ops) { + return chain((AbstractPipeline) pipe, ops); + } + + // Test data + + private class ShortCircuitOp implements StatelessTestOp { + private final StreamShape shape; + + private ShortCircuitOp(StreamShape shape) { + this.shape = shape; + } + + @Override + public Sink opWrapSink(int flags, boolean parallel, Sink sink) { + return sink; + } + + @Override + public int opGetFlags() { + return StreamOpFlag.IS_SHORT_CIRCUIT; + } + + @Override + public StreamShape outputShape() { + return shape; + } + + @Override + public StreamShape inputShape() { + return shape; + } + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/SpliteratorTestHelper.java b/jdk/test/java/util/stream/bootlib/java/util/stream/SpliteratorTestHelper.java new file mode 100644 index 00000000000..8cadf5fd824 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/SpliteratorTestHelper.java @@ -0,0 +1,654 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Spliterator; +import java.util.function.*; + +import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + +/** + * Assertion methods for spliterators, to be called from other tests + */ +public class SpliteratorTestHelper { + + public static void testSpliterator(Supplier> supplier) { + testSpliterator(supplier, (Consumer b) -> b); + } + + public static void testIntSpliterator(Supplier supplier) { + class BoxingAdapter implements Consumer, IntConsumer { + private final Consumer b; + + BoxingAdapter(Consumer b) { + this.b = b; + } + + @Override + public void accept(Integer value) { + throw new IllegalStateException(); + } + + @Override + public void accept(int value) { + b.accept(value); + } + } + + testSpliterator(supplier, c -> new BoxingAdapter(c)); + } + + public static void testLongSpliterator(Supplier supplier) { + class BoxingAdapter implements Consumer, LongConsumer { + private final Consumer b; + + BoxingAdapter(Consumer b) { + this.b = b; + } + + @Override + public void accept(Long value) { + throw new IllegalStateException(); + } + + @Override + public void accept(long value) { + b.accept(value); + } + } + + testSpliterator(supplier, c -> new BoxingAdapter(c)); + } + + public static void testDoubleSpliterator(Supplier supplier) { + class BoxingAdapter implements Consumer, DoubleConsumer { + private final Consumer b; + + BoxingAdapter(Consumer b) { + this.b = b; + } + + @Override + public void accept(Double value) { + throw new IllegalStateException(); + } + + @Override + public void accept(double value) { + b.accept(value); + } + } + + testSpliterator(supplier, c -> new BoxingAdapter(c)); + } + + static > void testSpliterator(Supplier supplier, + UnaryOperator> boxingAdapter) { + ArrayList fromForEach = new ArrayList<>(); + Spliterator spliterator = supplier.get(); + Consumer addToFromForEach = boxingAdapter.apply(fromForEach::add); + spliterator.forEachRemaining(addToFromForEach); + + Collection exp = Collections.unmodifiableList(fromForEach); + + 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); + testSplitUntilNull(exp, supplier, boxingAdapter); + } + + // + + private static > void testForEach( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + ArrayList fromForEach = new ArrayList<>(); + spliterator = supplier.get(); + Consumer addToFromForEach = boxingAdapter.apply(fromForEach::add); + spliterator.forEachRemaining(addToFromForEach); + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + // Assert that tryAdvance now produce no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + // assert that size, tryAdvance, and forEach are consistent + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, exp.size()); + } + assertEquals(fromForEach.size(), exp.size()); + + assertContents(fromForEach, exp, isOrdered); + } + + private static > void testTryAdvance( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + spliterator = supplier.get(); + ArrayList fromTryAdvance = new ArrayList<>(); + Consumer addToFromTryAdvance = boxingAdapter.apply(fromTryAdvance::add); + while (spliterator.tryAdvance(addToFromTryAdvance)) { } + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + // Assert that tryAdvance now produce no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + // assert that size, tryAdvance, and forEach are consistent + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, exp.size()); + } + assertEquals(fromTryAdvance.size(), exp.size()); + + assertContents(fromTryAdvance, exp, isOrdered); + } + + private static > void testMixedTryAdvanceForEach( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + // tryAdvance first few elements, then forEach rest + ArrayList dest = new ArrayList<>(); + spliterator = supplier.get(); + Consumer addToDest = boxingAdapter.apply(dest::add); + for (int i = 0; i < 10 && spliterator.tryAdvance(addToDest); i++) { } + spliterator.forEachRemaining(addToDest); + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + // Assert that tryAdvance now produce no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, dest.size()); + } + assertEquals(dest.size(), exp.size()); + + if (isOrdered) { + assertEquals(dest, exp); + } + else { + assertContentsUnordered(dest, exp); + } + } + + private static > void testMixedTraverseAndSplit( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + // tryAdvance first few elements, then forEach rest + ArrayList dest = new ArrayList<>(); + spliterator = supplier.get(); + Consumer b = boxingAdapter.apply(dest::add); + + Spliterator 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 > void testSplitAfterFullTraversal( + Supplier supplier, + UnaryOperator> boxingAdapter) { + // Full traversal using tryAdvance + Spliterator spliterator = supplier.get(); + while (spliterator.tryAdvance(boxingAdapter.apply(e -> { }))) { } + Spliterator split = spliterator.trySplit(); + assertNull(split); + + // Full traversal using forEach + spliterator = supplier.get(); + spliterator.forEachRemaining(boxingAdapter.apply(e -> { + })); + split = spliterator.trySplit(); + assertNull(split); + + // Full traversal using tryAdvance then forEach + spliterator = supplier.get(); + spliterator.tryAdvance(boxingAdapter.apply(e -> { })); + spliterator.forEachRemaining(boxingAdapter.apply(e -> { + })); + split = spliterator.trySplit(); + assertNull(split); + } + + private static > void testSplitOnce( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + ArrayList fromSplit = new ArrayList<>(); + Spliterator s1 = supplier.get(); + Spliterator s2 = s1.trySplit(); + long s1Size = s1.getExactSizeIfKnown(); + long s2Size = (s2 != null) ? s2.getExactSizeIfKnown() : 0; + Consumer addToFromSplit = boxingAdapter.apply(fromSplit::add); + if (s2 != null) + s2.forEachRemaining(addToFromSplit); + s1.forEachRemaining(addToFromSplit); + + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, fromSplit.size()); + if (s1Size >= 0 && s2Size >= 0) + assertEquals(sizeIfKnown, s1Size + s2Size); + } + assertContents(fromSplit, exp, isOrdered); + } + + private static > void testSplitSixDeep( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + for (int depth=0; depth < 6; depth++) { + List dest = new ArrayList<>(); + spliterator = supplier.get(); + + assertSpliterator(spliterator); + + // verify splitting with forEach + splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false); + assertContents(dest, exp, isOrdered); + + // verify splitting with tryAdvance + dest.clear(); + spliterator = supplier.get(); + splitSixDeepVisitor(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), true); + assertContents(dest, exp, isOrdered); + } + } + + private static > + void splitSixDeepVisitor(int depth, int curLevel, + List dest, S spliterator, UnaryOperator> boxingAdapter, + int rootCharacteristics, boolean useTryAdvance) { + if (curLevel < depth) { + long beforeSize = spliterator.getExactSizeIfKnown(); + Spliterator split = spliterator.trySplit(); + if (split != null) { + assertSpliterator(split, rootCharacteristics); + assertSpliterator(spliterator, rootCharacteristics); + + if ((rootCharacteristics & Spliterator.SUBSIZED) != 0 && + (rootCharacteristics & Spliterator.SIZED) != 0) { + assertEquals(beforeSize, split.estimateSize() + spliterator.estimateSize()); + } + splitSixDeepVisitor(depth, curLevel + 1, dest, split, boxingAdapter, rootCharacteristics, useTryAdvance); + } + splitSixDeepVisitor(depth, curLevel + 1, dest, spliterator, boxingAdapter, rootCharacteristics, useTryAdvance); + } + else { + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + if (useTryAdvance) { + Consumer addToDest = boxingAdapter.apply(dest::add); + int count = 0; + while (spliterator.tryAdvance(addToDest)) { + ++count; + } + + if (sizeIfKnown >= 0) + assertEquals(sizeIfKnown, count); + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + + Spliterator split = spliterator.trySplit(); + assertNull(split); + } + else { + List leafDest = new ArrayList<>(); + Consumer addToLeafDest = boxingAdapter.apply(leafDest::add); + spliterator.forEachRemaining(addToLeafDest); + + if (sizeIfKnown >= 0) + assertEquals(sizeIfKnown, leafDest.size()); + + // Assert that forEach now produces no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + Spliterator split = spliterator.trySplit(); + assertNull(split); + + dest.addAll(leafDest); + } + } + } + + private static > void testSplitUntilNull( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + Spliterator s = supplier.get(); + boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED); + assertSpliterator(s); + + List splits = new ArrayList<>(); + Consumer c = boxingAdapter.apply(splits::add); + + testSplitUntilNull(new SplitNode(c, s)); + assertContents(splits, exp, isOrdered); + } + + private static class SplitNode { + // Constant for every node + final Consumer c; + final int rootCharacteristics; + + final Spliterator s; + + SplitNode(Consumer c, Spliterator s) { + this(c, s.characteristics(), s); + } + + private SplitNode(Consumer c, int rootCharacteristics, Spliterator s) { + this.c = c; + this.rootCharacteristics = rootCharacteristics; + this.s = s; + } + + SplitNode fromSplit(Spliterator split) { + return new SplitNode<>(c, rootCharacteristics, split); + } + } + + /** + * Set the maximum stack capacity to 0.25MB. This should be more than enough to detect a bad spliterator + * while not unduly disrupting test infrastructure given the test data sizes that are used are small. + * Note that j.u.c.ForkJoinPool sets the max queue size to 64M (1 << 26). + */ + private static final int MAXIMUM_STACK_CAPACITY = 1 << 18; // 0.25MB + + private static void testSplitUntilNull(SplitNode e) { + // Use an explicit stack to avoid a StackOverflowException when testing a Spliterator + // that when repeatedly split produces a right-balanced (and maybe degenerate) tree, or + // for a spliterator that is badly behaved. + Deque> stack = new ArrayDeque<>(); + stack.push(e); + + int iteration = 0; + while (!stack.isEmpty()) { + assertTrue(iteration++ < MAXIMUM_STACK_CAPACITY, "Exceeded maximum stack modification count of 1 << 18"); + + e = stack.pop(); + Spliterator parentAndRightSplit = e.s; + + long parentEstimateSize = parentAndRightSplit.estimateSize(); + assertTrue(parentEstimateSize >= 0, + String.format("Split size estimate %d < 0", parentEstimateSize)); + + long parentSize = parentAndRightSplit.getExactSizeIfKnown(); + Spliterator leftSplit = parentAndRightSplit.trySplit(); + if (leftSplit == null) { + parentAndRightSplit.forEachRemaining(e.c); + continue; + } + + assertSpliterator(leftSplit, e.rootCharacteristics); + assertSpliterator(parentAndRightSplit, e.rootCharacteristics); + + if (parentEstimateSize != Long.MAX_VALUE && leftSplit.estimateSize() > 0 + && parentAndRightSplit.estimateSize() > 0) { + assertTrue(leftSplit.estimateSize() < parentEstimateSize, + String.format("Left split size estimate %d >= parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + assertTrue(parentAndRightSplit.estimateSize() < parentEstimateSize, + String.format("Right split size estimate %d >= parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + } + else { + assertTrue(leftSplit.estimateSize() <= parentEstimateSize, + String.format("Left split size estimate %d > parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + assertTrue(parentAndRightSplit.estimateSize() <= parentEstimateSize, + String.format("Right split size estimate %d > parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + } + + long leftSize = leftSplit.getExactSizeIfKnown(); + long rightSize = parentAndRightSplit.getExactSizeIfKnown(); + if (parentSize >= 0 && leftSize >= 0 && rightSize >= 0) + assertEquals(parentSize, leftSize + rightSize, + String.format("exact left split size %d + exact right split size %d != parent exact split size %d", + leftSize, rightSize, parentSize)); + + // Add right side to stack first so left side is popped off first + stack.push(e.fromSplit(parentAndRightSplit)); + stack.push(e.fromSplit(leftSplit)); + } + } + + private static void assertSpliterator(Spliterator s, int rootCharacteristics) { + if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) { + assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED), + "Child split is not SUBSIZED when root split is SUBSIZED"); + } + assertSpliterator(s); + } + + private static void assertSpliterator(Spliterator s) { + if (s.hasCharacteristics(Spliterator.SUBSIZED)) { + assertTrue(s.hasCharacteristics(Spliterator.SIZED)); + } + if (s.hasCharacteristics(Spliterator.SIZED)) { + assertTrue(s.estimateSize() != Long.MAX_VALUE); + assertTrue(s.getExactSizeIfKnown() >= 0); + } + try { + s.getComparator(); + assertTrue(s.hasCharacteristics(Spliterator.SORTED)); + } catch (IllegalStateException e) { + assertFalse(s.hasCharacteristics(Spliterator.SORTED)); + } + } + + private static void assertContents(Collection actual, Collection expected, boolean isOrdered) { + if (isOrdered) { + assertEquals(actual, expected); + } + else { + assertContentsUnordered(actual, expected); + } + } + + private static void assertContentsUnordered(Iterable actual, Iterable expected) { + assertEquals(toBoxedMultiset(actual), toBoxedMultiset(expected)); + } + + private static Map toBoxedMultiset(Iterable c) { + Map result = new HashMap<>(); + c.forEach(e -> { + if (result.containsKey(e)) result.put(e, result.get(e) + 1); + else result.put(e, 1); + }); + return result; + } + + static void mixedTraverseAndSplit(Consumer b, Spliterator splTop) { + Spliterator 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); + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/StatefulTestOp.java b/jdk/test/java/util/stream/bootlib/java/util/stream/StatefulTestOp.java new file mode 100644 index 00000000000..5414cfdacb1 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/StatefulTestOp.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import java.util.Spliterator; +import java.util.function.IntFunction; + +/** + * The base type for a stateful test operation. + */ +interface StatefulTestOp extends IntermediateTestOp { + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static AbstractPipeline chain(AbstractPipeline upstream, + StatefulTestOp op) { + switch (op.outputShape()) { + case REFERENCE: + return new ReferencePipeline.StatefulOp(upstream, op.inputShape(), op.opGetFlags()) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return op.opWrapSink(flags, isParallel(), sink); + } + + @Override + Spliterator opEvaluateParallelLazy(PipelineHelper helper, + Spliterator spliterator) { + return op.opEvaluateParallelLazy(helper, spliterator); + } + + @Override + Node opEvaluateParallel(PipelineHelper helper, + Spliterator spliterator, + IntFunction generator) { + return op.opEvaluateParallel(helper, spliterator, generator); + } + }; + case INT_VALUE: + return new IntPipeline.StatefulOp(upstream, op.inputShape(), op.opGetFlags()) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return op.opWrapSink(flags, isParallel(), sink); + } + + @Override + Spliterator opEvaluateParallelLazy(PipelineHelper helper, + Spliterator spliterator) { + return op.opEvaluateParallelLazy(helper, spliterator); + } + + @Override + Node opEvaluateParallel(PipelineHelper helper, + Spliterator spliterator, + IntFunction generator) { + return (Node) op.opEvaluateParallel(helper, spliterator, generator); + } + }; + case LONG_VALUE: + return new LongPipeline.StatefulOp(upstream, op.inputShape(), op.opGetFlags()) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return op.opWrapSink(flags, isParallel(), sink); + } + + @Override + Spliterator opEvaluateParallelLazy(PipelineHelper helper, + Spliterator spliterator) { + return op.opEvaluateParallelLazy(helper, spliterator); + } + + @Override + Node opEvaluateParallel(PipelineHelper helper, + Spliterator spliterator, + IntFunction generator) { + return (Node) op.opEvaluateParallel(helper, spliterator, generator); + } + }; + case DOUBLE_VALUE: + return new DoublePipeline.StatefulOp(upstream, op.inputShape(), op.opGetFlags()) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return op.opWrapSink(flags, isParallel(), sink); + } + + @Override + Spliterator opEvaluateParallelLazy(PipelineHelper helper, + Spliterator spliterator) { + return op.opEvaluateParallelLazy(helper, spliterator); + } + + @Override + Node opEvaluateParallel(PipelineHelper helper, + Spliterator spliterator, + IntFunction generator) { + return (Node) op.opEvaluateParallel(helper, spliterator, generator); + } + }; + default: throw new IllegalStateException(op.outputShape().toString()); + } + } + + default StreamShape inputShape() { return StreamShape.REFERENCE; } + + default StreamShape outputShape() { return StreamShape.REFERENCE; } + + default int opGetFlags() { return 0; } + + Sink opWrapSink(int flags, boolean parallel, Sink sink); + + @SuppressWarnings("unchecked") + default Spliterator opEvaluateParallelLazy(PipelineHelper helper, + Spliterator spliterator) { + return opEvaluateParallel(helper, spliterator, i -> (E[]) new Object[i]).spliterator(); + } + + Node opEvaluateParallel(PipelineHelper helper, + Spliterator spliterator, + IntFunction generator); +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/StatelessTestOp.java b/jdk/test/java/util/stream/bootlib/java/util/stream/StatelessTestOp.java new file mode 100644 index 00000000000..77460b79a91 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/StatelessTestOp.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013, 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. + * + * 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 java.util.stream; + +/** + * The base type of a stateless test operation + */ +interface StatelessTestOp extends IntermediateTestOp { + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static AbstractPipeline chain(AbstractPipeline upstream, + StatelessTestOp op) { + int flags = op.opGetFlags(); + switch (op.outputShape()) { + case REFERENCE: + return new ReferencePipeline.StatelessOp(upstream, op.inputShape(), flags) { + public Sink opWrapSink(int flags, Sink sink) { + return op.opWrapSink(flags, isParallel(), sink); + } + }; + case INT_VALUE: + return new IntPipeline.StatelessOp(upstream, op.inputShape(), flags) { + public Sink opWrapSink(int flags, Sink sink) { + return op.opWrapSink(flags, isParallel(), sink); + } + }; + case LONG_VALUE: + return new LongPipeline.StatelessOp(upstream, op.inputShape(), flags) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return op.opWrapSink(flags, isParallel(), sink); + } + }; + case DOUBLE_VALUE: + return new DoublePipeline.StatelessOp(upstream, op.inputShape(), flags) { + @Override + Sink opWrapSink(int flags, Sink sink) { + return op.opWrapSink(flags, isParallel(), sink); + } + }; + default: throw new IllegalStateException(op.outputShape().toString()); + } + } + + default StreamShape inputShape() { return StreamShape.REFERENCE; } + + default StreamShape outputShape() { return StreamShape.REFERENCE; } + + default int opGetFlags() { return 0; } + + Sink opWrapSink(int flags, boolean parallel, Sink sink); +} + diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/StreamOpFlagTestHelper.java b/jdk/test/java/util/stream/bootlib/java/util/stream/StreamOpFlagTestHelper.java new file mode 100644 index 00000000000..11ed0f195e6 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/StreamOpFlagTestHelper.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import java.util.EnumSet; + +public class StreamOpFlagTestHelper { + + /** EnumSet containing stream flags */ + private static final EnumSet allStreamFlags; + + static { + allStreamFlags = EnumSet.allOf(StreamOpFlag.class); + for (StreamOpFlag f : EnumSet.allOf(StreamOpFlag.class)) + if (!f.isStreamFlag()) + allStreamFlags.remove(f); + } + + + static EnumSet allStreamFlags() { + // EnumSet is mutable + return allStreamFlags.clone(); + } + + public static boolean isStreamOrdered(Stream s) { + return StreamOpFlag.ORDERED.isKnown(OpTestCase.getStreamFlags(s)); + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestDataProvider.java new file mode 100644 index 00000000000..08a71c479aa --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestDataProvider.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import org.testng.annotations.DataProvider; + +import java.util.*; +import java.util.Spliterators; +import java.util.function.Supplier; + +/** + * StreamTestDataProvider + * + * @author Brian Goetz + */ +/** TestNG DataProvider for ref-valued streams */ +public class StreamTestDataProvider { + private static final Integer[] to0 = new Integer[0]; + private static final Integer[] to1 = new Integer[1]; + private static final Integer[] to10 = new Integer[10]; + private static final Integer[] to100 = new Integer[100]; + private static final Integer[] to1000 = new Integer[1000]; + private static final Integer[] reversed = new Integer[100]; + private static final Integer[] ones = new Integer[100]; + private static final Integer[] twice = new Integer[200]; + private static final Integer[] pseudoRandom; + + private static final Object[][] testData; + private static final Object[][] withNullTestData; + private static final Object[][] spliteratorTestData; + + static { + Integer[][] arrays = {to0, to1, to10, to100, to1000}; + for (Integer[] arr : arrays) { + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + } + for (int i = 0; i < reversed.length; i++) { + reversed[i] = reversed.length - i; + } + for (int i = 0; i < ones.length; i++) { + ones[i] = 1; + } + System.arraycopy(to100, 0, twice, 0, to100.length); + System.arraycopy(to100, 0, twice, to100.length, to100.length); + pseudoRandom = new Integer[LambdaTestHelpers.LONG_STRING.length()]; + for (int i = 0; i < LambdaTestHelpers.LONG_STRING.length(); i++) { + pseudoRandom[i] = (int) LambdaTestHelpers.LONG_STRING.charAt(i); + } + } + + static final Object[][] arrays = { + {"empty", to0}, + {"0..1", to1}, + {"0..10", to10}, + {"0..100", to100}, + {"0..1000", to1000}, + {"100x[1]", ones}, + {"2x[0..100]", twice}, + {"reverse 0..100", reversed}, + {"pseudorandom", pseudoRandom} + }; + + static { + { + List list = new ArrayList<>(); + for (Object[] data : arrays) { + final Object name = data[0]; + final Integer[] ints = (Integer[])data[1]; + final List intsAsList = Arrays.asList(ints); + + list.add(arrayDataDescr("array:" + name, ints)); + list.add(collectionDataDescr("ArrayList.asList:" + name, intsAsList)); + list.add(collectionDataDescr("ArrayList:" + name, new ArrayList<>(intsAsList))); + list.add(streamDataDescr("DelegatingStream(ArrayList):" + name, + () -> new ArrayList<>(intsAsList).stream())); + List aList = new ArrayList<>(intsAsList); + list.add(collectionDataDescr("ArrayList.Sublist:" + name, + (ints.length) <= 1 ? aList.subList(0, 0) : aList.subList(1, ints.length / 2))); + list.add(collectionDataDescr("LinkedList:" + name, new LinkedList<>(intsAsList))); + list.add(collectionDataDescr("HashSet:" + name, new HashSet<>(intsAsList))); + list.add(collectionDataDescr("LinkedHashSet:" + name, new LinkedHashSet<>(intsAsList))); + list.add(collectionDataDescr("TreeSet:" + name, new TreeSet<>(intsAsList))); + SpinedBuffer spinedBuffer = new SpinedBuffer<>(); + intsAsList.forEach(spinedBuffer); + list.add(sbDataDescr("SpinedBuffer:" + name, spinedBuffer)); + + // @@@ Add more + } + testData = list.toArray(new Object[0][]); + } + + // Simple combination of numbers and null values, probably excessive but may catch + // errors for initialization/termination/sequence + // @@@ This is separate from the other data for now until nulls are consitently supported by + // all operations + { + List list = new ArrayList<>(); + int size = 5; + for (int i = 0; i < (1 << size) - 2; i++) { + Integer[] content = new Integer[size]; + for (int e = 0; e < size; e++) { + content[e] = (i & (1 << e)) > 0 ? e + 1 : null; + } + + // ORDERED + list.add(arrayDataDescr("array:" + i, content)); + // not ORDERED, DISTINCT + list.add(collectionDataDescr("HashSet:" + i, new HashSet<>(Arrays.asList(content)))); + } + + withNullTestData = list.toArray(new Object[0][]); + } + + { + List spliterators = new ArrayList<>(); + for (Object[] data : arrays) { + final Object name = data[0]; + final Integer[] ints = (Integer[])data[1]; + + spliterators.add(splitDescr("Arrays.s(array):" + name, + () -> Arrays.spliterator(ints))); + spliterators.add(splitDescr("arrays.s(array,o,l):" + name, + () -> Arrays.spliterator(ints, 0, ints.length/2))); + spliterators.add(splitDescr("SpinedBuffer.s():" + name, + () -> { + SpinedBuffer sb = new SpinedBuffer<>(); + for (Integer i : ints) + sb.accept(i); + return sb.spliterator(); + })); + spliterators.add(splitDescr("Iterators.s(Arrays.s(array).iterator(), size):" + name, + () -> Spliterators.spliterator(Arrays.asList(ints).iterator(), ints.length, 0))); + spliterators.add(splitDescr("Iterators.s(Arrays.s(array).iterator()):" + name, + () -> Spliterators.spliteratorUnknownSize(Arrays.asList(ints).iterator(), 0))); + // @@@ Add map and collection spliterators when spliterator() is exposed on Collection or Iterable + } + spliteratorTestData = spliterators.toArray(new Object[0][]); + } + } + + static Object[] arrayDataDescr(String description, T[] data) { + return new Object[] { description, TestData.Factory.ofArray(description, data)}; + } + + static Object[] streamDataDescr(String description, Supplier> supplier) { + return new Object[] { description, TestData.Factory.ofSupplier(description, supplier)}; + } + + static Object[] collectionDataDescr(String description, Collection data) { + return new Object[] { description, TestData.Factory.ofCollection(description, data)}; + } + + static Object[] sbDataDescr(String description, SpinedBuffer data) { + return new Object[] { description, TestData.Factory.ofSpinedBuffer(description, data)}; + } + + static Object[] splitDescr(String description, Supplier> ss) { + return new Object[] { description, ss }; + } + + // Return an array of ( String name, StreamTestData ) + @DataProvider(name = "StreamTestData") + public static Object[][] makeStreamTestData() { + return testData; + } + + @DataProvider(name = "withNull:StreamTestData") + public static Object[][] makeStreamWithNullTestData() { + return withNullTestData; + } + + // returns an array of (String name, Supplier>) + @DataProvider(name = "Spliterator") + public static Object[][] spliteratorProvider() { + return spliteratorTestData; + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java b/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java new file mode 100644 index 00000000000..c7f09eab1d4 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import java.util.Iterator; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Function; + +/** + * Test scenarios for reference streams. + * + * Each scenario is provided with a data source, a function that maps a fresh + * stream (as provided by the data source) to a new stream, and a sink to + * receive results. Each scenario describes a different way of computing the + * stream contents. The test driver will ensure that all scenarios produce + * the same output (modulo allowable differences in ordering). + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public enum StreamTestScenario implements OpTestCase.BaseStreamTestScenario { + + STREAM_FOR_EACH(false) { + > + void _run(TestData data, Consumer b, Function> m) { + Stream s = m.apply(data.stream()); + if (s.isParallel()) { + s = s.sequential(); + } + s.forEach(b); + } + }, + + // Collec to list + STREAM_COLLECT(false) { + > + void _run(TestData data, Consumer b, Function> m) { + for (U t : m.apply(data.stream()).collect(Collectors.toList())) { + b.accept(t); + } + } + }, + + // To array + STREAM_TO_ARRAY(false) { + > + void _run(TestData data, Consumer b, Function> m) { + for (Object t : m.apply(data.stream()).toArray()) { + b.accept((U) t); + } + } + }, + + // Wrap as stream, and iterate in pull mode + STREAM_ITERATOR(false) { + > + void _run(TestData data, Consumer b, Function> m) { + for (Iterator seqIter = m.apply(data.stream()).iterator(); seqIter.hasNext(); ) + b.accept(seqIter.next()); + } + }, + + // Wrap as stream, and spliterate then iterate in pull mode + STREAM_SPLITERATOR(false) { + > + void _run(TestData data, Consumer b, Function> m) { + for (Spliterator spl = m.apply(data.stream()).spliterator(); spl.tryAdvance(b); ) { } + } + }, + + // Wrap as stream, spliterate, then split a few times mixing advances with forEach + STREAM_SPLITERATOR_WITH_MIXED_TRAVERSE_AND_SPLIT(false) { + > + void _run(TestData data, Consumer b, Function> m) { + SpliteratorTestHelper.mixedTraverseAndSplit(b, m.apply(data.stream()).spliterator()); + } + }, + + // Wrap as stream, and spliterate then iterate in pull mode + STREAM_SPLITERATOR_FOREACH(false) { + > + void _run(TestData data, Consumer b, Function> m) { + m.apply(data.stream()).spliterator().forEachRemaining(b); + } + }, + + // Wrap as parallel stream + sequential + PAR_STREAM_SEQUENTIAL_FOR_EACH(true) { + > + void _run(TestData data, Consumer b, Function> m) { + m.apply(data.parallelStream()).sequential().forEach(b); + } + }, + + // Wrap as parallel stream + forEachOrdered + PAR_STREAM_FOR_EACH_ORDERED(true) { + > + void _run(TestData data, Consumer b, Function> m) { + // @@@ Want to explicitly select ordered equalator + m.apply(data.parallelStream()).forEachOrdered(b); + } + }, + + // Wrap as stream, and spliterate then iterate sequentially + PAR_STREAM_SPLITERATOR(true) { + > + void _run(TestData data, Consumer b, Function> m) { + for (Spliterator spl = m.apply(data.parallelStream()).spliterator(); spl.tryAdvance(b); ) { } + } + }, + + // Wrap as stream, and spliterate then iterate sequentially + PAR_STREAM_SPLITERATOR_FOREACH(true) { + > + void _run(TestData data, Consumer b, Function> m) { + m.apply(data.parallelStream()).spliterator().forEachRemaining(b); + } + }, + + // Wrap as parallel stream + toArray + PAR_STREAM_TO_ARRAY(true) { + > + void _run(TestData data, Consumer b, Function> m) { + for (Object t : m.apply(data.parallelStream()).toArray()) + b.accept((U) t); + } + }, + + // Wrap as parallel stream, get the spliterator, wrap as a stream + toArray + PAR_STREAM_SPLITERATOR_STREAM_TO_ARRAY(true) { + > + void _run(TestData data, Consumer b, Function> m) { + Stream s = m.apply(data.parallelStream()); + Spliterator sp = s.spliterator(); + Stream ss = StreamSupport.parallelStream(() -> sp, + StreamOpFlag.toCharacteristics(OpTestCase.getStreamFlags(s)) + | (sp.getExactSizeIfKnown() < 0 ? 0 : Spliterator.SIZED)); + for (Object t : ss.toArray()) + b.accept((U) t); + } + }, + + // Wrap as parallel stream + toArray and clear SIZED flag + PAR_STREAM_TO_ARRAY_CLEAR_SIZED(true) { + > + void _run(TestData data, Consumer b, Function> m) { + S_IN pipe1 = (S_IN) OpTestCase.chain(data.parallelStream(), + new FlagDeclaringOp(StreamOpFlag.NOT_SIZED, data.getShape())); + Stream pipe2 = m.apply(pipe1); + + for (Object t : pipe2.toArray()) + b.accept((U) t); + } + }, + + // Wrap as parallel + collect + PAR_STREAM_COLLECT(true) { + > + void _run(TestData data, Consumer b, Function> m) { + for (U u : m.apply(data.parallelStream()).collect(Collectors.toList())) + b.accept(u); + } + }, + + // Wrap sequential as parallel, + collect + STREAM_TO_PAR_STREAM_COLLECT(true) { + > + void _run(TestData data, Consumer b, Function> m) { + for (U u : m.apply(data.stream().parallel()).collect(Collectors.toList())) + b.accept(u); + } + }, + + // Wrap parallel as sequential,, + collect + PAR_STREAM_TO_STREAM_COLLECT(true) { + > + void _run(TestData data, Consumer b, Function> m) { + for (U u : m.apply(data.parallelStream().sequential()).collect(Collectors.toList())) + b.accept(u); + } + }, + ; + + private boolean isParallel; + + StreamTestScenario(boolean isParallel) { + this.isParallel = isParallel; + } + + public StreamShape getShape() { + return StreamShape.REFERENCE; + } + + public boolean isParallel() { + return isParallel; + } + + public , S_OUT extends BaseStream> + void run(TestData data, Consumer b, Function m) { + _run(data, b, (Function>) m); + } + + abstract > + void _run(TestData data, Consumer b, Function> m); + +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/TestData.java b/jdk/test/java/util/stream/bootlib/java/util/stream/TestData.java new file mode 100644 index 00000000000..e8b65d2bdf0 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/TestData.java @@ -0,0 +1,355 @@ +/* + * 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. + * + * 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 java.util.stream; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.DoubleConsumer; +import java.util.function.Function; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.function.Supplier; +import java.util.function.ToIntFunction; + +/** Describes a test data set for use in stream tests */ +public interface TestData> + extends Iterable { + + default int size() { + throw new UnsupportedOperationException(); + } + + @Override + default Iterator iterator() { + return Spliterators.iteratorFromSpliterator(spliterator()); + } + + Spliterator spliterator(); + + default boolean isOrdered() { + return spliterator().hasCharacteristics(Spliterator.ORDERED); + } + + StreamShape getShape(); + + default > A into(A target) { + spliterator().forEachRemaining(target::add); + return target; + } + + S stream(); + + S parallelStream(); + + public interface OfRef extends TestData> { } + + public interface OfInt extends TestData { } + + public interface OfLong extends TestData { } + + public interface OfDouble extends TestData { } + + // @@@ Temporary garbage class to avoid triggering bugs with lambdas in static methods in interfaces + public static class Factory { + public static OfRef ofArray(String name, T[] array) { + return new AbstractTestData.RefTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(), + Arrays::spliterator, a -> a.length); + } + + public static OfRef ofCollection(String name, Collection collection) { + return new AbstractTestData.RefTestData<>(name, collection, Collection::stream, Collection::parallelStream, + Collection::spliterator, Collection::size); + } + + public static OfRef ofSpinedBuffer(String name, SpinedBuffer buffer) { + return new AbstractTestData.RefTestData<>(name, buffer, + b -> StreamSupport.stream(b.spliterator()), + b -> StreamSupport.parallelStream(b.spliterator()), + SpinedBuffer::spliterator, + b -> (int) b.count()); + } + + public static OfRef ofSupplier(String name, Supplier> supplier) { + return new AbstractTestData.RefTestData<>(name, supplier, + Supplier::get, + s -> s.get().parallel(), + s -> s.get().spliterator(), + s -> (int) s.get().spliterator().getExactSizeIfKnown()); + } + + public static OfRef ofRefNode(String name, Node node) { + return new AbstractTestData.RefTestData<>(name, node, + n -> StreamSupport.stream(n::spliterator, Spliterator.SIZED | Spliterator.ORDERED), + n -> StreamSupport.parallelStream(n::spliterator, Spliterator.SIZED | Spliterator.ORDERED), + Node::spliterator, + n -> (int) n.count()); + } + + // int factories + public static OfInt ofArray(String name, int[] array) { + return new AbstractTestData.IntTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(), + Arrays::spliterator, a -> a.length); + } + + public static OfInt ofSpinedBuffer(String name, SpinedBuffer.OfInt buffer) { + return new AbstractTestData.IntTestData<>(name, buffer, + b -> StreamSupport.intStream(b.spliterator()), + b -> StreamSupport.intParallelStream(b.spliterator()), + SpinedBuffer.OfInt::spliterator, + b -> (int) b.count()); + } + + public static OfInt ofIntSupplier(String name, Supplier supplier) { + return new AbstractTestData.IntTestData<>(name, supplier, + Supplier::get, + s -> s.get().parallel(), + s -> s.get().spliterator(), + s -> (int) s.get().spliterator().getExactSizeIfKnown()); + } + + public static OfInt ofNode(String name, Node.OfInt node) { + int characteristics = Spliterator.SIZED | Spliterator.ORDERED; + return new AbstractTestData.IntTestData<>(name, node, + n -> StreamSupport.intStream(n::spliterator, characteristics), + n -> StreamSupport.intParallelStream(n::spliterator, characteristics), + Node.OfInt::spliterator, + n -> (int) n.count()); + } + + // long factories + public static OfLong ofArray(String name, long[] array) { + return new AbstractTestData.LongTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(), + Arrays::spliterator, a -> a.length); + } + + public static OfLong ofSpinedBuffer(String name, SpinedBuffer.OfLong buffer) { + return new AbstractTestData.LongTestData<>(name, buffer, + b -> StreamSupport.longStream(b.spliterator()), + b -> StreamSupport.longParallelStream(b.spliterator()), + SpinedBuffer.OfLong::spliterator, + b -> (int) b.count()); + } + + public static OfLong ofLongSupplier(String name, Supplier supplier) { + return new AbstractTestData.LongTestData<>(name, supplier, + Supplier::get, + s -> s.get().parallel(), + s -> s.get().spliterator(), + s -> (int) s.get().spliterator().getExactSizeIfKnown()); + } + + public static OfLong ofNode(String name, Node.OfLong node) { + int characteristics = Spliterator.SIZED | Spliterator.ORDERED; + return new AbstractTestData.LongTestData<>(name, node, + n -> StreamSupport.longStream(n::spliterator, characteristics), + n -> StreamSupport.longParallelStream(n::spliterator, characteristics), + Node.OfLong::spliterator, + n -> (int) n.count()); + } + + // double factories + public static OfDouble ofArray(String name, double[] array) { + return new AbstractTestData.DoubleTestData<>(name, array, Arrays::stream, a -> Arrays.stream(a).parallel(), + Arrays::spliterator, a -> a.length); + } + + public static OfDouble ofSpinedBuffer(String name, SpinedBuffer.OfDouble buffer) { + return new AbstractTestData.DoubleTestData<>(name, buffer, + b -> StreamSupport.doubleStream(b.spliterator()), + b -> StreamSupport.doubleParallelStream(b.spliterator()), + SpinedBuffer.OfDouble::spliterator, + b -> (int) b.count()); + } + + public static OfDouble ofDoubleSupplier(String name, Supplier supplier) { + return new AbstractTestData.DoubleTestData<>(name, supplier, + Supplier::get, + s -> s.get().parallel(), + s -> s.get().spliterator(), + s -> (int) s.get().spliterator().getExactSizeIfKnown()); + } + + public static OfDouble ofNode(String name, Node.OfDouble node) { + int characteristics = Spliterator.SIZED | Spliterator.ORDERED; + return new AbstractTestData.DoubleTestData<>(name, node, + n -> StreamSupport.doubleStream(n::spliterator, characteristics), + n -> StreamSupport.doubleParallelStream(n::spliterator, characteristics), + Node.OfDouble::spliterator, + n -> (int) n.count()); + } + } + + + abstract class AbstractTestData, + T_STATE, + T_SPLITR extends Spliterator> + implements TestData { + private final String name; + private final StreamShape shape; + protected final T_STATE state; + private final ToIntFunction sizeFn; + private final Function streamFn; + private final Function parStreamFn; + private final Function splitrFn; + + AbstractTestData(String name, + StreamShape shape, + T_STATE state, + Function streamFn, + Function parStreamFn, + Function splitrFn, + ToIntFunction sizeFn) { + this.name = name; + this.shape = shape; + this.state = state; + this.streamFn = streamFn; + this.parStreamFn = parStreamFn; + this.splitrFn = splitrFn; + this.sizeFn = sizeFn; + } + + @Override + public StreamShape getShape() { + return shape; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + name + "]"; + } + + @Override + public int size() { + return sizeFn.applyAsInt(state); + } + + @Override + public T_SPLITR spliterator() { + return splitrFn.apply(state); + } + + @Override + public S stream() { + return streamFn.apply(state); + } + + @Override + public S parallelStream() { + return parStreamFn.apply(state); + } + + public static class RefTestData + extends AbstractTestData, I, Spliterator> + implements TestData.OfRef { + + protected RefTestData(String name, + I state, + Function> streamFn, + Function> parStreamFn, + Function> splitrFn, + ToIntFunction sizeFn) { + super(name, StreamShape.REFERENCE, state, streamFn, parStreamFn, splitrFn, sizeFn); + } + + } + + static class IntTestData + extends AbstractTestData + implements TestData.OfInt { + + protected IntTestData(String name, + I state, + Function streamFn, + Function parStreamFn, + Function splitrFn, + ToIntFunction sizeFn) { + super(name, StreamShape.INT_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn); + } + + @Override + public PrimitiveIterator.OfInt iterator() { + return Spliterators.iteratorFromSpliterator(spliterator()); + } + + @Override + public > A into(A target) { + spliterator().forEachRemaining((IntConsumer) target::add); + return target; + } + } + + static class LongTestData + extends AbstractTestData + implements TestData.OfLong { + + protected LongTestData(String name, + I state, + Function streamFn, + Function parStreamFn, + Function splitrFn, + ToIntFunction sizeFn) { + super(name, StreamShape.LONG_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn); + } + + @Override + public PrimitiveIterator.OfLong iterator() { + return Spliterators.iteratorFromSpliterator(spliterator()); + } + + @Override + public > A into(A target) { + spliterator().forEachRemaining((LongConsumer) target::add); + return target; + } + } + + static class DoubleTestData + extends AbstractTestData + implements OfDouble { + + protected DoubleTestData(String name, + I state, + Function streamFn, + Function parStreamFn, + Function splitrFn, + ToIntFunction sizeFn) { + super(name, StreamShape.DOUBLE_VALUE, state, streamFn, parStreamFn, splitrFn, sizeFn); + } + + @Override + public PrimitiveIterator.OfDouble iterator() { + return Spliterators.iteratorFromSpliterator(spliterator()); + } + + @Override + public > A into(A target) { + spliterator().forEachRemaining((DoubleConsumer) target::add); + return target; + } + } + } +} diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/TestFlagExpectedOp.java b/jdk/test/java/util/stream/bootlib/java/util/stream/TestFlagExpectedOp.java new file mode 100644 index 00000000000..c59a1855501 --- /dev/null +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/TestFlagExpectedOp.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import org.testng.Assert; + +import java.util.EnumSet; + +class TestFlagExpectedOp extends FlagDeclaringOp { + + static class Builder { + final int flags; + StreamShape shape = StreamShape.REFERENCE; + + EnumSet known = EnumSet.noneOf(StreamOpFlag.class); + EnumSet preserve = EnumSet.noneOf(StreamOpFlag.class); + EnumSet notKnown = EnumSet.noneOf(StreamOpFlag.class); + + Builder(int flags) { + this.flags = flags; + } + + Builder known(EnumSet known) { + this.known = known; + return this; + } + + Builder preserve(EnumSet preserve) { + this.preserve = preserve; + return this; + } + + Builder notKnown(EnumSet notKnown) { + this.notKnown = notKnown; + return this; + } + + Builder shape(StreamShape shape) { + this.shape = shape; + return this; + } + + TestFlagExpectedOp build() { + return new TestFlagExpectedOp<>(flags, known, preserve, notKnown, shape); + } + } + + final EnumSet known; + final EnumSet preserve; + final EnumSet notKnown; + final StreamShape shape; + + TestFlagExpectedOp(int flags, + EnumSet known, + EnumSet preserve, + EnumSet notKnown) { + this(flags, known, preserve, notKnown, StreamShape.REFERENCE); + } + + TestFlagExpectedOp(int flags, + EnumSet known, + EnumSet preserve, + EnumSet notKnown, + StreamShape shape) { + super(flags); + this.known = known; + this.preserve = preserve; + this.notKnown = notKnown; + this.shape = shape; + } + + @Override + public StreamShape outputShape() { + return shape; + } + + @Override + public StreamShape inputShape() { + return shape; + } + + @Override + @SuppressWarnings({"rawtypes", "unchecked"}) + public Sink opWrapSink(int flags, boolean parallel, Sink upstream) { + assertFlags(flags); + return upstream; + } + + private void assertFlags(int flags) { + for (StreamOpFlag f : known) { + Assert.assertTrue(f.isKnown(flags), + String.format("Flag %s is not known, but should be known.", f.toString())); + } + + for (StreamOpFlag f : preserve) { + Assert.assertTrue(f.isPreserved(flags), + String.format("Flag %s is not preserved, but should be preserved.", f.toString())); + } + + for (StreamOpFlag f : notKnown) { + Assert.assertFalse(f.isKnown(flags), + String.format("Flag %s is known, but should be not known.", f.toString())); + } + } +} diff --git a/jdk/test/java/util/stream/boottest/TEST.properties b/jdk/test/java/util/stream/boottest/TEST.properties new file mode 100644 index 00000000000..d51ddf7889a --- /dev/null +++ b/jdk/test/java/util/stream/boottest/TEST.properties @@ -0,0 +1,5 @@ +# This file identifies root(s) of the test-ng hierarchy. + +TestNG.dirs = . +bootclasspath.dirs = . +lib.dirs = /java/util/stream/bootlib diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/DoubleNodeTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/DoubleNodeTest.java new file mode 100644 index 00000000000..7ad4801e421 --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/DoubleNodeTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013, 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. + * + * 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 java.util.stream; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.PrimitiveIterator; +import java.util.Spliterators; +import java.util.function.Function; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@Test +public class DoubleNodeTest extends OpTestCase { + + @DataProvider(name = "nodes") + public Object[][] createSizes() { + List params = new ArrayList<>(); + + for (int size : Arrays.asList(0, 1, 4, 15, 16, 17, 127, 128, 129, 1000)) { + double[] array = new double[size]; + for (int i = 0; i < array.length; i++) { + array[i] = i; + } + + List> nodes = new ArrayList<>(); + + nodes.add(Nodes.node(array)); + nodes.add(degenerateTree(Spliterators.iteratorFromSpliterator(Arrays.spliterator(array)))); + nodes.add(tree(toList(array), l -> Nodes.node(toDoubleArray(l)))); + nodes.add(fill(array, Nodes.doubleBuilder(array.length))); + nodes.add(fill(array, Nodes.doubleBuilder())); + + for (Node node : nodes) { + params.add(new Object[]{array, node}); + } + + } + + return params.toArray(new Object[0][]); + } + + private static void assertEqualsListDoubleArray(List list, double[] array) { + assertEquals(list.size(), array.length); + for (int i = 0; i < array.length; i++) + assertEquals(array[i], list.get(i)); + } + + private List toList(double[] a) { + List l = new ArrayList<>(); + for (double i : a) { + l.add(i); + } + + return l; + } + + private double[] toDoubleArray(List l) { + double[] a = new double[l.size()]; + + int i = 0; + for (Double e : l) { + a[i++] = e; + } + return a; + } + + private Node.OfDouble fill(double[] array, Node.Builder.OfDouble nb) { + nb.begin(array.length); + for (double i : array) + nb.accept(i); + nb.end(); + return nb.build(); + } + + private Node.OfDouble degenerateTree(PrimitiveIterator.OfDouble it) { + if (!it.hasNext()) { + return Nodes.node(new double[0]); + } + + double i = it.nextDouble(); + if (it.hasNext()) { + return new Nodes.DoubleConcNode(Nodes.node(new double[] {i}), degenerateTree(it)); + } + else { + return Nodes.node(new double[] {i}); + } + } + + private Node.OfDouble tree(List l, Function, Node.OfDouble> m) { + if (l.size() < 3) { + return m.apply(l); + } + else { + return new Nodes.DoubleConcNode( + tree(l.subList(0, l.size() / 2), m), + tree(l.subList(l.size() / 2, l.size()), m)); + } + } + + @Test(dataProvider = "nodes") + public void testAsArray(double[] array, Node.OfDouble n) { + assertEquals(n.asDoubleArray(), array); + } + + @Test(dataProvider = "nodes") + public void testFlattenAsArray(double[] array, Node.OfDouble n) { + assertEquals(Nodes.flattenDouble(n).asDoubleArray(), array); + } + + @Test(dataProvider = "nodes") + public void testCopyTo(double[] array, Node.OfDouble n) { + double[] copy = new double[(int) n.count()]; + n.copyInto(copy, 0); + + assertEquals(copy, array); + } + + @Test(dataProvider = "nodes", groups = { "serialization-hostile" }) + public void testForEach(double[] array, Node.OfDouble n) { + List l = new ArrayList<>((int) n.count()); + n.forEach((double e) -> { + l.add(e); + }); + + assertEqualsListDoubleArray(l, array); + } + + @Test(dataProvider = "nodes") + public void testStreams(double[] array, Node.OfDouble n) { + TestData.OfDouble data = TestData.Factory.ofNode("Node", n); + + exerciseOps(data, s -> s); + + exerciseTerminalOps(data, s -> s.toArray()); + } + + @Test(dataProvider = "nodes", groups={ "serialization-hostile" }) + // throws SOE on serialization of DoubleConcNode[size=1000] + public void testSpliterator(double[] array, Node.OfDouble n) { + SpliteratorTestHelper.testDoubleSpliterator(n::spliterator); + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/FlagOpTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/FlagOpTest.java new file mode 100644 index 00000000000..602d51febbd --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/FlagOpTest.java @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.function.Supplier; + +import static java.util.stream.LambdaTestHelpers.countTo; + +@Test +public class FlagOpTest extends OpTestCase { + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testFlagsPassThrough(String name, TestData> data) { + + @SuppressWarnings({"unchecked", "rawtypes"}) + TestFlagPassThroughOp[] ops = new TestFlagPassThroughOp[3]; + ops[0] = new TestFlagPassThroughOp<>(); + ops[1] = new TestFlagPassThroughOp<>(); + ops[2] = new TestFlagPassThroughOp<>(); + + ops[0].set(null, ops[1]); + ops[1].set(ops[0], ops[2]); + ops[2].set(ops[1], null); + + withData(data).ops(ops).exercise(); + } + + static class TestFlagPassThroughOp extends FlagDeclaringOp { + TestFlagPassThroughOp upstream; + TestFlagPassThroughOp downstream; + + TestFlagPassThroughOp() { + super(0); + } + + void set(TestFlagPassThroughOp upstream, TestFlagPassThroughOp downstream) { + this.upstream = upstream; + this.downstream = downstream; + } + + int wrapFlags; + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public Sink opWrapSink(int flags, boolean parallel, Sink sink) { + this.wrapFlags = flags; + + if (downstream != null) { + assertTrue(flags == downstream.wrapFlags); + } + + return sink; + } + } + + public void testFlagsClearAllSet() { + int clearAllFlags = 0; + for (StreamOpFlag f : EnumSet.allOf(StreamOpFlag.class)) { + if (f.isStreamFlag()) { + clearAllFlags |= f.clear(); + } + } + + EnumSet known = EnumSet.noneOf(StreamOpFlag.class); + EnumSet notKnown = StreamOpFlagTestHelper.allStreamFlags(); + + List> ops = new ArrayList<>(); + ops.add(new FlagDeclaringOp<>(clearAllFlags)); + for (StreamOpFlag f : StreamOpFlagTestHelper.allStreamFlags()) { + if (f.canSet(StreamOpFlag.Type.OP)) { + ops.add(new TestFlagExpectedOp<>(f.set(), + known.clone(), + EnumSet.noneOf(StreamOpFlag.class), + notKnown.clone())); + known.add(f); + notKnown.remove(f); + } + } + ops.add(new TestFlagExpectedOp<>(0, + known.clone(), + EnumSet.noneOf(StreamOpFlag.class), + notKnown.clone())); + + TestData> data = TestData.Factory.ofArray("Array", countTo(10).toArray(new Integer[0])); + @SuppressWarnings("rawtypes") + FlagDeclaringOp[] opsArray = ops.toArray(new FlagDeclaringOp[ops.size()]); + + withData(data).ops(opsArray). + without(StreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED). + exercise(); + } + + public void testFlagsSetAllClear() { + EnumSet known = StreamOpFlagTestHelper.allStreamFlags(); + int setAllFlags = 0; + for (StreamOpFlag f : EnumSet.allOf(StreamOpFlag.class)) { + if (f.isStreamFlag()) { + if (f.canSet(StreamOpFlag.Type.OP)) { + setAllFlags |= f.set(); + } else { + known.remove(f); + } + } + } + + EnumSet notKnown = EnumSet.noneOf(StreamOpFlag.class); + + List> ops = new ArrayList<>(); + ops.add(new FlagDeclaringOp<>(setAllFlags)); + for (StreamOpFlag f : StreamOpFlagTestHelper.allStreamFlags()) { + ops.add(new TestFlagExpectedOp<>(f.clear(), + known.clone(), + EnumSet.noneOf(StreamOpFlag.class), + notKnown.clone())); + known.remove(f); + notKnown.add(f); + } + ops.add(new TestFlagExpectedOp<>(0, + known.clone(), + EnumSet.noneOf(StreamOpFlag.class), + notKnown.clone())); + + TestData> data = TestData.Factory.ofArray("Array", countTo(10).toArray(new Integer[0])); + @SuppressWarnings("rawtypes") + FlagDeclaringOp[] opsArray = ops.toArray(new FlagDeclaringOp[ops.size()]); + + + withData(data).ops(opsArray). + without(StreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED). + exercise(); + } + + public void testFlagsParallelCollect() { + testFlagsSetSequence(CollectorOps::collector); + } + + private void testFlagsSetSequence(Supplier> cf) { + EnumSet known = EnumSet.of(StreamOpFlag.ORDERED, StreamOpFlag.SIZED); + EnumSet preserve = EnumSet.of(StreamOpFlag.DISTINCT, StreamOpFlag.SORTED); + + List> ops = new ArrayList<>(); + for (StreamOpFlag f : EnumSet.of(StreamOpFlag.DISTINCT, StreamOpFlag.SORTED)) { + ops.add(cf.get()); + ops.add(new TestFlagExpectedOp<>(f.set(), + known.clone(), + preserve.clone(), + EnumSet.noneOf(StreamOpFlag.class))); + known.add(f); + preserve.remove(f); + } + ops.add(cf.get()); + ops.add(new TestFlagExpectedOp<>(0, + known.clone(), + preserve.clone(), + EnumSet.noneOf(StreamOpFlag.class))); + + TestData> data = TestData.Factory.ofArray("Array", countTo(10).toArray(new Integer[0])); + @SuppressWarnings("rawtypes") + IntermediateTestOp[] opsArray = ops.toArray(new IntermediateTestOp[ops.size()]); + + withData(data).ops(opsArray). + without(StreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED). + exercise(); + } + + + public void testFlagsClearParallelCollect() { + testFlagsClearSequence(CollectorOps::collector); + } + + protected void testFlagsClearSequence(Supplier> cf) { + EnumSet known = EnumSet.of(StreamOpFlag.ORDERED, StreamOpFlag.SIZED); + EnumSet preserve = EnumSet.of(StreamOpFlag.DISTINCT, StreamOpFlag.SORTED); + EnumSet notKnown = EnumSet.noneOf(StreamOpFlag.class); + + List> ops = new ArrayList<>(); + for (StreamOpFlag f : EnumSet.of(StreamOpFlag.ORDERED, StreamOpFlag.DISTINCT, StreamOpFlag.SORTED)) { + ops.add(cf.get()); + ops.add(new TestFlagExpectedOp<>(f.clear(), + known.clone(), + preserve.clone(), + notKnown.clone())); + known.remove(f); + preserve.remove(f); + notKnown.add(f); + } + ops.add(cf.get()); + ops.add(new TestFlagExpectedOp<>(0, + known.clone(), + preserve.clone(), + notKnown.clone())); + + TestData> data = TestData.Factory.ofArray("Array", countTo(10).toArray(new Integer[0])); + @SuppressWarnings("rawtypes") + IntermediateTestOp[] opsArray = ops.toArray(new IntermediateTestOp[ops.size()]); + + withData(data).ops(opsArray). + without(StreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED). + exercise(); + } + + public void testFlagsSizedOrderedParallelCollect() { + EnumSet parKnown = EnumSet.of(StreamOpFlag.SIZED); + EnumSet serKnown = parKnown.clone(); + + List> ops = new ArrayList<>(); + for (StreamOpFlag f : parKnown) { + ops.add(CollectorOps.collector()); + ops.add(new ParSerTestFlagExpectedOp<>(f.clear(), + parKnown, + serKnown)); + serKnown.remove(f); + } + ops.add(CollectorOps.collector()); + ops.add(new ParSerTestFlagExpectedOp<>(0, + parKnown, + EnumSet.noneOf(StreamOpFlag.class))); + + TestData> data = TestData.Factory.ofArray("Array", countTo(10).toArray(new Integer[0])); + @SuppressWarnings("rawtypes") + IntermediateTestOp[] opsArray = ops.toArray(new IntermediateTestOp[ops.size()]); + + withData(data).ops(opsArray).exercise(); + } + + static class ParSerTestFlagExpectedOp extends FlagDeclaringOp { + final EnumSet parKnown; + final EnumSet serKnown; + + ParSerTestFlagExpectedOp(int flags, EnumSet known, EnumSet serKnown) { + super(flags); + this.parKnown = known; + this.serKnown = serKnown; + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + public Sink opWrapSink(int flags, boolean parallel, Sink upstream) { + assertFlags(flags, parallel); + return upstream; + } + + protected void assertFlags(int flags, boolean parallel) { + if (parallel) { + for (StreamOpFlag f : parKnown) { + Assert.assertTrue(f.isKnown(flags), String.format("Flag %s is not known, but should be known.", f.toString())); + } + + } else { + for (StreamOpFlag f : serKnown) { + Assert.assertTrue(f.isKnown(flags), String.format("Flag %s is not known, but should be known.", f.toString())); + } + + } + } + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/IntNodeTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/IntNodeTest.java new file mode 100644 index 00000000000..0d345ad451a --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/IntNodeTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.PrimitiveIterator; +import java.util.Spliterators; +import java.util.function.Function; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@Test +public class IntNodeTest extends OpTestCase { + + @DataProvider(name = "nodes") + public Object[][] createSizes() { + List params = new ArrayList<>(); + + for (int size : Arrays.asList(0, 1, 4, 15, 16, 17, 127, 128, 129, 1000)) { + int[] array = new int[size]; + for (int i = 0; i < array.length; i++) { + array[i] = i; + } + + List> nodes = new ArrayList<>(); + + nodes.add(Nodes.node(array)); + nodes.add(degenerateTree(Spliterators.iteratorFromSpliterator(Arrays.spliterator(array)))); + nodes.add(tree(toList(array), l -> Nodes.node(toIntArray(l)))); + nodes.add(fill(array, Nodes.intBuilder(array.length))); + nodes.add(fill(array, Nodes.intBuilder())); + + for (Node node : nodes) { + params.add(new Object[]{array, node}); + } + + } + + return params.toArray(new Object[0][]); + } + + private static void assertEqualsListIntArray(List list, int[] array) { + assertEquals(list.size(), array.length); + for (int i = 0; i < array.length; i++) + assertEquals(array[i], (int) list.get(i)); + } + + private List toList(int[] a) { + List l = new ArrayList<>(); + for (int i : a) { + l.add(i); + } + + return l; + } + + private int[] toIntArray(List l) { + int[] a = new int[l.size()]; + + int i = 0; + for (Integer e : l) { + a[i++] = e; + } + return a; + } + + private Node.OfInt fill(int[] array, Node.Builder.OfInt nb) { + nb.begin(array.length); + for (int i : array) + nb.accept(i); + nb.end(); + return nb.build(); + } + + private Node.OfInt degenerateTree(PrimitiveIterator.OfInt it) { + if (!it.hasNext()) { + return Nodes.node(new int[0]); + } + + int i = it.nextInt(); + if (it.hasNext()) { + return new Nodes.IntConcNode(Nodes.node(new int[] {i}), degenerateTree(it)); + } + else { + return Nodes.node(new int[] {i}); + } + } + + private Node.OfInt tree(List l, Function, Node.OfInt> m) { + if (l.size() < 3) { + return m.apply(l); + } + else { + return new Nodes.IntConcNode( + tree(l.subList(0, l.size() / 2), m), + tree(l.subList(l.size() / 2, l.size()), m)); + } + } + + @Test(dataProvider = "nodes") + public void testAsArray(int[] array, Node.OfInt n) { + assertEquals(n.asIntArray(), array); + } + + @Test(dataProvider = "nodes") + public void testFlattenAsArray(int[] array, Node.OfInt n) { + assertEquals(Nodes.flattenInt(n).asIntArray(), array); + } + + @Test(dataProvider = "nodes") + public void testCopyTo(int[] array, Node.OfInt n) { + int[] copy = new int[(int) n.count()]; + n.copyInto(copy, 0); + + assertEquals(copy, array); + } + + @Test(dataProvider = "nodes", groups = { "serialization-hostile" }) + public void testForEach(int[] array, Node.OfInt n) { + List l = new ArrayList<>((int) n.count()); + n.forEach((int e) -> { + l.add(e); + }); + + assertEqualsListIntArray(l, array); + } + + @Test(dataProvider = "nodes") + public void testStreams(int[] array, Node.OfInt n) { + TestData.OfInt data = TestData.Factory.ofNode("Node", n); + + exerciseOps(data, s -> s); + exerciseTerminalOps(data, s -> s.toArray()); + } + + @Test(dataProvider = "nodes") + public void testSpliterator(int[] array, Node.OfInt n) { + SpliteratorTestHelper.testIntSpliterator(n::spliterator); + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/LongNodeTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/LongNodeTest.java new file mode 100644 index 00000000000..0b101a04ad9 --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/LongNodeTest.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2013, 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. + * + * 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 java.util.stream; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.PrimitiveIterator; +import java.util.Spliterators; +import java.util.function.Function; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@Test +public class LongNodeTest extends OpTestCase { + + @DataProvider(name = "nodes") + public Object[][] createSizes() { + List params = new ArrayList<>(); + + for (int size : Arrays.asList(0, 1, 4, 15, 16, 17, 127, 128, 129, 1000)) { + long[] array = new long[size]; + for (int i = 0; i < array.length; i++) { + array[i] = i; + } + + List> nodes = new ArrayList<>(); + + nodes.add(Nodes.node(array)); + nodes.add(degenerateTree(Spliterators.iteratorFromSpliterator(Arrays.spliterator(array)))); + nodes.add(tree(toList(array), l -> Nodes.node(toLongArray(l)))); + nodes.add(fill(array, Nodes.longBuilder(array.length))); + nodes.add(fill(array, Nodes.longBuilder())); + + for (Node node : nodes) { + params.add(new Object[]{array, node}); + } + + } + + return params.toArray(new Object[0][]); + } + + private static void assertEqualsListLongArray(List list, long[] array) { + assertEquals(list.size(), array.length); + for (int i = 0; i < array.length; i++) + assertEquals(array[i], (long) list.get(i)); + } + + private List toList(long[] a) { + List l = new ArrayList<>(); + for (long i : a) { + l.add(i); + } + + return l; + } + + private long[] toLongArray(List l) { + long[] a = new long[l.size()]; + + int i = 0; + for (Long e : l) { + a[i++] = e; + } + return a; + } + + private Node.OfLong fill(long[] array, Node.Builder.OfLong nb) { + nb.begin(array.length); + for (long i : array) + nb.accept(i); + nb.end(); + return nb.build(); + } + + private Node.OfLong degenerateTree(PrimitiveIterator.OfLong it) { + if (!it.hasNext()) { + return Nodes.node(new long[0]); + } + + long i = it.nextLong(); + if (it.hasNext()) { + return new Nodes.LongConcNode(Nodes.node(new long[] {i}), degenerateTree(it)); + } + else { + return Nodes.node(new long[] {i}); + } + } + + private Node.OfLong tree(List l, Function, Node.OfLong> m) { + if (l.size() < 3) { + return m.apply(l); + } + else { + return new Nodes.LongConcNode( + tree(l.subList(0, l.size() / 2), m), + tree(l.subList(l.size() / 2, l.size()), m)); + } + } + + @Test(dataProvider = "nodes") + public void testAsArray(long[] array, Node.OfLong n) { + assertEquals(n.asLongArray(), array); + } + + @Test(dataProvider = "nodes") + public void testFlattenAsArray(long[] array, Node.OfLong n) { + assertEquals(Nodes.flattenLong(n).asLongArray(), array); + } + + @Test(dataProvider = "nodes") + public void testCopyTo(long[] array, Node.OfLong n) { + long[] copy = new long[(int) n.count()]; + n.copyInto(copy, 0); + + assertEquals(copy, array); + } + + @Test(dataProvider = "nodes", groups = { "serialization-hostile" }) + public void testForEach(long[] array, Node.OfLong n) { + List l = new ArrayList<>((int) n.count()); + n.forEach((long e) -> { + l.add(e); + }); + + assertEqualsListLongArray(l, array); + } + + @Test(dataProvider = "nodes") + public void testStreams(long[] array, Node.OfLong n) { + TestData.OfLong data = TestData.Factory.ofNode("Node", n); + + exerciseOps(data, s -> s); + + exerciseTerminalOps(data, s -> s.toArray()); + } + + @Test(dataProvider = "nodes") + public void testSpliterator(long[] array, Node.OfLong n) { + SpliteratorTestHelper.testLongSpliterator(n::spliterator); + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/NodeBuilderTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/NodeBuilderTest.java new file mode 100644 index 00000000000..11fe86f318e --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/NodeBuilderTest.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.DoubleConsumer; +import java.util.function.Function; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static java.util.stream.LambdaTestHelpers.assertContents; +import static java.util.stream.LambdaTestHelpers.countTo; +import static org.testng.Assert.assertEquals; + +@Test +public class NodeBuilderTest { + + List sizes = Arrays.asList(0, 1, 4, 16, 256, + 1023, 1024, 1025, + 2047, 2048, 2049, + 1024 * 32 - 1, 1024 * 32, 1024 * 32 + 1); + + @DataProvider(name = "Node.Builder") + public Object[][] createNodeBuilders() { + List> ls = new ArrayList<>(); + for (int size : sizes) { + ls.add(countTo(size)); + } + + List>> ms = Arrays.asList( + s -> Nodes.builder(), + s -> Nodes.builder(s, LambdaTestHelpers.integerArrayGenerator) + ); + + Object[][] params = new Object[ls.size() * ms.size()][]; + int i = 0; + for (List l : ls) { + for (Function> m : ms) { + params[i++] = new Object[]{l, m}; + } + } + + return params; + } + + @Test(dataProvider = "Node.Builder", groups = { "serialization-hostile" }) + public void testIteration(List l, Function> m) { + Node.Builder nb = m.apply(l.size()); + nb.begin(l.size()); + for (Integer i : l) { + nb.accept(i); + } + nb.end(); + + Node n = nb.build(); + assertEquals(n.count(), l.size()); + + { + List _l = new ArrayList<>(); + n.forEach(_l::add); + + assertContents(_l, l); + } + } + + // Node.Builder.OfInt + + @DataProvider(name = "Node.Builder") + public Object[][] createIntNodeBuilders() { + List> ls = new ArrayList<>(); + for (int size : sizes) { + ls.add(countTo(size)); + } + + List>> ms = Arrays.asList( + s -> Nodes.intBuilder(), + s -> Nodes.intBuilder(s) + ); + + Object[][] params = new Object[ls.size() * ms.size()][]; + int i = 0; + for (List l : ls) { + for (Function> m : ms) { + params[i++] = new Object[]{l, m}; + } + } + + return params; + } + + @Test(dataProvider = "Node.Builder", groups = { "serialization-hostile" }) + public void testIntIteration(List l, Function m) { + Node.Builder.OfInt nb = m.apply(l.size()); + nb.begin(l.size()); + for (Integer i : l) { + nb.accept((int) i); + } + nb.end(); + + Node.OfInt n = nb.build(); + assertEquals(n.count(), l.size()); + + { + List _l = new ArrayList<>(); + n.forEach((IntConsumer) _l::add); + + assertContents(_l, l); + } + + } + + // Node.Builder.OfLong + + @DataProvider(name = "Node.Builder") + public Object[][] createLongNodeBuilders() { + List> ls = new ArrayList<>(); + for (int size : sizes) { + List l = new ArrayList<>(); + for (long i = 0; i < size; i++) { + l.add(i); + } + ls.add(l); + } + + List>> ms = Arrays.asList( + s -> Nodes.longBuilder(), + s -> Nodes.longBuilder(s) + ); + + Object[][] params = new Object[ls.size() * ms.size()][]; + int i = 0; + for (List l : ls) { + for (Function> m : ms) { + params[i++] = new Object[]{l, m}; + } + } + + return params; + } + + @Test(dataProvider = "Node.Builder") + public void testLongIteration(List l, Function m) { + Node.Builder.OfLong nb = m.apply(l.size()); + nb.begin(l.size()); + for (Long i : l) { + nb.accept((long) i); + } + nb.end(); + + Node.OfLong n = nb.build(); + assertEquals(n.count(), l.size()); + + { + List _l = new ArrayList<>(); + n.forEach((LongConsumer) _l::add); + + assertContents(_l, l); + } + + } + + // Node.Builder.OfDouble + + @DataProvider(name = "Node.Builder") + public Object[][] createDoubleNodeBuilders() { + List> ls = new ArrayList<>(); + for (int size : sizes) { + List l = new ArrayList<>(); + for (long i = 0; i < size; i++) { + l.add((double) i); + } + ls.add(l); + } + + List>> ms = Arrays.asList( + s -> Nodes.doubleBuilder(), + s -> Nodes.doubleBuilder(s) + ); + + Object[][] params = new Object[ls.size() * ms.size()][]; + int i = 0; + for (List l : ls) { + for (Function> m : ms) { + params[i++] = new Object[]{l, m}; + } + } + + return params; + } + + @Test(dataProvider = "Node.Builder") + public void testDoubleIteration(List l, Function m) { + Node.Builder.OfDouble nb = m.apply(l.size()); + nb.begin(l.size()); + for (Double i : l) { + nb.accept((double) i); + } + nb.end(); + + Node.OfDouble n = nb.build(); + assertEquals(n.count(), l.size()); + + { + List _l = new ArrayList<>(); + n.forEach((DoubleConsumer) _l::add); + + assertContents(_l, l); + } + + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/NodeTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/NodeTest.java new file mode 100644 index 00000000000..8f5bff5cb66 --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/NodeTest.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.function.Function; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@Test +public class NodeTest extends OpTestCase { + + @DataProvider(name = "nodes") + public Object[][] createSizes() { + List params = new ArrayList<>(); + + for (int size : Arrays.asList(0, 1, 4, 15, 16, 17, 127, 128, 129, 1000)) { + Integer[] array = new Integer[size]; + for (int i = 0; i < array.length; i++) { + array[i] = i; + } + + List> nodes = new ArrayList<>(); + nodes.add(Nodes.node(array)); + nodes.add(Nodes.node(Arrays.asList(array))); + nodes.add(degenerateTree(Arrays.asList(array).iterator())); + nodes.add(tree(Arrays.asList(array), l -> Nodes.node(l.toArray(new Integer[l.size()])))); + nodes.add(tree(Arrays.asList(array), l -> Nodes.node(l))); + nodes.add(fill(array, Nodes.builder(array.length, LambdaTestHelpers.integerArrayGenerator))); + nodes.add(fill(array, Nodes.builder())); + + for (int i = 0; i < nodes.size(); i++) { + params.add(new Object[]{array, nodes.get(i)}); + } + + } + + return params.toArray(new Object[0][]); + } + + Node fill(Integer[] array, Node.Builder nb) { + nb.begin(array.length); + for (Integer i : array) { + nb.accept(i); + } + nb.end(); + return nb.build(); + } + + Node degenerateTree(Iterator it) { + if (!it.hasNext()) { + return Nodes.node(Collections.emptyList()); + } + + Integer i = it.next(); + if (it.hasNext()) { + return new Nodes.ConcNode(Nodes.node(new Integer[] {i}), degenerateTree(it)); + } + else { + return Nodes.node(new Integer[]{i}); + } + } + + Node tree(List l, Function, Node> m) { + if (l.size() < 3) { + return m.apply(l); + } + else { + return new Nodes.ConcNode<>( + tree(l.subList(0, l.size() / 2), m), + tree(l.subList(l.size() / 2, l.size()), m )); + } + } + + @Test(dataProvider = "nodes") + public void testAsArray(Integer[] array, Node n) { + assertEquals(n.asArray(LambdaTestHelpers.integerArrayGenerator), array); + } + + @Test(dataProvider = "nodes") + public void testFlattenAsArray(Integer[] array, Node n) { + assertEquals(Nodes.flatten(n, LambdaTestHelpers.integerArrayGenerator) + .asArray(LambdaTestHelpers.integerArrayGenerator), array); + } + + @Test(dataProvider = "nodes") + public void testCopyTo(Integer[] array, Node n) { + Integer[] copy = new Integer[(int) n.count()]; + n.copyInto(copy, 0); + + assertEquals(copy, array); + } + + @Test(dataProvider = "nodes", groups = { "serialization-hostile" }) + public void testForEach(Integer[] array, Node n) { + List l = new ArrayList<>((int) n.count()); + n.forEach(e -> l.add(e)); + + assertEquals(l.toArray(), array); + } + + @Test(dataProvider = "nodes") + public void testStreams(Integer[] array, Node n) { + TestData> data = TestData.Factory.ofRefNode("Node", n); + + exerciseOps(data, s -> s); + + exerciseTerminalOps(data, s -> s.toArray()); + } + + @Test(dataProvider = "nodes") + public void testSpliterator(Integer[] array, Node n) { + SpliteratorTestHelper.testSpliterator(n::spliterator); + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/SpinedBufferTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/SpinedBufferTest.java new file mode 100644 index 00000000000..3fee90b6106 --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/SpinedBufferTest.java @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.*; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; + +@Test +public class SpinedBufferTest { + + // Create sizes around the boundary of spines + static List sizes; + static { + try { + sizes = IntStream.range(0, 15) + .map(i -> 1 << i) + .flatMap(i -> Arrays.stream(new int[] { i-2, i-1, i, i+1, i+2 })) + .filter(i -> i >= 0) + .boxed() + .distinct() + .collect(Collectors.toList()); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private static final int TEST_SIZE = 5000; + + // SpinedBuffer + + @DataProvider(name = "SpinedBuffer") + public Object[][] createSpinedBuffer() { + List params = new ArrayList<>(); + + for (int size : sizes) { + int[] array = IntStream.range(0, size).toArray(); + + SpinedBuffer sb = new SpinedBuffer<>(); + Arrays.stream(array).boxed().forEach(sb); + params.add(new Object[]{array, sb}); + + sb = new SpinedBuffer<>(size / 2); + Arrays.stream(array).boxed().forEach(sb); + params.add(new Object[]{array, sb}); + + sb = new SpinedBuffer<>(size); + Arrays.stream(array).boxed().forEach(sb); + params.add(new Object[]{array, sb}); + + sb = new SpinedBuffer<>(size * 2); + Arrays.stream(array).boxed().forEach(sb); + params.add(new Object[]{array, sb}); + } + + return params.toArray(new Object[0][]); + } + + @Test(dataProvider = "SpinedBuffer") + public void testSpliterator(int[] array, SpinedBuffer sb) { + assertEquals(sb.count(), array.length); + assertEquals(sb.count(), sb.spliterator().getExactSizeIfKnown()); + + SpliteratorTestHelper.testSpliterator(sb::spliterator); + } + + @Test(dataProvider = "SpinedBuffer", groups = { "serialization-hostile" }) + public void testLastSplit(int[] array, SpinedBuffer sb) { + Spliterator spliterator = sb.spliterator(); + Spliterator split = spliterator.trySplit(); + long splitSizes = (split == null) ? 0 : split.getExactSizeIfKnown(); + long lastSplitSize = spliterator.getExactSizeIfKnown(); + splitSizes += lastSplitSize; + + assertEquals(splitSizes, array.length); + + List contentOfLastSplit = new ArrayList<>(); + spliterator.forEachRemaining(contentOfLastSplit::add); + + assertEquals(contentOfLastSplit.size(), lastSplitSize); + + List end = Arrays.stream(array) + .boxed() + .substream(array.length - lastSplitSize) + .collect(Collectors.toList()); + assertEquals(contentOfLastSplit, end); + } + + @Test(groups = { "serialization-hostile" }) + public void testSpinedBuffer() { + List list1 = new ArrayList<>(); + List list2 = new ArrayList<>(); + SpinedBuffer sb = new SpinedBuffer<>(); + for (int i = 0; i < TEST_SIZE; i++) { + list1.add(i); + sb.accept(i); + } + Iterator it = sb.iterator(); + for (int i = 0; i < TEST_SIZE; i++) + list2.add(it.next()); + assertFalse(it.hasNext()); + assertEquals(list1, list2); + + for (int i = 0; i < TEST_SIZE; i++) + assertEquals(sb.get(i), (Integer) i, Integer.toString(i)); + + list2.clear(); + sb.forEach(list2::add); + assertEquals(list1, list2); + Integer[] array = sb.asArray(LambdaTestHelpers.integerArrayGenerator); + list2.clear(); + for (Integer i : array) + list2.add(i); + assertEquals(list1, list2); + } + + // IntSpinedBuffer + + @DataProvider(name = "IntSpinedBuffer") + public Object[][] createIntSpinedBuffer() { + List params = new ArrayList<>(); + + for (int size : sizes) { + int[] array = IntStream.range(0, size).toArray(); + SpinedBuffer.OfInt sb = new SpinedBuffer.OfInt(); + Arrays.stream(array).forEach(sb); + + params.add(new Object[]{array, sb}); + } + + return params.toArray(new Object[0][]); + } + + @Test(dataProvider = "IntSpinedBuffer") + public void testIntSpliterator(int[] array, SpinedBuffer.OfInt sb) { + assertEquals(sb.count(), array.length); + assertEquals(sb.count(), sb.spliterator().getExactSizeIfKnown()); + + SpliteratorTestHelper.testIntSpliterator(sb::spliterator); + } + + @Test(dataProvider = "IntSpinedBuffer", groups = { "serialization-hostile" }) + public void testIntLastSplit(int[] array, SpinedBuffer.OfInt sb) { + Spliterator.OfInt spliterator = sb.spliterator(); + Spliterator.OfInt split = spliterator.trySplit(); + long splitSizes = (split == null) ? 0 : split.getExactSizeIfKnown(); + long lastSplitSize = spliterator.getExactSizeIfKnown(); + splitSizes += lastSplitSize; + + assertEquals(splitSizes, array.length); + + List contentOfLastSplit = new ArrayList<>(); + spliterator.forEachRemaining((IntConsumer) contentOfLastSplit::add); + + assertEquals(contentOfLastSplit.size(), lastSplitSize); + + List end = Arrays.stream(array) + .boxed() + .substream(array.length - lastSplitSize) + .collect(Collectors.toList()); + assertEquals(contentOfLastSplit, end); + } + + @Test(groups = { "serialization-hostile" }) + public void testIntSpinedBuffer() { + List list1 = new ArrayList<>(); + List list2 = new ArrayList<>(); + SpinedBuffer.OfInt sb = new SpinedBuffer.OfInt(); + for (int i = 0; i < TEST_SIZE; i++) { + list1.add(i); + sb.accept(i); + } + PrimitiveIterator.OfInt it = sb.iterator(); + for (int i = 0; i < TEST_SIZE; i++) + list2.add(it.nextInt()); + assertFalse(it.hasNext()); + assertEquals(list1, list2); + + for (int i = 0; i < TEST_SIZE; i++) + assertEquals(sb.get(i), i, Integer.toString(i)); + + list2.clear(); + sb.forEach((int i) -> list2.add(i)); + assertEquals(list1, list2); + int[] array = sb.asIntArray(); + list2.clear(); + for (int i : array) + list2.add(i); + assertEquals(list1, list2); + } + + // LongSpinedBuffer + + @DataProvider(name = "LongSpinedBuffer") + public Object[][] createLongSpinedBuffer() { + List params = new ArrayList<>(); + + for (int size : sizes) { + long[] array = LongStream.range(0, size).toArray(); + SpinedBuffer.OfLong sb = new SpinedBuffer.OfLong(); + Arrays.stream(array).forEach(sb); + + params.add(new Object[]{array, sb}); + } + + return params.toArray(new Object[0][]); + } + + @Test(dataProvider = "LongSpinedBuffer") + public void testLongSpliterator(long[] array, SpinedBuffer.OfLong sb) { + assertEquals(sb.count(), array.length); + assertEquals(sb.count(), sb.spliterator().getExactSizeIfKnown()); + + SpliteratorTestHelper.testLongSpliterator(sb::spliterator); + } + + @Test(dataProvider = "LongSpinedBuffer", groups = { "serialization-hostile" }) + public void testLongLastSplit(long[] array, SpinedBuffer.OfLong sb) { + Spliterator.OfLong spliterator = sb.spliterator(); + Spliterator.OfLong split = spliterator.trySplit(); + long splitSizes = (split == null) ? 0 : split.getExactSizeIfKnown(); + long lastSplitSize = spliterator.getExactSizeIfKnown(); + splitSizes += lastSplitSize; + + assertEquals(splitSizes, array.length); + + List contentOfLastSplit = new ArrayList<>(); + spliterator.forEachRemaining((LongConsumer) contentOfLastSplit::add); + + assertEquals(contentOfLastSplit.size(), lastSplitSize); + + List end = Arrays.stream(array) + .boxed() + .substream(array.length - lastSplitSize) + .collect(Collectors.toList()); + assertEquals(contentOfLastSplit, end); + } + + @Test(groups = { "serialization-hostile" }) + public void testLongSpinedBuffer() { + List list1 = new ArrayList<>(); + List list2 = new ArrayList<>(); + SpinedBuffer.OfLong sb = new SpinedBuffer.OfLong(); + for (long i = 0; i < TEST_SIZE; i++) { + list1.add(i); + sb.accept(i); + } + PrimitiveIterator.OfLong it = sb.iterator(); + for (int i = 0; i < TEST_SIZE; i++) + list2.add(it.nextLong()); + assertFalse(it.hasNext()); + assertEquals(list1, list2); + + for (int i = 0; i < TEST_SIZE; i++) + assertEquals(sb.get(i), i, Long.toString(i)); + + list2.clear(); + sb.forEach((long i) -> list2.add(i)); + assertEquals(list1, list2); + long[] array = sb.asLongArray(); + list2.clear(); + for (long i : array) + list2.add(i); + assertEquals(list1, list2); + } + + // DoubleSpinedBuffer + + @DataProvider(name = "DoubleSpinedBuffer") + public Object[][] createDoubleSpinedBuffer() { + List params = new ArrayList<>(); + + for (int size : sizes) { + // @@@ replace with double range when implemented + double[] array = LongStream.range(0, size).doubles().toArray(); + SpinedBuffer.OfDouble sb = new SpinedBuffer.OfDouble(); + Arrays.stream(array).forEach(sb); + + params.add(new Object[]{array, sb}); + } + + return params.toArray(new Object[0][]); + } + + @Test(dataProvider = "DoubleSpinedBuffer") + public void testDoubleSpliterator(double[] array, SpinedBuffer.OfDouble sb) { + assertEquals(sb.count(), array.length); + assertEquals(sb.count(), sb.spliterator().getExactSizeIfKnown()); + + SpliteratorTestHelper.testDoubleSpliterator(sb::spliterator); + } + + @Test(dataProvider = "DoubleSpinedBuffer", groups = { "serialization-hostile" }) + public void testLongLastSplit(double[] array, SpinedBuffer.OfDouble sb) { + Spliterator.OfDouble spliterator = sb.spliterator(); + Spliterator.OfDouble split = spliterator.trySplit(); + long splitSizes = (split == null) ? 0 : split.getExactSizeIfKnown(); + long lastSplitSize = spliterator.getExactSizeIfKnown(); + splitSizes += lastSplitSize; + + assertEquals(splitSizes, array.length); + + List contentOfLastSplit = new ArrayList<>(); + spliterator.forEachRemaining((DoubleConsumer) contentOfLastSplit::add); + + assertEquals(contentOfLastSplit.size(), lastSplitSize); + + List end = Arrays.stream(array) + .boxed() + .substream(array.length - lastSplitSize) + .collect(Collectors.toList()); + assertEquals(contentOfLastSplit, end); + } + + @Test(groups = { "serialization-hostile" }) + public void testDoubleSpinedBuffer() { + List list1 = new ArrayList<>(); + List list2 = new ArrayList<>(); + SpinedBuffer.OfDouble sb = new SpinedBuffer.OfDouble(); + for (long i = 0; i < TEST_SIZE; i++) { + list1.add((double) i); + sb.accept((double) i); + } + PrimitiveIterator.OfDouble it = sb.iterator(); + for (int i = 0; i < TEST_SIZE; i++) + list2.add(it.nextDouble()); + assertFalse(it.hasNext()); + assertEquals(list1, list2); + + for (int i = 0; i < TEST_SIZE; i++) + assertEquals(sb.get(i), (double) i, Double.toString(i)); + + list2.clear(); + sb.forEach((double i) -> list2.add(i)); + assertEquals(list1, list2); + double[] array = sb.asDoubleArray(); + list2.clear(); + for (double i : array) + list2.add(i); + assertEquals(list1, list2); + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/StreamFlagsTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/StreamFlagsTest.java new file mode 100644 index 00000000000..a5fa364e1e0 --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/StreamFlagsTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import org.testng.annotations.Test; + +import java.util.*; +import java.util.stream.Stream; +import java.util.stream.StreamOpFlag; +import java.util.stream.Streams; + +import static java.util.stream.StreamOpFlag.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * StreamFlagsTest + * + * @author Brian Goetz + */ +@Test +public class StreamFlagsTest { + Stream arrayList = new ArrayList().stream(); + Stream linkedList = new LinkedList().stream(); + Stream hashSet = new HashSet().stream(); + Stream treeSet = new TreeSet().stream(); + Stream linkedHashSet = new LinkedHashSet().stream(); + Stream repeat = Stream.generate(() -> ""); + + Stream[] streams = { arrayList, linkedList, hashSet, treeSet, linkedHashSet, repeat }; + + private void assertFlags(int value, EnumSet setFlags, EnumSet clearFlags) { + for (StreamOpFlag flag : setFlags) + assertTrue(flag.isKnown(value)); + for (StreamOpFlag flag : clearFlags) + assertTrue(!flag.isKnown(value)); + } + + public void testBaseStreams() { + Stream arrayList = new ArrayList().stream(); + Stream linkedList = new LinkedList().stream(); + Stream hashSet = new HashSet().stream(); + Stream treeSet = new TreeSet().stream(); + Stream linkedHashSet = new LinkedHashSet().stream(); + Stream repeat = Stream.generate(() -> ""); + + assertFlags(OpTestCase.getStreamFlags(arrayList), + EnumSet.of(ORDERED, SIZED), + EnumSet.of(DISTINCT, SORTED, SHORT_CIRCUIT)); + assertFlags(OpTestCase.getStreamFlags(linkedList), + EnumSet.of(ORDERED, SIZED), + EnumSet.of(DISTINCT, SORTED, SHORT_CIRCUIT)); + assertFlags(OpTestCase.getStreamFlags(hashSet), + EnumSet.of(SIZED, DISTINCT), + EnumSet.of(ORDERED, SORTED, SHORT_CIRCUIT)); + assertFlags(OpTestCase.getStreamFlags(treeSet), + EnumSet.of(ORDERED, SIZED, DISTINCT, SORTED), + EnumSet.of(SHORT_CIRCUIT)); + assertFlags(OpTestCase.getStreamFlags(linkedHashSet), + EnumSet.of(ORDERED, DISTINCT, SIZED), + EnumSet.of(SORTED, SHORT_CIRCUIT)); + assertFlags(OpTestCase.getStreamFlags(repeat), + EnumSet.of(ORDERED), + EnumSet.of(SIZED, DISTINCT, SORTED, SHORT_CIRCUIT)); + } + + public void testFilter() { + for (Stream s : streams) { + int baseFlags = OpTestCase.getStreamFlags(s); + int filteredFlags = OpTestCase.getStreamFlags(s.filter((Object e) -> true)); + int expectedFlags = baseFlags & ~SIZED.set(); + + assertEquals(filteredFlags, expectedFlags); + } + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/StreamOpFlagsTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/StreamOpFlagsTest.java new file mode 100644 index 00000000000..aa47aa2a103 --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/StreamOpFlagsTest.java @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.List; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.ToDoubleFunction; +import java.util.function.ToIntFunction; +import java.util.function.ToLongFunction; + +import static java.util.stream.Collectors.toList; +import static java.util.stream.StreamOpFlag.*; +import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; + +@Test +public class StreamOpFlagsTest { + + public void testNullCombine() { + int sourceFlags = StreamOpFlag.IS_SIZED; + + assertEquals(sourceFlags, toStreamFlags(combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE))); + } + + public void testInitialOpFlagsFromSourceFlags() { + List flags = new ArrayList<>(StreamOpFlagTestHelper.allStreamFlags()); + for (int i = 0; i < (1 << flags.size()); i++) { + int sourceFlags = 0; + for (int f = 0; f < flags.size(); f++) { + if ((i & (1 << f)) != 0) { + sourceFlags |= flags.get(f).set(); + } + } + + int opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE); + assertEquals(opsFlags, (~(sourceFlags << 1)) & StreamOpFlag.INITIAL_OPS_VALUE); + } + } + + public void testSameCombine() { + for (StreamOpFlag f : StreamOpFlagTestHelper.allStreamFlags()) { + int sourceFlags = f.set(); + int opsFlags; + + opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE); + opsFlags = combineOpFlags(f.set(), opsFlags); + assertEquals(sourceFlags, toStreamFlags(opsFlags)); + } + } + + public void testOpClear() { + for (StreamOpFlag f : StreamOpFlagTestHelper.allStreamFlags()) { + // Clear when source not set + int sourceFlags = 0; + int opsFlags; + + opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE); + opsFlags = combineOpFlags(f.clear(), opsFlags); + assertEquals(sourceFlags, toStreamFlags(opsFlags)); + + // Clear when source set + sourceFlags = f.set(); + + opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE); + opsFlags = combineOpFlags(f.clear(), opsFlags); + assertEquals(0, toStreamFlags(opsFlags)); + } + } + + public void testOpInject() { + for (StreamOpFlag f : StreamOpFlagTestHelper.allStreamFlags()) { + // Set when source not set + int sourceFlags = 0; + int opsFlags; + + opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE); + opsFlags = combineOpFlags(f.set(), opsFlags); + assertEquals(f.set(), toStreamFlags(opsFlags)); + + // Set when source set + sourceFlags = f.set(); + + opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE); + opsFlags = combineOpFlags(f.set(), opsFlags); + assertEquals(sourceFlags, toStreamFlags(opsFlags)); + } + } + + public void testPairSet() { + List sourceFlagsList + = StreamOpFlagTestHelper.allStreamFlags().stream().map(StreamOpFlag::set).collect(toList()); + sourceFlagsList.add(0, 0); + + for (int sourceFlags : sourceFlagsList) { + for (StreamOpFlag f1 : StreamOpFlagTestHelper.allStreamFlags()) { + for (StreamOpFlag f2 : StreamOpFlagTestHelper.allStreamFlags()) { + int opsFlags; + + opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE); + opsFlags = combineOpFlags(f1.set(), opsFlags); + opsFlags = combineOpFlags(f2.set(), opsFlags); + assertEquals(sourceFlags | f1.set() | f2.set(), toStreamFlags(opsFlags)); + } + } + } + } + + public void testPairSetAndClear() { + List sourceFlagsList + = StreamOpFlagTestHelper.allStreamFlags().stream().map(StreamOpFlag::set).collect(toList()); + sourceFlagsList.add(0, 0); + + for (int sourceFlags : sourceFlagsList) { + for (StreamOpFlag f1 : StreamOpFlagTestHelper.allStreamFlags()) { + for (StreamOpFlag f2 : StreamOpFlagTestHelper.allStreamFlags()) { + int opsFlags; + + opsFlags = combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE); + opsFlags = combineOpFlags(f1.set(), opsFlags); + opsFlags = combineOpFlags(f2.clear(), opsFlags); + if (f1 == f2) + assertEquals((f2.set() == sourceFlags) ? 0 : sourceFlags, toStreamFlags(opsFlags)); + else + assertEquals((f2.set() == sourceFlags) ? f1.set() : sourceFlags | f1.set(), toStreamFlags(opsFlags)); + } + } + } + } + + public void testShortCircuit() { + int opsFlags = combineOpFlags(0, StreamOpFlag.INITIAL_OPS_VALUE); + assertFalse(StreamOpFlag.SHORT_CIRCUIT.isKnown(opsFlags)); + + opsFlags = combineOpFlags(StreamOpFlag.IS_SHORT_CIRCUIT, opsFlags); + assertTrue(StreamOpFlag.SHORT_CIRCUIT.isKnown(opsFlags)); + + opsFlags = combineOpFlags(0, opsFlags); + assertTrue(StreamOpFlag.SHORT_CIRCUIT.isKnown(opsFlags)); + } + + public void testApplySourceFlags() { + int sourceFlags = StreamOpFlag.IS_SIZED | StreamOpFlag.IS_DISTINCT; + + List ops = Arrays.asList(StreamOpFlag.NOT_SIZED, StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SORTED); + + int opsFlags = StreamOpFlag.combineOpFlags(sourceFlags, StreamOpFlag.INITIAL_OPS_VALUE); + for (int opFlags : ops) { + opsFlags = combineOpFlags(opFlags, opsFlags); + } + assertFalse(StreamOpFlag.SIZED.isKnown(opsFlags)); + assertTrue(StreamOpFlag.SIZED.isCleared(opsFlags)); + assertFalse(StreamOpFlag.SIZED.isPreserved(opsFlags)); + assertTrue(StreamOpFlag.DISTINCT.isKnown(opsFlags)); + assertFalse(StreamOpFlag.DISTINCT.isCleared(opsFlags)); + assertFalse(StreamOpFlag.DISTINCT.isPreserved(opsFlags)); + assertTrue(StreamOpFlag.SORTED.isKnown(opsFlags)); + assertFalse(StreamOpFlag.SORTED.isCleared(opsFlags)); + assertFalse(StreamOpFlag.SORTED.isPreserved(opsFlags)); + assertTrue(StreamOpFlag.ORDERED.isKnown(opsFlags)); + assertFalse(StreamOpFlag.ORDERED.isCleared(opsFlags)); + assertFalse(StreamOpFlag.ORDERED.isPreserved(opsFlags)); + + int streamFlags = toStreamFlags(opsFlags); + assertFalse(StreamOpFlag.SIZED.isKnown(streamFlags)); + assertTrue(StreamOpFlag.DISTINCT.isKnown(streamFlags)); + assertTrue(StreamOpFlag.SORTED.isKnown(streamFlags)); + assertTrue(StreamOpFlag.ORDERED.isKnown(streamFlags)); + } + + public void testSpliteratorMask() { + assertSpliteratorMask(StreamOpFlag.DISTINCT.set(), StreamOpFlag.IS_DISTINCT); + assertSpliteratorMask(StreamOpFlag.DISTINCT.clear(), 0); + + assertSpliteratorMask(StreamOpFlag.SORTED.set(), StreamOpFlag.IS_SORTED); + assertSpliteratorMask(StreamOpFlag.SORTED.clear(), 0); + + assertSpliteratorMask(StreamOpFlag.ORDERED.set(), StreamOpFlag.IS_ORDERED); + assertSpliteratorMask(StreamOpFlag.ORDERED.clear(), 0); + + assertSpliteratorMask(StreamOpFlag.SIZED.set(), StreamOpFlag.IS_SIZED); + assertSpliteratorMask(StreamOpFlag.SIZED.clear(), 0); + + assertSpliteratorMask(StreamOpFlag.SHORT_CIRCUIT.set(), 0); + assertSpliteratorMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0); + } + + private void assertSpliteratorMask(int actual, int expected) { + assertEquals(actual & StreamOpFlag.SPLITERATOR_CHARACTERISTICS_MASK, expected); + } + + public void testStreamMask() { + assertStreamMask(StreamOpFlag.DISTINCT.set(), StreamOpFlag.IS_DISTINCT); + assertStreamMask(StreamOpFlag.DISTINCT.clear(), 0); + + assertStreamMask(StreamOpFlag.SORTED.set(), StreamOpFlag.IS_SORTED); + assertStreamMask(StreamOpFlag.SORTED.clear(), 0); + + assertStreamMask(StreamOpFlag.ORDERED.set(), StreamOpFlag.IS_ORDERED); + assertStreamMask(StreamOpFlag.ORDERED.clear(), 0); + + assertStreamMask(StreamOpFlag.SIZED.set(), StreamOpFlag.IS_SIZED); + assertStreamMask(StreamOpFlag.SIZED.clear(), 0); + + assertStreamMask(StreamOpFlag.SHORT_CIRCUIT.set(), 0); + assertStreamMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0); + } + + private void assertStreamMask(int actual, int expected) { + assertEquals(actual & StreamOpFlag.STREAM_MASK, expected); + } + + public void testOpMask() { + assertOpMask(StreamOpFlag.DISTINCT.set(), StreamOpFlag.IS_DISTINCT); + assertOpMask(StreamOpFlag.DISTINCT.clear(), StreamOpFlag.NOT_DISTINCT); + + assertOpMask(StreamOpFlag.SORTED.set(), StreamOpFlag.IS_SORTED); + assertOpMask(StreamOpFlag.SORTED.clear(), StreamOpFlag.NOT_SORTED); + + assertOpMask(StreamOpFlag.ORDERED.set(), StreamOpFlag.IS_ORDERED); + assertOpMask(StreamOpFlag.ORDERED.clear(), StreamOpFlag.NOT_ORDERED); + + assertOpMask(StreamOpFlag.SIZED.set(), 0); + assertOpMask(StreamOpFlag.SIZED.clear(), StreamOpFlag.NOT_SIZED); + + assertOpMask(StreamOpFlag.SHORT_CIRCUIT.set(), StreamOpFlag.IS_SHORT_CIRCUIT); + assertOpMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0); + } + + private void assertOpMask(int actual, int expected) { + assertEquals(actual & StreamOpFlag.OP_MASK, expected); + } + + public void testTerminalOpMask() { + assertTerminalOpMask(StreamOpFlag.DISTINCT.set(), 0); + assertTerminalOpMask(StreamOpFlag.DISTINCT.clear(), 0); + + assertTerminalOpMask(StreamOpFlag.SORTED.set(), 0); + assertTerminalOpMask(StreamOpFlag.SORTED.clear(), 0); + + assertTerminalOpMask(StreamOpFlag.ORDERED.set(), 0); + assertTerminalOpMask(StreamOpFlag.ORDERED.clear(), StreamOpFlag.NOT_ORDERED); + + assertTerminalOpMask(StreamOpFlag.SIZED.set(), 0); + assertTerminalOpMask(StreamOpFlag.SIZED.clear(), 0); + + assertTerminalOpMask(StreamOpFlag.SHORT_CIRCUIT.set(), StreamOpFlag.IS_SHORT_CIRCUIT); + assertTerminalOpMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0); + } + + private void assertTerminalOpMask(int actual, int expected) { + assertEquals(actual & StreamOpFlag.TERMINAL_OP_MASK, expected); + } + + public void testUpstreamTerminalOpMask() { + assertUpstreamTerminalOpMask(StreamOpFlag.DISTINCT.set(), 0); + assertUpstreamTerminalOpMask(StreamOpFlag.DISTINCT.clear(), 0); + + assertUpstreamTerminalOpMask(StreamOpFlag.SORTED.set(), 0); + assertUpstreamTerminalOpMask(StreamOpFlag.SORTED.clear(), 0); + + assertUpstreamTerminalOpMask(StreamOpFlag.ORDERED.set(), 0); + assertUpstreamTerminalOpMask(StreamOpFlag.ORDERED.clear(), StreamOpFlag.NOT_ORDERED); + + assertUpstreamTerminalOpMask(StreamOpFlag.SIZED.set(), 0); + assertUpstreamTerminalOpMask(StreamOpFlag.SIZED.clear(), 0); + + assertUpstreamTerminalOpMask(StreamOpFlag.SHORT_CIRCUIT.set(), 0); + assertUpstreamTerminalOpMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0); + } + + private void assertUpstreamTerminalOpMask(int actual, int expected) { + assertEquals(actual & StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK, expected); + } + + public void testSpliteratorCharacteristics() { + assertEquals(Spliterator.DISTINCT, StreamOpFlag.IS_DISTINCT); + assertEquals(Spliterator.SORTED, StreamOpFlag.IS_SORTED); + assertEquals(Spliterator.ORDERED, StreamOpFlag.IS_ORDERED); + assertEquals(Spliterator.SIZED, StreamOpFlag.IS_SIZED); + + List others = Arrays.asList(Spliterator.NONNULL, Spliterator.IMMUTABLE, + Spliterator.CONCURRENT, Spliterator.SUBSIZED); + for (int c : others) { + assertNotEquals(c, StreamOpFlag.IS_SHORT_CIRCUIT); + } + } + + public void testSpliteratorCharacteristicsMask() { + assertSpliteratorCharacteristicsMask(StreamOpFlag.DISTINCT.set(), StreamOpFlag.IS_DISTINCT); + assertSpliteratorCharacteristicsMask(StreamOpFlag.DISTINCT.clear(), 0); + + assertSpliteratorCharacteristicsMask(StreamOpFlag.SORTED.set(), StreamOpFlag.IS_SORTED); + assertSpliteratorCharacteristicsMask(StreamOpFlag.SORTED.clear(), 0); + + assertSpliteratorCharacteristicsMask(StreamOpFlag.ORDERED.set(), StreamOpFlag.IS_ORDERED); + assertSpliteratorCharacteristicsMask(StreamOpFlag.ORDERED.clear(), 0); + + assertSpliteratorCharacteristicsMask(StreamOpFlag.SIZED.set(), StreamOpFlag.IS_SIZED); + assertSpliteratorCharacteristicsMask(StreamOpFlag.SIZED.clear(), 0); + + assertSpliteratorCharacteristicsMask(StreamOpFlag.SHORT_CIRCUIT.set(), 0); + assertSpliteratorCharacteristicsMask(StreamOpFlag.SHORT_CIRCUIT.clear(), 0); + } + + private void assertSpliteratorCharacteristicsMask(int actual, int expected) { + assertEquals(StreamOpFlag.fromCharacteristics(actual), expected); + } + + public void testSpliteratorSorted() { + class SortedEmptySpliterator implements Spliterator { + final Comparator c; + + SortedEmptySpliterator(Comparator c) { + this.c = c; + } + + @Override + public Spliterator trySplit() { + return null; + } + + @Override + public boolean tryAdvance(Consumer action) { + return false; + } + + @Override + public long estimateSize() { + return Long.MAX_VALUE; + } + + @Override + public int characteristics() { + return Spliterator.SORTED; + } + + @Override + public Comparator getComparator() { + return c; + } + }; + + { + int flags = StreamOpFlag.fromCharacteristics(new SortedEmptySpliterator(null)); + assertEquals(flags, StreamOpFlag.IS_SORTED); + } + + { + int flags = StreamOpFlag.fromCharacteristics(new SortedEmptySpliterator((a, b) -> 0)); + assertEquals(flags, 0); + } + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/StreamReuseTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/StreamReuseTest.java new file mode 100644 index 00000000000..0ac9d68f43f --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/StreamReuseTest.java @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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 java.util.stream; + +import org.testng.annotations.Test; + +import java.util.function.Function; + +import static org.testng.Assert.fail; + +/** + * StreamReuseTest + * + * @author Brian Goetz + */ +@Test +public class StreamReuseTest { + + private , D extends TestData> void assertSecondFails( + D data, + Function first, + Function second, + Class exception, + String text) { + S stream = data.stream(); + T fr = first.apply(stream); + try { + U sr = second.apply(stream); + fail(text + " (seq)"); + } + catch (Throwable e) { + if (exception.isAssignableFrom(e.getClass())) { + // Expected + } + else if (e instanceof Error) + throw (Error) e; + else if (e instanceof RuntimeException) + throw (RuntimeException) e; + else + throw new AssertionError("Unexpected exception " + e.getClass(), e); + } + + stream = data.parallelStream(); + fr = first.apply(stream); + try { + U sr = second.apply(stream); + fail(text + " (par)"); + } + catch (Throwable e) { + if (exception.isAssignableFrom(e.getClass())) { + // Expected + } + else if (e instanceof Error) + throw (Error) e; + else if (e instanceof RuntimeException) + throw (RuntimeException) e; + else + throw new AssertionError("Unexpected exception " + e.getClass(), e); + } + } + + // Stream + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testTwoStreams(String name, TestData> data) { + assertSecondFails(data, + (Stream s) -> s.map(i -> i), (Stream s) -> s.map(i -> i), + IllegalStateException.class, + "Stream map / map succeeded erroneously"); + assertSecondFails(data, + Stream::distinct, (Stream s) -> s.map(i -> i), + IllegalStateException.class, + "Stream distinct / map succeeded erroneously"); + assertSecondFails(data, + (Stream s) -> s.map(i -> i), Stream::distinct, + IllegalStateException.class, + "Stream map / distinct succeeded erroneously"); + assertSecondFails(data, + Stream::distinct, Stream::distinct, + IllegalStateException.class, + "Stream distinct / distinct succeeded erroneously"); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testTwoTerminals(String name, TestData> data) { + assertSecondFails(data, + Stream::findFirst, Stream::findFirst, + IllegalStateException.class, + "Stream findFirst / findFirst succeeded erroneously"); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testTerminalStream(String name, TestData> data) { + assertSecondFails(data, + Stream::findFirst, (Stream s) -> s.map(i -> i), + IllegalStateException.class, + "Stream findFirst / map succeeded erroneously"); + assertSecondFails(data, + (Stream s) -> s.map(i -> i), Stream::findFirst, + IllegalStateException.class, + "Stream map / findFirst succeeded erroneously"); + assertSecondFails(data, + Stream::findFirst, Stream::distinct, + IllegalStateException.class, + "Stream findFirst / distinct succeeded erroneously"); + assertSecondFails(data, + Stream::distinct, Stream::findFirst, + IllegalStateException.class, + "Stream distinct / findFirst succeeded erroneously"); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testTwoIterators(String name, TestData> data) { + assertSecondFails(data, + Stream::iterator, Stream::iterator, + IllegalStateException.class, + "Stream iterator / iterator succeeded erroneously"); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testTerminalIterator(String name, TestData> data) { + assertSecondFails(data, + Stream::iterator, Stream::findFirst, + IllegalStateException.class, + "Stream iterator / findFirst succeeded erroneously"); + assertSecondFails(data, + Stream::findFirst, Stream::iterator, + IllegalStateException.class, + "Stream findFirst / iterator succeeded erroneously"); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testStreamIterator(String name, TestData> data) { + assertSecondFails(data, + Stream::iterator, (Stream s) -> s.map(i -> i), + IllegalStateException.class, + "Stream iterator / map succeeded erroneously"); + assertSecondFails(data, + (Stream s) -> s.map(i -> i), Stream::iterator, + IllegalStateException.class, + "Stream map / iterator succeeded erroneously"); + assertSecondFails(data, + Stream::iterator, Stream::distinct, + IllegalStateException.class, + "Stream iterator / distinct succeeded erroneously"); + assertSecondFails(data, + Stream::distinct, Stream::iterator, + IllegalStateException.class, + "Stream distinct / iterator succeeded erroneously"); + } + + // IntStream + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testTwoStreams(String name, TestData.OfInt data) { + assertSecondFails(data, + (IntStream s) -> s.mapToObj(i -> i), (IntStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "IntStream map / map succeeded erroneously"); + assertSecondFails(data, + IntStream::distinct, (IntStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "IntStream distinct / map succeeded erroneously"); + assertSecondFails(data, + (IntStream s) -> s.mapToObj(i -> i), IntStream::distinct, + IllegalStateException.class, + "IntStream map / distinct succeeded erroneously"); + assertSecondFails(data, + IntStream::distinct, IntStream::distinct, + IllegalStateException.class, + "IntStream distinct / distinct succeeded erroneously"); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testTwoTerminals(String name, TestData.OfInt data) { + assertSecondFails(data, + IntStream::sum, IntStream::sum, + IllegalStateException.class, + "IntStream sum / sum succeeded erroneously"); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testTerminalStream(String name, TestData.OfInt data) { + assertSecondFails(data, + IntStream::sum, (IntStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "IntStream sum / map succeeded erroneously"); + assertSecondFails(data, + (IntStream s) -> s.mapToObj(i -> i), IntStream::sum, + IllegalStateException.class, + "IntStream map / sum succeeded erroneously"); + assertSecondFails(data, + IntStream::sum, IntStream::distinct, + IllegalStateException.class, + "IntStream sum / distinct succeeded erroneously"); + assertSecondFails(data, + IntStream::distinct, IntStream::sum, + IllegalStateException.class, + "IntStream distinct / sum succeeded erroneously"); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testTwoIterators(String name, TestData.OfInt data) { + assertSecondFails(data, + IntStream::iterator, IntStream::iterator, + IllegalStateException.class, + "IntStream iterator / iterator succeeded erroneously"); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testTerminalIterator(String name, TestData.OfInt data) { + assertSecondFails(data, + IntStream::iterator, IntStream::sum, + IllegalStateException.class, + "IntStream iterator / sum succeeded erroneously"); + assertSecondFails(data, + IntStream::sum, IntStream::iterator, + IllegalStateException.class, + "Stream sum / iterator succeeded erroneously"); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testStreamIterator(String name, TestData.OfInt data) { + assertSecondFails(data, + IntStream::iterator, (IntStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "IntStream iterator / map succeeded erroneously"); + assertSecondFails(data, + (IntStream s) -> s.mapToObj(i -> i), IntStream::iterator, + IllegalStateException.class, + "IntStream map / iterator succeeded erroneously"); + assertSecondFails(data, + IntStream::iterator, IntStream::distinct, + IllegalStateException.class, + "IntStream iterator / distinct succeeded erroneously"); + assertSecondFails(data, + IntStream::distinct, IntStream::iterator, + IllegalStateException.class, + "IntStream distinct / iterator succeeded erroneously"); + } + + // LongStream + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testTwoStreams(String name, TestData.OfLong data) { + assertSecondFails(data, + (LongStream s) -> s.mapToObj(i -> i), (LongStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "LongStream map / map succeeded erroneously"); + assertSecondFails(data, + LongStream::distinct, (LongStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "LongStream distinct / map succeeded erroneously"); + assertSecondFails(data, + (LongStream s) -> s.mapToObj(i -> i), LongStream::distinct, + IllegalStateException.class, + "LongStream map / distinct succeeded erroneously"); + assertSecondFails(data, + LongStream::distinct, LongStream::distinct, + IllegalStateException.class, + "LongStream distinct / distinct succeeded erroneously"); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testTwoTerminals(String name, TestData.OfLong data) { + assertSecondFails(data, + LongStream::sum, LongStream::sum, + IllegalStateException.class, + "LongStream sum / sum succeeded erroneously"); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testTerminalStream(String name, TestData.OfLong data) { + assertSecondFails(data, + LongStream::sum, (LongStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "LongStream sum / map succeeded erroneously"); + assertSecondFails(data, + (LongStream s) -> s.mapToObj(i -> i), LongStream::sum, + IllegalStateException.class, + "LongStream map / sum succeeded erroneously"); + assertSecondFails(data, + LongStream::sum, LongStream::distinct, + IllegalStateException.class, + "LongStream sum / distinct succeeded erroneously"); + assertSecondFails(data, + LongStream::distinct, LongStream::sum, + IllegalStateException.class, + "LongStream distinct / sum succeeded erroneously"); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testTwoIterators(String name, TestData.OfLong data) { + assertSecondFails(data, + LongStream::iterator, LongStream::iterator, + IllegalStateException.class, + "LongStream iterator / iterator succeeded erroneously"); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testTerminalIterator(String name, TestData.OfLong data) { + assertSecondFails(data, + LongStream::iterator, LongStream::sum, + IllegalStateException.class, + "LongStream iterator / sum succeeded erroneously"); + assertSecondFails(data, + LongStream::sum, LongStream::iterator, + IllegalStateException.class, + "Stream sum / iterator succeeded erroneously"); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testStreamIterator(String name, TestData.OfLong data) { + assertSecondFails(data, + LongStream::iterator, (LongStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "LongStream iterator / map succeeded erroneously"); + assertSecondFails(data, + (LongStream s) -> s.mapToObj(i -> i), LongStream::iterator, + IllegalStateException.class, + "LongStream map / iterator succeeded erroneously"); + assertSecondFails(data, + LongStream::iterator, LongStream::distinct, + IllegalStateException.class, + "LongStream iterator / distinct succeeded erroneously"); + assertSecondFails(data, + LongStream::distinct, LongStream::iterator, + IllegalStateException.class, + "LongStream distinct / iterator succeeded erroneously"); + } + + // DoubleStream + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testTwoStreams(String name, TestData.OfDouble data) { + assertSecondFails(data, + (DoubleStream s) -> s.mapToObj(i -> i), (DoubleStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "DoubleStream map / map succeeded erroneously"); + assertSecondFails(data, + DoubleStream::distinct, (DoubleStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "DoubleStream distinct / map succeeded erroneously"); + assertSecondFails(data, + (DoubleStream s) -> s.mapToObj(i -> i), DoubleStream::distinct, + IllegalStateException.class, + "DoubleStream map / distinct succeeded erroneously"); + assertSecondFails(data, + DoubleStream::distinct, DoubleStream::distinct, + IllegalStateException.class, + "DoubleStream distinct / distinct succeeded erroneously"); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testTwoTerminals(String name, TestData.OfDouble data) { + assertSecondFails(data, + DoubleStream::sum, DoubleStream::sum, + IllegalStateException.class, + "DoubleStream sum / sum succeeded erroneously"); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testTerminalStream(String name, TestData.OfDouble data) { + assertSecondFails(data, + DoubleStream::sum, (DoubleStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "DoubleStream sum / map succeeded erroneously"); + assertSecondFails(data, + (DoubleStream s) -> s.mapToObj(i -> i), DoubleStream::sum, + IllegalStateException.class, + "DoubleStream map / sum succeeded erroneously"); + assertSecondFails(data, + DoubleStream::sum, DoubleStream::distinct, + IllegalStateException.class, + "DoubleStream sum / distinct succeeded erroneously"); + assertSecondFails(data, + DoubleStream::distinct, DoubleStream::sum, + IllegalStateException.class, + "DoubleStream distinct / sum succeeded erroneously"); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testTwoIterators(String name, TestData.OfDouble data) { + assertSecondFails(data, + DoubleStream::iterator, DoubleStream::iterator, + IllegalStateException.class, + "DoubleStream iterator / iterator succeeded erroneously"); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testTerminalIterator(String name, TestData.OfDouble data) { + assertSecondFails(data, + DoubleStream::iterator, DoubleStream::sum, + IllegalStateException.class, + "DoubleStream iterator / sum succeeded erroneously"); + assertSecondFails(data, + DoubleStream::sum, DoubleStream::iterator, + IllegalStateException.class, + "Stream sum / iterator succeeded erroneously"); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testStreamIterator(String name, TestData.OfDouble data) { + assertSecondFails(data, + DoubleStream::iterator, (DoubleStream s) -> s.mapToObj(i -> i), + IllegalStateException.class, + "DoubleStream iterator / map succeeded erroneously"); + assertSecondFails(data, + (DoubleStream s) -> s.mapToObj(i -> i), DoubleStream::iterator, + IllegalStateException.class, + "DoubleStream map / iterator succeeded erroneously"); + assertSecondFails(data, + DoubleStream::iterator, DoubleStream::distinct, + IllegalStateException.class, + "DoubleStream iterator / distinct succeeded erroneously"); + assertSecondFails(data, + DoubleStream::distinct, DoubleStream::iterator, + IllegalStateException.class, + "DoubleStream distinct / iterator succeeded erroneously"); + } +} diff --git a/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java b/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java new file mode 100644 index 00000000000..48b4e7576e1 --- /dev/null +++ b/jdk/test/java/util/stream/boottest/java/util/stream/UnorderedTest.java @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2013, 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. + * + * 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 java.util.stream; + +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.UnaryOperator; + +@Test +public class UnorderedTest extends OpTestCase { + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testTerminalOps(String name, TestData> data) { + testTerminal(data, s -> { s.forEach(x -> { }); return 0; }); + + testTerminal(data, s -> s.findAny(), (a, b) -> assertEquals(a.isPresent(), b.isPresent())); + + testTerminal(data, s -> s.anyMatch(e -> true)); + } + + + private void testTerminal(TestData> data, Function, R> terminalF) { + testTerminal(data, terminalF, LambdaTestHelpers::assertContentsEqual); + } + + static class WrappingUnaryOperator implements UnaryOperator { + + final boolean isLimit; + final UnaryOperator uo; + + WrappingUnaryOperator(UnaryOperator uo) { + this(uo, false); + } + + WrappingUnaryOperator(UnaryOperator uo, boolean isLimit) { + this.uo = uo; + this.isLimit = isLimit; + } + + @Override + public S apply(S s) { + return uo.apply(s); + } + } + + static WrappingUnaryOperator wrap(UnaryOperator uo) { + return new WrappingUnaryOperator<>(uo); + } + + static WrappingUnaryOperator wrap(UnaryOperator uo, boolean isLimit) { + return new WrappingUnaryOperator<>(uo, isLimit); + } + + @SuppressWarnings("rawtypes") + private List permutationOfFunctions = + LambdaTestHelpers.perm(Arrays.>>asList( + wrap(s -> s.sorted()), + wrap(s -> s.distinct()), + wrap(s -> s.limit(5), true) + )); + + @SuppressWarnings("unchecked") + private void testTerminal(TestData> data, + Function, R> terminalF, + BiConsumer equalityAsserter) { + testTerminal(data, terminalF, equalityAsserter, permutationOfFunctions, StreamShape.REFERENCE); + } + + // + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntTerminalOps(String name, TestData.OfInt data) { + testIntTerminal(data, s -> { s.forEach(x -> { }); return 0; }); + testIntTerminal(data, s -> s.findAny(), (a, b) -> assertEquals(a.isPresent(), b.isPresent())); + testIntTerminal(data, s -> s.anyMatch(e -> true)); + } + + + private void testIntTerminal(TestData.OfInt data, Function terminalF) { + testIntTerminal(data, terminalF, LambdaTestHelpers::assertContentsEqual); + } + + private List>> intPermutationOfFunctions = + LambdaTestHelpers.perm(Arrays.asList( + wrap(s -> s.sorted()), + wrap(s -> s.distinct()), + wrap(s -> s.limit(5), true) + )); + + private void testIntTerminal(TestData.OfInt data, + Function terminalF, + BiConsumer equalityAsserter) { + testTerminal(data, terminalF, equalityAsserter, intPermutationOfFunctions, StreamShape.INT_VALUE); + } + + // + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongTerminalOps(String name, TestData.OfLong data) { + testLongTerminal(data, s -> { s.forEach(x -> { }); return 0; }); + testLongTerminal(data, s -> s.findAny(), (a, b) -> assertEquals(a.isPresent(), b.isPresent())); + testLongTerminal(data, s -> s.anyMatch(e -> true)); + } + + + private void testLongTerminal(TestData.OfLong data, Function terminalF) { + testLongTerminal(data, terminalF, LambdaTestHelpers::assertContentsEqual); + } + + private List>> longPermutationOfFunctions = + LambdaTestHelpers.perm(Arrays.asList( + wrap(s -> s.sorted()), + wrap(s -> s.distinct()), + wrap(s -> s.limit(5), true) + )); + + private void testLongTerminal(TestData.OfLong data, + Function terminalF, + BiConsumer equalityAsserter) { + testTerminal(data, terminalF, equalityAsserter, longPermutationOfFunctions, StreamShape.LONG_VALUE); + } + + // + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleTerminalOps(String name, TestData.OfDouble data) { + testDoubleTerminal(data, s -> { s.forEach(x -> { }); return 0; }); + testDoubleTerminal(data, s -> s.findAny(), (a, b) -> assertEquals(a.isPresent(), b.isPresent())); + testDoubleTerminal(data, s -> s.anyMatch(e -> true)); + } + + + private void testDoubleTerminal(TestData.OfDouble data, Function terminalF) { + testDoubleTerminal(data, terminalF, LambdaTestHelpers::assertContentsEqual); + } + + private List>> doublePermutationOfFunctions = + LambdaTestHelpers.perm(Arrays.asList( + wrap(s -> s.sorted()), + wrap(s -> s.distinct()), + wrap(s -> s.limit(5), true) + )); + + private void testDoubleTerminal(TestData.OfDouble data, + Function terminalF, + BiConsumer equalityAsserter) { + testTerminal(data, terminalF, equalityAsserter, doublePermutationOfFunctions, StreamShape.DOUBLE_VALUE); + } + + // + + private , R> void testTerminal(TestData data, + Function terminalF, + BiConsumer equalityAsserter, + List>> pFunctions, + StreamShape shape) { + CheckClearOrderedOp checkClearOrderedOp = new CheckClearOrderedOp<>(shape); + for (List> f : pFunctions) { + @SuppressWarnings("unchecked") + UnaryOperator fi = interpose(f, (S s) -> (S) chain(s, checkClearOrderedOp)); + withData(data). + terminal(fi, terminalF). + without(TerminalTestScenario.ALL_PARALLEL_SEQUENTIAL). + equalator(equalityAsserter). + exercise(); + } + + CheckSetOrderedOp checkSetOrderedOp = new CheckSetOrderedOp<>(shape); + for (List> f : pFunctions) { + @SuppressWarnings("unchecked") + UnaryOperator fi = interpose(f, (S s) -> (S) chain(s, checkSetOrderedOp)); + withData(data). + terminal(fi, s -> terminalF.apply(s.sequential())). + without(TerminalTestScenario.ALL_PARALLEL_SEQUENTIAL). + equalator(equalityAsserter). + exercise(); + } + } + + static class CheckClearOrderedOp implements StatelessTestOp { + private final StreamShape shape; + + CheckClearOrderedOp(StreamShape shape) { + this.shape = shape; + } + + @Override + public StreamShape outputShape() { + return shape; + } + + @Override + public StreamShape inputShape() { + return shape; + } + + @Override + public Sink opWrapSink(int flags, boolean parallel, Sink sink) { + if (parallel) { + assertTrue(StreamOpFlag.ORDERED.isCleared(flags)); + } + + return sink; + } + } + + static class CheckSetOrderedOp extends CheckClearOrderedOp { + + CheckSetOrderedOp(StreamShape shape) { + super(shape); + } + + @Override + public Sink opWrapSink(int flags, boolean parallel, Sink sink) { + assertTrue(StreamOpFlag.ORDERED.isKnown(flags) || StreamOpFlag.ORDERED.isPreserved(flags)); + + return sink; + } + } + + private > + UnaryOperator interpose(List> fs, UnaryOperator fi) { + int l = -1; + for (int i = 0; i < fs.size(); i++) { + if (fs.get(i).isLimit) { + l = i; + } + } + + final int lastLimitIndex = l; + return s -> { + if (lastLimitIndex == -1) + s = fi.apply(s); + for (int i = 0; i < fs.size(); i++) { + s = fs.get(i).apply(s); + if (i >= lastLimitIndex) { + s = fi.apply(s); + } + } + return s; + }; + } +} diff --git a/jdk/test/java/util/stream/test/TEST.properties b/jdk/test/java/util/stream/test/TEST.properties new file mode 100644 index 00000000000..4128f6afd75 --- /dev/null +++ b/jdk/test/java/util/stream/test/TEST.properties @@ -0,0 +1,8 @@ +# This file identifies root(s) of the test-ng hierarchy. + +TestNG.dirs = . + +lib.dirs = /java/util/stream/bootlib + +# Tests that must run in othervm mode +othervm.dirs= /java/util/stream diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/DeserializeMethodTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/DeserializeMethodTest.java new file mode 100644 index 00000000000..67dc982185f --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/DeserializeMethodTest.java @@ -0,0 +1,87 @@ +/* + * 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. + * + * 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.lang.invoke; + +import org.testng.annotations.Test; + +import java.io.Serializable; +import java.lang.invoke.SerializedLambda; +import java.lang.reflect.Method; + +import static org.testng.Assert.fail; + +/** + * Ensure that the $deserializeLambda$ method is present when it should be, and absent otherwise + */ + +@Test(groups = { "serialization-hostile" }) +public class DeserializeMethodTest { + private void assertDeserializeMethod(Class clazz, boolean expectedPresent) { + try { + Method m = clazz.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class); + if (!expectedPresent) + fail("Unexpected $deserializeLambda$ in " + clazz); + } + catch (NoSuchMethodException e) { + if (expectedPresent) + fail("Expected to find $deserializeLambda$ in " + clazz); + } + } + + static class Empty {} + + public void testEmptyClass() { + assertDeserializeMethod(Empty.class, false); + } + + static class Cap1 { + void foo() { + Runnable r = (Runnable & Serializable) () -> { }; + } + } + + public void testCapturingSerLambda() { + assertDeserializeMethod(Cap1.class, true); + } + + static class Cap2 { + void foo() { + Runnable r = () -> { }; + } + } + + public void testCapturingNonSerLambda() { + assertDeserializeMethod(Cap2.class, false); + } + + interface Marker { } + static class Cap3 { + void foo() { + Runnable r = (Runnable & Marker) () -> { }; + } + } + + public void testCapturingNonserIntersectionLambda() { + assertDeserializeMethod(Cap3.class, false); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/MHProxiesTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/MHProxiesTest.java new file mode 100644 index 00000000000..9d9829df546 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/MHProxiesTest.java @@ -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. + * + * 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.lang.invoke; + +import org.testng.annotations.Test; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandleProxies; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +import static org.testng.Assert.assertEquals; + +/** + * MHProxiesTest -- regression test for MH library bug + */ +@Test +public class MHProxiesTest { + public interface Sam { double m(int arg); } + + public static Byte m(int arg) { return (byte) arg; } + + public void testProxy() throws NoSuchMethodException, IllegalAccessException { + MethodHandle m = MethodHandles.lookup().findStatic(MHProxiesTest.class, "m", + MethodType.methodType(Byte.class, int.class)); + Sam s = MethodHandleProxies.asInterfaceInstance(Sam.class, m); + assertEquals(66d, s.m(66)); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java new file mode 100644 index 00000000000..5423ac465d2 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java @@ -0,0 +1,280 @@ +/* + * 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. + * + * 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.lang.invoke; + +import org.testng.annotations.Test; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.LongConsumer; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +/** + * SerializedLambdaTest + * + * @author Brian Goetz + */ +@Test +public class SerializedLambdaTest { + @SuppressWarnings("unchecked") + private void assertSerial(T p, Consumer asserter) throws IOException, ClassNotFoundException { + asserter.accept(p); + + byte[] bytes = serialize(p); + assertTrue(bytes.length > 0); + + asserter.accept((T) deserialize(bytes)); + } + + private void assertNotSerial(Predicate p, Consumer> asserter) + throws IOException, ClassNotFoundException { + asserter.accept(p); + try { + byte[] bytes = serialize(p); + fail("Expected serialization failure"); + } + catch (NotSerializableException e) { + // success + } + } + + private byte[] serialize(Object o) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(o); + oos.close(); + return bos.toByteArray(); + } + + private Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException { + try(ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))) { + return ois.readObject(); + } + } + + // Test instantiating against intersection type + public void testSimpleSerializedInstantiation() throws IOException, ClassNotFoundException { + @SuppressWarnings("unchecked") + Predicate pred = (Predicate & Serializable) s -> true; + assertSerial(pred, + p -> { + assertTrue(p instanceof Predicate); + assertTrue(p instanceof Serializable); + assertTrue(p.test("")); + }); + } + + interface SerPredicate extends Predicate, Serializable { } + + // Test instantiating against derived type + public void testSimpleSerializedInstantiation2() throws IOException, ClassNotFoundException { + SerPredicate serPred = (SerPredicate) s -> true; + assertSerial(serPred, + p -> { + assertTrue(p instanceof Predicate); + assertTrue(p instanceof Serializable); + assertTrue(p instanceof SerPredicate); + assertTrue(p.test("")); + }); + } + + // Negative test: non-serializable lambdas are in fact not serializable + public void testNonserializableInstantiation() throws IOException, ClassNotFoundException { + @SuppressWarnings("unchecked") + Predicate pred = (Predicate) s -> true; + assertNotSerial(pred, + p -> { + assertTrue(p instanceof Predicate); + assertFalse(p instanceof Serializable); + assertTrue(p.test("")); + }); + } + + // Test lambda capturing int + public void testSerializeCapturingInt() throws IOException, ClassNotFoundException { + class Moo { + @SuppressWarnings("unchecked") + Predicate foo(int x) { + return (Predicate & Serializable) s -> s.length() >= x; + } + } + Predicate pred = new Moo().foo(3); + assertSerial(pred, p -> { + assertTrue(p.test("yada")); + assertFalse(p.test("no")); + }); + } + + // Test lambda capturing String + public void testSerializeCapturingString() throws IOException, ClassNotFoundException { + class Moo { + @SuppressWarnings("unchecked") + Predicate foo(String t) { + return (Predicate & Serializable) s -> s.equals(t); + } + } + Predicate pred = new Moo().foo("goo"); + assertSerial(pred, p -> { + assertTrue(p.test("goo")); + assertFalse(p.test("foo")); + }); + } + + // Negative test: lambdas that capture a non-serializable var + public void testSerializeCapturingNonSerializable() throws IOException, ClassNotFoundException { + class Box { + String s; + + Box(String s) { this.s = s; } + } + class Moo { + @SuppressWarnings("unchecked") + Predicate foo(Box b) { + return (Predicate & Serializable) s -> s.equals(b.s); + } + } + Predicate pred = new Moo().foo(new Box("goo")); + assertNotSerial(pred, p -> { + assertTrue(p.test("goo")); + assertFalse(p.test("foo")); + }); + } + + static boolean startsWithA(String s) { + return s.startsWith("a"); + } + + // Test static method ref + public void testStaticMR() throws IOException, ClassNotFoundException { + @SuppressWarnings("unchecked") + Predicate mh1 = (Predicate & Serializable) SerializedLambdaTest::startsWithA; + @SuppressWarnings("unchecked") + Predicate mh2 = (SerPredicate) SerializedLambdaTest::startsWithA; + Consumer> b = p -> { + assertTrue(p instanceof Serializable); + assertTrue(p.test("arf")); + assertFalse(p.test("barf")); + }; + assertSerial(mh1, b); + assertSerial(mh2, b); + } + + // Test unbound method ref of nonserializable class -- should still succeed + public void testUnboundMR() throws IOException, ClassNotFoundException { + class Moo { + public boolean startsWithB(String s) { + return s.startsWith("b"); + } + } + @SuppressWarnings("unchecked") + BiPredicate mh1 = (BiPredicate & Serializable) Moo::startsWithB; + Consumer> b = p -> { + assertTrue(p instanceof Serializable); + assertTrue(p.test(new Moo(), "barf")); + assertFalse(p.test(new Moo(), "arf")); + }; + assertSerial(mh1, b); + } + + // Negative test: test bound MR of nonserializable class + public void testBoundMRNotSerReceiver() throws IOException, ClassNotFoundException { + class Moo { + public boolean startsWithB(String s) { + return s.startsWith("b"); + } + } + Moo moo = new Moo(); + @SuppressWarnings("unchecked") + Predicate mh1 = (Predicate & Serializable) moo::startsWithB; + @SuppressWarnings("unchecked") + Predicate mh2 = (SerPredicate) moo::startsWithB; + Consumer> b = p -> { + assertTrue(p instanceof Serializable); + assertTrue(p.test("barf")); + assertFalse(p.test("arf")); + }; + assertNotSerial(mh1, b); + assertNotSerial(mh2, b); + } + + // Test bound MR of serializable class + @SuppressWarnings("serial") + static class ForBoundMRef implements Serializable { + public boolean startsWithB(String s) { + return s.startsWith("b"); + } + } + + public void testBoundMR() throws IOException, ClassNotFoundException { + ForBoundMRef moo = new ForBoundMRef(); + @SuppressWarnings("unchecked") + Predicate mh1 = (Predicate & Serializable) moo::startsWithB; + @SuppressWarnings("unchecked") + Predicate mh2 = (SerPredicate) moo::startsWithB; + Consumer> b = p -> { + assertTrue(p instanceof Serializable); + assertTrue(p.test("barf")); + assertFalse(p.test("arf")); + }; + assertSerial(mh1, b); + assertSerial(mh2, b); + } + + static class ForCtorRef { + public boolean startsWithB(String s) { + return s.startsWith("b"); + } + } + // Test ctor ref of nonserializable class + public void testCtorRef() throws IOException, ClassNotFoundException { + @SuppressWarnings("unchecked") + Supplier ctor = (Supplier & Serializable) ForCtorRef::new; + Consumer> b = s -> { + assertTrue(s instanceof Serializable); + ForCtorRef m = s.get(); + assertTrue(m.startsWithB("barf")); + assertFalse(m.startsWithB("arf")); + }; + assertSerial(ctor, b); + } + + //Test throwing away return type + public void testDiscardReturnBound() throws IOException, ClassNotFoundException { + List list = new ArrayList<>(); + Consumer c = (Consumer & Serializable) list::add; + assertSerial(c, cc -> { assertTrue(cc instanceof Consumer); }); + + AtomicLong a = new AtomicLong(); + LongConsumer lc = (LongConsumer & Serializable) a::addAndGet; + assertSerial(lc, plc -> { plc.accept(3); }); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/FillableStringTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/FillableStringTest.java new file mode 100644 index 00000000000..5c8a65a50f3 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/FillableStringTest.java @@ -0,0 +1,56 @@ +/* + * 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. + * + * 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; + +import java.util.Arrays; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +@Test(groups = "lib") +public class FillableStringTest { + public Stream generate() { + return Arrays.asList("one", "two", "three", "four", "five", "six").stream() + .filter(s->s.length() > 3) + .map(String::toUpperCase); + } + + public void testStringBuilder() { + String s = generate().collect(Collectors.toStringBuilder()).toString(); + assertEquals(s, "THREEFOURFIVE"); + } + + public void testStringBuffer() { + String s = generate().collect(Collectors.toStringBuilder()).toString(); + assertEquals(s, "THREEFOURFIVE"); + } + + public void testStringJoiner() { + String s = generate().collect(Collectors.toStringJoiner("-")).toString(); + assertEquals(s, "THREE-FOUR-FIVE"); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/MapTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/MapTest.java new file mode 100644 index 00000000000..53c7ab1c7dc --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/MapTest.java @@ -0,0 +1,93 @@ +/* + * 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. + * + * 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; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.LambdaTestHelpers; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * Unit tests for extension methods on Map + */ +public class MapTest { + + private static final Map EXPECTED = new HashMap<>(); + + private Map map; + + @BeforeClass + public void setUpClass() { + EXPECTED.put(0, "zero"); + EXPECTED.put(1, "one"); + EXPECTED.put(2, "two"); + EXPECTED.put(3, "three"); + EXPECTED.put(4, "four"); + EXPECTED.put(5, "five"); + EXPECTED.put(6, "six"); + EXPECTED.put(7, "seven"); + EXPECTED.put(8, "eight"); + EXPECTED.put(9, "nine"); + } + + @AfterClass + public void tearDownClass() { + EXPECTED.clear(); + } + + @BeforeMethod + public void setUp() { + map = new HashMap<>(EXPECTED); + } + + @AfterMethod + public void tearDown() { + map.clear(); + map = null; + } + + @Test(groups = { "serialization-hostile" }) + public void testForEach() { + final Set values = new HashSet<>(EXPECTED.size()); + map.forEach((k, v) -> {values.add(v);}); + LambdaTestHelpers.assertContentsUnordered(values, EXPECTED.values()); + } + + @Test + public void testReplaceAll() { + map.replaceAll((k, v) -> {return v.toUpperCase();}); + for (final Map.Entry entry : map.entrySet()) { + assertEquals(entry.getValue(), EXPECTED.get(entry.getKey()).toUpperCase()); + } + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/NullArgsTestCase.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/NullArgsTestCase.java new file mode 100644 index 00000000000..eaad7685702 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/NullArgsTestCase.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1997, 2010, 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. + * + * 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; + +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.function.Consumer; + +import static org.testng.Assert.fail; + +/** + * NullArgsTestCase -- Given a Consumer<Object[]>, and an Object[] array of args, call the block with the args, + * assert success, and then call the consumer N times, each time setting one of the args to null, and assert that + * all these throw NPE. + * + * Typically this would be combined with a DataProvider that serves up combinations of things to be tested, as in + * IteratorsNullTest. + */ +public abstract class NullArgsTestCase { + public final String name; + public final Consumer sink; + public final Object[] args; + + protected NullArgsTestCase(String name, Consumer sink, Object[] args) { + this.name = name; + this.sink = sink; + this.args = args; + } + + @Test + public void goodNonNull() { + sink.accept(args); + } + + @Test + public void throwWithNull() { + for (int i=0; i content = LambdaTestHelpers.countTo(10); + + List> collections = new ArrayList<>(); + collections.add(new ArrayList<>(content)); + collections.add(new LinkedList<>(content)); + collections.add(new Vector<>(content)); + + collections.add(new HashSet<>(content)); + collections.add(new LinkedHashSet<>(content)); + collections.add(new TreeSet<>(content)); + + Stack stack = new Stack<>(); + stack.addAll(content); + collections.add(stack); + collections.add(new PriorityQueue<>(content)); + collections.add(new ArrayDeque<>(content)); + + // Concurrent collections + + collections.add(new ConcurrentSkipListSet<>(content)); + + ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<>(content.size()); + for (Integer i : content) + arrayBlockingQueue.add(i); + collections.add(arrayBlockingQueue); + collections.add(new PriorityBlockingQueue<>(content)); + collections.add(new LinkedBlockingQueue<>(content)); + collections.add(new LinkedTransferQueue<>(content)); + collections.add(new ConcurrentLinkedQueue<>(content)); + collections.add(new LinkedBlockingDeque<>(content)); + collections.add(new ConcurrentLinkedDeque<>(content)); + + Object[][] params = new Object[collections.size()][]; + for (int i = 0; i < collections.size(); i++) { + params[i] = new Object[]{collections.get(i).getClass().getName(), collections.get(i)}; + } + + return params; + } + + @Test(dataProvider = "collections") + public void testCollectionSizeRemove(String name, Collection c) { + assertTrue(c.remove(1)); + Stream s = c.stream(); + assertTrue(c.remove(2)); + Object[] result = s.toArray(); + assertEquals(result.length, c.size()); + } + + @DataProvider(name = "maps") + public Object[][] createMaps() { + Map content = new HashMap<>(); + for (int i = 0; i < 10; i++) { + content.put(i, i); + } + + Map>> maps = new HashMap<>(); + + maps.put(HashMap.class.getName(), () -> new HashMap<>(content)); + maps.put(HashMap.class.getName(), () -> new LinkedHashMap<>(content)); + maps.put(IdentityHashMap.class.getName(), () -> new IdentityHashMap<>(content)); + maps.put(WeakHashMap.class.getName(), () -> new WeakHashMap<>(content)); + + maps.put(TreeMap.class.getName(), () -> new TreeMap<>(content)); + maps.put(TreeMap.class.getName() + ".descendingMap()", () -> new TreeMap<>(content).descendingMap()); + + // The following are not lazy +// maps.put(TreeMap.class.getName() + ".descendingMap().descendingMap()", () -> new TreeMap<>(content).descendingMap().descendingMap()); +// maps.put(TreeMap.class.getName() + ".headMap()", () -> new TreeMap<>(content).headMap(content.size() - 1)); +// maps.put(TreeMap.class.getName() + ".descendingMap().headMap()", () -> new TreeMap<>(content).descendingMap().tailMap(content.size() - 1, false)); + + // Concurrent collections + + maps.put(ConcurrentHashMap.class.getName(), () -> new ConcurrentHashMap<>(content)); + maps.put(ConcurrentSkipListMap.class.getName(), () -> new ConcurrentSkipListMap<>(content)); + + Object[][] params = new Object[maps.size()][]; + int i = 0; + for (Map.Entry>> e : maps.entrySet()) { + params[i++] = new Object[]{e.getKey(), e.getValue()}; + + } + + return params; + } + + @Test(dataProvider = "maps", groups = { "serialization-hostile" }) + public void testMapKeysSizeRemove(String name, Supplier> c) { + testCollectionSizeRemove(name + " key set", c.get().keySet()); + } + + @Test(dataProvider = "maps", groups = { "serialization-hostile" }) + public void testMapValuesSizeRemove(String name, Supplier> c) { + testCollectionSizeRemove(name + " value set", c.get().values()); + } + + @Test(dataProvider = "maps") + public void testMapEntriesSizeRemove(String name, Supplier> c) { + testEntrySetSizeRemove(name + " entry set", c.get().entrySet()); + } + + private void testEntrySetSizeRemove(String name, Set> c) { + Map.Entry first = c.iterator().next(); + assertTrue(c.remove(first)); + Stream> s = c.stream(); + Map.Entry second = c.iterator().next(); + assertTrue(c.remove(second)); + Object[] result = s.toArray(); + assertEquals(result.length, c.size()); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java new file mode 100644 index 00000000000..cb492f8003a --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.*; + +import static java.util.stream.LambdaTestHelpers.*; + +/** + * DistinctOpTest + */ +@Test +public class DistinctOpTest extends OpTestCase { + + public void testUniqOp() { + assertCountSum(repeat(0, 10).stream().distinct(), 1, 0); + assertCountSum(repeat(1, 10).stream().distinct(), 1, 1); + assertCountSum(countTo(0).stream().distinct(), 0, 0); + assertCountSum(countTo(10).stream().distinct(), 10, 55); + assertCountSum(countTo(10).stream().distinct(), 10, 55); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOp(String name, TestData.OfRef data) { + Collection result = exerciseOpsInt(data, Stream::distinct, IntStream::distinct, LongStream::distinct, DoubleStream::distinct); + + assertUnique(result); + assertTrue((data.size() > 0) ? result.size() > 0 : result.size() == 0); + assertTrue(result.size() <= data.size()); + } + + @Test(dataProvider = "withNull:StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOpWithNull(String name, TestData.OfRef data) { + Collection node = exerciseOps(data, Stream::distinct); + assertUnique(node); + + node = withData(data). + stream(s -> s.unordered().distinct()). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + assertUnique(node); + + node = exerciseOps(data, s -> s.distinct().distinct()); + assertUnique(node); + } + + @Test(dataProvider = "withNull:StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOpWithNullSorted(String name, TestData.OfRef data) { + List l = new ArrayList<>(); + data.into(l).sort(cNullInteger); + // Need to inject SORTED into the sorted list source since + // sorted() with a comparator ironically clears SORTED + Collection node = exerciseOps(new SortedTestData<>(l), Stream::distinct); + assertUnique(node); + assertSorted(node, cNullInteger); + } + + @SuppressWarnings("serial") + static class SortedTestData extends TestData.AbstractTestData.RefTestData> { + SortedTestData(List coll) { + super("SortedTestData", coll, + c -> StreamSupport.stream(Spliterators.spliterator(c.toArray(), Spliterator.ORDERED | Spliterator.SORTED)), + c -> StreamSupport.parallelStream(Spliterators.spliterator(c.toArray(), Spliterator.ORDERED | Spliterator.SORTED)), + c -> Spliterators.spliterator(c.toArray(), Spliterator.ORDERED | Spliterator.SORTED), + List::size); + } + } + + public static final Comparator cNullInteger = (a, b) -> { + if (a == null && b == null) { + return 0; + } + else if (a == null) { + return -1; + } + else if (b == null) { + return 1; + } + else { + return Integer.compare(a, b); + } + }; + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testDistinctDistinct(String name, TestData.OfRef data) { + Collection result = withData(data) + .stream(s -> s.distinct().distinct(), new CollectorOps.TestParallelSizedOp<>()) + .exercise(); + assertUnique(result); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testDistinctSorted(String name, TestData.OfRef data) { + Collection result = withData(data) + .stream(s -> s.distinct().sorted(), + new CollectorOps.TestParallelSizedOp<>()) + .exercise(); + assertUnique(result); + assertSorted(result); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testSortedDistinct(String name, TestData.OfRef data) { + Collection result = withData(data) + .stream(s -> s.sorted().distinct(), + new CollectorOps.TestParallelSizedOp<>()) + .exercise(); + assertUnique(result); + assertSorted(result); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java new file mode 100644 index 00000000000..4a66d1a86d4 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013, 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. + * + * 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.stream; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Random; +import java.util.stream.DoubleStream; +import java.util.stream.LongStream; + +import static org.testng.Assert.assertEquals; + +@Test +public class DoublePrimitiveOpsTests { + + // @@@ tests for double are fragile if relying on equality when accumulating and multiplying values + + public void testUnBox() { + double sum = Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0).stream().mapToDouble(i -> i).reduce(0.0, Double::sum); + assertEquals(sum, 1.0 + 2.0 + 3.0 + 4.0 + 5.0); + } + + public void testToArray() { + { + double[] array = LongStream.range(1, 10).doubles().map(i -> i * 2).toArray(); + assertEquals(array, new double[]{2, 4, 6, 8, 10, 12, 14, 16, 18}); + } + + { + double[] array = LongStream.range(1, 10).parallel().doubles().map(i -> i * 2).toArray(); + assertEquals(array, new double[]{2, 4, 6, 8, 10, 12, 14, 16, 18}); + } + } + + public void testSort() { + Random r = new Random(); + + double[] content = DoubleStream.generate(() -> r.nextDouble()).limit(10).toArray(); + double[] sortedContent = content.clone(); + Arrays.sort(sortedContent); + + { + double[] array = Arrays.stream(content).sorted().toArray(); + assertEquals(array, sortedContent); + } + + { + double[] array = Arrays.stream(content).parallel().sorted().toArray(); + assertEquals(array, sortedContent); + } + } + + public void testSortSort() { + Random r = new Random(); + + double[] content = DoubleStream.generate(() -> r.nextDouble()).limit(10).toArray(); + double[] sortedContent = content.clone(); + Arrays.sort(sortedContent); + + { + double[] array = Arrays.stream(content).sorted().sorted().toArray(); + assertEquals(array, sortedContent); + } + + { + double[] array = Arrays.stream(content).parallel().sorted().sorted().toArray(); + assertEquals(array, sortedContent); + } + } + + public void testLimit() { + double[] expected = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + { + double[] actual = DoubleStream.iterate(1.0, i -> i + 1.0).limit(9).toArray(); + Assert.assertTrue(Arrays.equals(expected, actual)); + } + + { + double[] actual = LongStream.range(1, 100).parallel().doubles().limit(9).toArray(); + Assert.assertTrue(Arrays.equals(expected, actual)); + } + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ExplodeOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ExplodeOpTest.java new file mode 100644 index 00000000000..dcb88fb61cb --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ExplodeOpTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.function.Function; +import java.util.stream.*; + +import static java.util.stream.LambdaTestHelpers.*; + +/** + * ExplodeOpTest + * + * @author Brian Goetz + */ +@Test +public class ExplodeOpTest extends OpTestCase { + + static final Function> integerRangeMapper + = e -> IntStream.range(0, e).boxed(); + + public void testFlatMap() { + String[] stringsArray = {"hello", "there", "", "yada"}; + Stream strings = Arrays.asList(stringsArray).stream(); + assertConcat(strings.flatMap(flattenChars).iterator(), "hellothereyada"); + + assertCountSum(countTo(10).stream().flatMap(mfId), 10, 55); + assertCountSum(countTo(10).stream().flatMap(mfNull), 0, 0); + assertCountSum(countTo(3).stream().flatMap(mfLt), 6, 4); + + exerciseOps(TestData.Factory.ofArray("stringsArray", stringsArray), s -> s.flatMap(flattenChars)); + exerciseOps(TestData.Factory.ofArray("LONG_STRING", new String[] {LONG_STRING}), s -> s.flatMap(flattenChars)); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + Collection result = exerciseOps(data, s -> s.flatMap(mfId)); + assertEquals(data.size(), result.size()); + + result = exerciseOps(data, s -> s.flatMap(mfNull)); + assertEquals(0, result.size()); + + exerciseOps(data, s -> s.flatMap(mfLt)); + exerciseOps(data, s -> s.flatMap(integerRangeMapper)); + exerciseOps(data, s -> s.flatMap((Integer e) -> IntStream.range(0, e).boxed().limit(10))); + } + + // + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOps(String name, TestData.OfInt data) { + Collection result = exerciseOps(data, s -> s.flatMap(i -> Collections.singleton(i).stream().mapToInt(j -> j))); + assertEquals(data.size(), result.size()); + assertContents(data, result); + + result = exerciseOps(data, s -> s.flatMap(i -> IntStream.empty())); + assertEquals(0, result.size()); + + exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, e))); + exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, e).limit(10))); + } + + // + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOps(String name, TestData.OfLong data) { + Collection result = exerciseOps(data, s -> s.flatMap(i -> Collections.singleton(i).stream().mapToLong(j -> j))); + assertEquals(data.size(), result.size()); + assertContents(data, result); + + result = exerciseOps(data, s -> LongStream.empty()); + assertEquals(0, result.size()); + + exerciseOps(data, s -> s.flatMap(e -> LongStream.range(0, e))); + exerciseOps(data, s -> s.flatMap(e -> LongStream.range(0, e).limit(10))); + } + + // + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOps(String name, TestData.OfDouble data) { + Collection result = exerciseOps(data, s -> s.flatMap(i -> Collections.singleton(i).stream().mapToDouble(j -> j))); + assertEquals(data.size(), result.size()); + assertContents(data, result); + + result = exerciseOps(data, s -> DoubleStream.empty()); + assertEquals(0, result.size()); + + exerciseOps(data, s -> s.flatMap(e -> DoubleStream.range(0, e))); + exerciseOps(data, s -> s.flatMap(e -> DoubleStream.range(0, e).limit(10))); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FilterOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FilterOpTest.java new file mode 100644 index 00000000000..12ff052a2a0 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FilterOpTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.Collection; +import java.util.stream.*; + +import org.testng.annotations.Test; + +import java.util.Arrays; + +import static java.util.stream.LambdaTestHelpers.*; + +/** + * FilterOpTest + * + * @author Brian Goetz + */ +@Test +public class FilterOpTest extends OpTestCase { + public void testFilter() { + assertCountSum(countTo(0).stream().filter(pTrue), 0, 0); + assertCountSum(countTo(10).stream().filter(pFalse), 0, 0); + assertCountSum(countTo(10).stream().filter(pEven), 5, 30); + assertCountSum(countTo(10).stream().filter(pOdd), 5, 25); + assertCountSum(countTo(10).stream().filter(pTrue), 10, 55); + assertCountSum(countTo(10).stream().filter(pEven).filter(pOdd), 0, 0); + + exerciseOps(countTo(1000), s -> s.filter(pTrue), countTo(1000)); + exerciseOps(countTo(1000), s -> s.filter(pFalse), countTo(0)); + exerciseOps(countTo(1000), s -> s.filter(e -> e > 100), range(101, 1000)); + exerciseOps(countTo(1000), s -> s.filter(e -> e < 100), countTo(99)); + exerciseOps(countTo(1000), s -> s.filter(e -> e == 100), Arrays.asList(100)); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + Collection result = exerciseOps(data, s -> s.filter(pTrue)); + assertEquals(result.size(), data.size()); + + result = exerciseOps(data, s -> s.filter(pFalse)); + assertEquals(result.size(), 0); + + exerciseOps(data, s -> s.filter(pEven)); + exerciseOps(data, s -> s.filter(pOdd)); + + result = exerciseOps(data, s -> s.filter(pOdd.and(pEven))); + assertEquals(result.size(), 0); + + result = exerciseOps(data, s -> s.filter(pOdd.or(pEven))); + assertEquals(result.size(), data.size()); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testOps(String name, TestData.OfInt data) { + Collection result = exerciseOps(data, s -> s.filter(i -> true)); + assertEquals(result.size(), data.size()); + + result = exerciseOps(data, s -> s.filter(i -> false)); + assertEquals(result.size(), 0); + + exerciseOps(data, s -> s.filter(i -> 0 == i % 2)); + exerciseOps(data, s -> s.filter(i -> 1 == i % 2)); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testOps(String name, TestData.OfLong data) { + Collection result = exerciseOps(data, s -> s.filter(i -> true)); + assertEquals(result.size(), data.size()); + + result = exerciseOps(data, s -> s.filter(i -> false)); + assertEquals(result.size(), 0); + + exerciseOps(data, s -> s.filter(i -> 0 == i % 2)); + exerciseOps(data, s -> s.filter(i -> 1 == i % 2)); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testOps(String name, TestData.OfDouble data) { + Collection result = exerciseOps(data, s -> s.filter(i -> true)); + assertEquals(result.size(), data.size()); + + result = exerciseOps(data, s -> s.filter(i -> false)); + assertEquals(result.size(), 0); + + exerciseOps(data, s -> s.filter(i -> 0 == ((long) i) % 2)); + exerciseOps(data, s -> s.filter(i -> 1 == ((long) i) % 2)); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FindAnyOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FindAnyOpTest.java new file mode 100644 index 00000000000..64a9240fecd --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FindAnyOpTest.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.stream.*; + +import org.testng.annotations.Test; + +import java.util.function.Function; + +import static java.util.stream.LambdaTestHelpers.*; + + +/** + * FindAnyOpTest + */ +@Test +public class FindAnyOpTest extends OpTestCase { + + public void testFindAny() { + assertFalse(Collections.emptySet().stream().findAny().isPresent(), "no result"); + assertFalse(countTo(10).stream().filter(x -> x > 10).findAny().isPresent(), "no result"); + assertTrue(countTo(10).stream().filter(pEven).findAny().isPresent(), "with result"); + } + + public void testFindAnyParallel() { + assertFalse(Collections.emptySet().parallelStream().findAny().isPresent(), "no result"); + assertFalse(countTo(1000).parallelStream().filter(x -> x > 1000).findAny().isPresent(), "no result"); + assertTrue(countTo(1000).parallelStream().filter(pEven).findAny().isPresent(), "with result"); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testStream(String name, TestData.OfRef data) { + exerciseStream(data, s -> s); + exerciseStream(data, s -> s.filter(pTrue)); + exerciseStream(data, s -> s.filter(pFalse)); + exerciseStream(data, s -> s.filter(pEven)); + } + + void exerciseStream(TestData.OfRef data, Function, Stream> fs) { + Optional or = withData(data).terminal(fs, s -> s.findAny()).equalator(VALID_ANSWER).exercise(); + if (or.isPresent()) { + Integer r = or.get(); + Iterator it = fs.apply(data.stream()).iterator(); + boolean contained = false; + while (!contained && it.hasNext()) { + contained = Objects.equals(r, it.next()); + } + assertTrue(contained); + } + else { + assertFalse(fs.apply(data.stream()).iterator().hasNext()); + } + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntStream(String name, TestData.OfInt data) { + exerciseIntStream(data, s -> s); + exerciseIntStream(data, s -> s.filter(ipTrue)); + exerciseIntStream(data, s -> s.filter(ipFalse)); + exerciseIntStream(data, s -> s.filter(ipEven)); + } + + void exerciseIntStream(TestData.OfInt data, Function fs) { + OptionalInt or = withData(data).terminal(fs, s -> s.findAny()).equalator(INT_VALID_ANSWER).exercise(); + if (or.isPresent()) { + int r = or.getAsInt(); + PrimitiveIterator.OfInt it = fs.apply(data.stream()).iterator(); + boolean contained = false; + while (!contained && it.hasNext()) { + contained = r == it.nextInt(); + } + assertTrue(contained); + } + else { + assertFalse(fs.apply(data.stream()).iterator().hasNext()); + } + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongStream(String name, TestData.OfLong data) { + exerciseLongStream(data, s -> s); + exerciseLongStream(data, s -> s.filter(lpTrue)); + exerciseLongStream(data, s -> s.filter(lpFalse)); + exerciseLongStream(data, s -> s.filter(lpEven)); + } + + void exerciseLongStream(TestData.OfLong data, Function fs) { + OptionalLong or = withData(data).terminal(fs, s -> s.findAny()).equalator(LONG_VALID_ANSWER).exercise(); + if (or.isPresent()) { + long r = or.getAsLong(); + PrimitiveIterator.OfLong it = fs.apply(data.stream()).iterator(); + boolean contained = false; + while (!contained && it.hasNext()) { + contained = r == it.nextLong(); + } + assertTrue(contained); + } + else { + assertFalse(fs.apply(data.stream()).iterator().hasNext()); + } + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleStream(String name, TestData.OfDouble data) { + exerciseDoubleStream(data, s -> s); + exerciseDoubleStream(data, s -> s.filter(dpTrue)); + exerciseDoubleStream(data, s -> s.filter(dpEven)); + exerciseDoubleStream(data, s -> s.filter(dpFalse)); + } + + void exerciseDoubleStream(TestData.OfDouble data, Function fs) { + OptionalDouble or = withData(data).terminal(fs, s -> s.findAny()).equalator(DOUBLE_VALID_ANSWER).exercise(); + if (or.isPresent()) { + double r = or.getAsDouble(); + PrimitiveIterator.OfDouble it = fs.apply(data.stream()).iterator(); + boolean contained = false; + while (!contained && it.hasNext()) { + contained = r == it.nextDouble(); + } + assertTrue(contained); + } + else { + assertFalse(fs.apply(data.stream()).iterator().hasNext()); + } + } + + static final BiConsumer, Optional> VALID_ANSWER = (a, b) -> assertEquals(a.isPresent(), b.isPresent()); + + static final BiConsumer INT_VALID_ANSWER = (a, b) -> assertEquals(a.isPresent(), b.isPresent()); + + static final BiConsumer LONG_VALID_ANSWER = (a, b) -> assertEquals(a.isPresent(), b.isPresent()); + + static final BiConsumer DOUBLE_VALID_ANSWER = (a, b) -> assertEquals(a.isPresent(), b.isPresent()); +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FindFirstOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FindFirstOpTest.java new file mode 100644 index 00000000000..02e3d0727b8 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FindFirstOpTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.*; +import java.util.stream.*; + +import org.testng.annotations.Test; + +import java.util.function.Function; + +import static java.util.stream.LambdaTestHelpers.*; + + +/** + * FindFirstOpTest + */ +@Test +public class FindFirstOpTest extends OpTestCase { + + public void testFindFirst() { + assertFalse(Collections.emptySet().stream().findFirst().isPresent(), "no result"); + assertFalse(countTo(10).stream().filter(x -> x > 10).findFirst().isPresent(), "no result"); + + exerciseOps(countTo(1000), s -> Arrays.asList(new Integer[]{s.filter(pEven).findFirst().get()}).stream(), Arrays.asList(2)); + exerciseOps(countTo(1000), s -> Arrays.asList(new Integer[]{s.findFirst().get()}).stream(), Arrays.asList(1)); + exerciseOps(countTo(1000), s -> Arrays.asList(new Integer[]{s.filter(e -> e == 499).findFirst().get()}).stream(), Arrays.asList(499)); + exerciseOps(countTo(1000), s -> Arrays.asList(new Integer[]{s.filter(e -> e == 999).findFirst().get()}).stream(), Arrays.asList(999)); + exerciseOps(countTo(0), s -> Arrays.asList(new Integer[]{s.findFirst().orElse(-1)}).stream(), Arrays.asList(-1)); + exerciseOps(countTo(1000), s -> Arrays.asList(new Integer[]{s.filter(e -> e == 1499).findFirst().orElse(-1)}).stream(), Arrays.asList(-1)); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testStream(String name, TestData.OfRef data) { + exerciseStream(data, s -> s); + exerciseStream(data, s -> s.filter(pTrue)); + exerciseStream(data, s -> s.filter(pFalse)); + exerciseStream(data, s -> s.filter(pEven)); + } + + void exerciseStream(TestData.OfRef data, Function, Stream> fs) { + Optional r = exerciseTerminalOps(data, fs, s -> s.findFirst()); + if (r.isPresent()) { + Iterator i = fs.apply(data.stream()).iterator(); + assertTrue(i.hasNext()); + assertEquals(i.next(), r.get()); + } + else { + assertFalse(fs.apply(data.stream()).iterator().hasNext()); + } + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntStream(String name, TestData.OfInt data) { + exerciseIntStream(data, s -> s); + exerciseIntStream(data, s -> s.filter(ipTrue)); + exerciseIntStream(data, s -> s.filter(ipFalse)); + exerciseIntStream(data, s -> s.filter(ipEven)); + } + + void exerciseIntStream(TestData.OfInt data, Function fs) { + OptionalInt r = exerciseTerminalOps(data, fs, s -> s.findFirst()); + if (r.isPresent()) { + PrimitiveIterator.OfInt i = fs.apply(data.stream()).iterator(); + assertTrue(i.hasNext()); + assertEquals(i.nextInt(), r.getAsInt()); + } + else { + assertFalse(fs.apply(data.stream()).iterator().hasNext()); + } + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongStream(String name, TestData.OfLong data) { + exerciseLongStream(data, s -> s); + exerciseLongStream(data, s -> s.filter(lpTrue)); + exerciseLongStream(data, s -> s.filter(lpFalse)); + exerciseLongStream(data, s -> s.filter(lpEven)); + } + + void exerciseLongStream(TestData.OfLong data, Function fs) { + OptionalLong r = exerciseTerminalOps(data, fs, s -> s.findFirst()); + if (r.isPresent()) { + PrimitiveIterator.OfLong i = fs.apply(data.stream()).iterator(); + assertTrue(i.hasNext()); + assertEquals(i.nextLong(), r.getAsLong()); + } + else { + assertFalse(fs.apply(data.stream()).iterator().hasNext()); + } + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleStream(String name, TestData.OfDouble data) { + exerciseDoubleStream(data, s -> s); + exerciseDoubleStream(data, s -> s.filter(dpTrue)); + exerciseDoubleStream(data, s -> s.filter(dpFalse)); + exerciseDoubleStream(data, s -> s.filter(dpEven)); + } + + void exerciseDoubleStream(TestData.OfDouble data, Function fs) { + OptionalDouble r = exerciseTerminalOps(data, fs, s -> s.findFirst()); + if (r.isPresent()) { + PrimitiveIterator.OfDouble i = fs.apply(data.stream()).iterator(); + assertTrue(i.hasNext()); + assertEquals(i.nextDouble(), r.getAsDouble()); + } + else { + assertFalse(fs.apply(data.stream()).iterator().hasNext()); + } + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ForEachOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ForEachOpTest.java new file mode 100644 index 00000000000..4a078a485da --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ForEachOpTest.java @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.stream.*; + +import static java.util.stream.LambdaTestHelpers.countTo; + +/** + * ForEachOpTest + */ +@Test +public class ForEachOpTest extends OpTestCase { + + @Test(groups = { "serialization-hostile" }) + public void testForEach() { + exerciseTerminalOps(countTo(10), + s -> { + AtomicInteger count = new AtomicInteger(0); + s.forEach(e -> count.incrementAndGet()); + return count.get(); + }, + 10); + + exerciseTerminalOps(countTo(10), + s -> { + AtomicInteger sum = new AtomicInteger(0); + s.forEach(sum::addAndGet); + return sum.get(); + }, + 55); + } + + @Test + public void testForEachOrdered() { + List input = countTo(10000); + TestData.OfRef data = TestData.Factory.ofCollection("[1, 10000]", input); + + Function, List> terminalFunc = s -> { + List l = new ArrayList<>(); + s.forEachOrdered(l::add); + return l; + }; + + // Test head + withData(data). + terminal(terminalFunc). + expectedResult(input). + exercise(); + + // Test multiple stages + withData(data). + terminal(s -> s.map(LambdaTestHelpers.identity()), terminalFunc). + expectedResult(input). + exercise(); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testForEach(String name, TestData.OfRef data) { + Function, List> terminalFunc = s -> { + List l = Collections.synchronizedList(new ArrayList<>()); + s.forEach(l::add); + return l; + }; + + // Test head + withData(data). + terminal(terminalFunc). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + + // Test multiple stages + withData(data). + terminal(s -> s.map(LambdaTestHelpers.identity()), terminalFunc). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + } + + // + + @Test + public void testIntForEachOrdered() { + List input = countTo(10000); + TestData.OfInt data = TestData.Factory.ofIntSupplier("[1, 10000]", + () -> IntStream.range(1, 10001)); + + Function> terminalFunc = s -> { + List l = new ArrayList<>(); + s.forEachOrdered(l::add); + return l; + }; + + // Test head + withData(data). + terminal(terminalFunc). + expectedResult(input). + exercise(); + + // Test multiple stages + withData(data). + terminal(s -> s.map(i -> i), terminalFunc). + expectedResult(input). + exercise(); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntForEach(String name, TestData.OfInt data) { + Function> terminalFunc = s -> { + List l = Collections.synchronizedList(new ArrayList()); + s.forEach(l::add); + return l; + }; + + // Test head + withData(data). + terminal(terminalFunc). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + + // Test multiple stages + withData(data). + terminal(s -> s.map(i -> i), terminalFunc). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + } + + // + + @Test + public void testLongForEachOrdered() { + List input = countTo(10000); + TestData.OfLong data = TestData.Factory.ofLongSupplier("[1, 10000]", + () -> LongStream.range(1, 10001)); + + Function> terminalFunc = s -> { + List l = new ArrayList<>(); + s.forEachOrdered(e -> l.add((int) e)); + return l; + }; + + // Test head + withData(data). + terminal(terminalFunc). + expectedResult(input). + exercise(); + + // Test multiple stages + withData(data). + terminal(s -> s.map(i -> i), terminalFunc). + expectedResult(input). + exercise(); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOps(String name, TestData.OfLong data) { + Function> terminalFunc = s -> { + List l = Collections.synchronizedList(new ArrayList()); + s.forEach(l::add); + return l; + }; + + // Test head + withData(data). + terminal(terminalFunc). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + + // Test multiple stages + withData(data). + terminal(s -> s.map(i -> i), terminalFunc). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + } + + // + + @Test + public void testDoubleForEachOrdered() { + List input = countTo(10000); + TestData.OfDouble data = TestData.Factory.ofDoubleSupplier("[1, 10000]", + () -> DoubleStream.range(1, 10001)); + + Function> terminalFunc = s -> { + List l = new ArrayList<>(); + s.forEachOrdered(e -> l.add((int) e)); + return l; + }; + + // Test head + withData(data). + terminal(terminalFunc). + expectedResult(input). + exercise(); + + // Test multiple stages + withData(data). + terminal(s -> s.map(i -> i), terminalFunc). + expectedResult(input). + exercise(); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOps(String name, TestData.OfDouble data) { + Function> terminalFunc = s -> { + List l = Collections.synchronizedList(new ArrayList()); + s.forEach(l::add); + return l; + }; + + // Test head + withData(data). + terminal(terminalFunc). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + + // Test multiple stages + withData(data). + terminal(s -> s.map(i -> i), terminalFunc). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + } + +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/GroupByOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/GroupByOpTest.java new file mode 100644 index 00000000000..7c6d6953c18 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/GroupByOpTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import java.util.stream.LambdaTestHelpers; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.StreamOpFlagTestHelper; +import java.util.stream.StreamTestDataProvider; +import java.util.stream.TestData; + +import org.testng.annotations.Test; + +import static java.util.stream.LambdaTestHelpers.countTo; +import static java.util.stream.LambdaTestHelpers.mDoubler; +import static java.util.stream.LambdaTestHelpers.mId; +import static java.util.stream.LambdaTestHelpers.mZero; +import static java.util.stream.LambdaTestHelpers.pEven; +import static java.util.stream.LambdaTestHelpers.pFalse; +import static java.util.stream.LambdaTestHelpers.pOdd; +import static java.util.stream.LambdaTestHelpers.pTrue; + +/** + * GroupByOpTest + * + */ +@Test +public class GroupByOpTest extends OpTestCase { + + public void testBypassCollect() { + Collector>> collector + = Collectors.groupingBy(LambdaTestHelpers.forPredicate(pEven, true, false)); + + Map> m = collector.resultSupplier().get(); + int[] ints = countTo(10).stream().mapToInt(e -> (int) e).toArray(); + for (int i : ints) + m = collector.accumulator().apply(m, i); + + assertEquals(2, m.keySet().size()); + for(Collection group : m.values()) { + int count = 0; + Stream stream = group.stream(); + Iterator it = stream.iterator(); + while (it.hasNext()) { + it.next(); + ++count; + } + assertEquals(5, count); + } + } + + public void testGroupBy() { + Map> result = countTo(10).stream().collect(Collectors.groupingBy(LambdaTestHelpers.forPredicate(pEven, true, false))); + + assertEquals(2, result.keySet().size()); + for(Collection group : result.values()) { + int count = 0; + Stream stream = group.stream(); + Iterator it = stream.iterator(); + while (it.hasNext()) { + it.next(); + ++count; + } + assertEquals(5, count); + } + } + + static class MapperData { + Function m; + int expectedSize; + + MapperData(Function m, int expectedSize) { + this.m = m; + this.expectedSize = expectedSize; + } + } + + List> getMapperData(TestData.OfRef data) { + int uniqueSize = data.into(new HashSet<>()).size(); + + return Arrays.asList( + new MapperData<>(mId, uniqueSize), + new MapperData<>(mZero, Math.min(1, data.size())), + new MapperData<>(mDoubler, uniqueSize), + new MapperData<>(LambdaTestHelpers.compose(mId, mDoubler), uniqueSize), + new MapperData<>(LambdaTestHelpers.compose(mDoubler, mDoubler), uniqueSize), + + new MapperData<>(LambdaTestHelpers.forPredicate(pFalse, true, false), Math.min(1, uniqueSize)), + new MapperData<>(LambdaTestHelpers.forPredicate(pTrue, true, false), Math.min(1, uniqueSize)), + new MapperData<>(LambdaTestHelpers.forPredicate(pEven, true, false), Math.min(2, uniqueSize)), + new MapperData<>(LambdaTestHelpers.forPredicate(pOdd, true, false), Math.min(2, uniqueSize)) + ); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + // @@@ More things to test here: + // - Every value in data is present in right bucket + // - Total number of values equals size of data + + for (MapperData md : getMapperData(data)) { + Collector>> tab = Collectors.groupingBy(md.m); + Map> result = + withData(data) + .terminal(s -> s, s -> s.collect(tab)) + .parallelEqualityAsserter(s -> StreamOpFlagTestHelper.isStreamOrdered(s) ? GroupByOpTest::assertObjectEquals : GroupByOpTest::assertMultiMapEquals) + .exercise(); + assertEquals(result.keySet().size(), md.expectedSize); + } + } + + static void assertObjectEquals(Object a, Object b) { + assertTrue(Objects.equals(a, b)); + } + + static void assertMultiMapEquals(Map> a, Map> b) { + assertTrue(multiMapEquals(a, b)); + } + + static boolean multiMapEquals(Map> a, Map> b) { + if (!Objects.equals(a.keySet(), b.keySet())) { + return false; + } + + for (K k : a.keySet()) { + Set as = new HashSet<>(a.get(k)); + Set bs = new HashSet<>(b.get(k)); + if (!Objects.equals(as, bs)) { + return false; + } + } + + return true; + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest.java new file mode 100644 index 00000000000..a43802cc419 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.stream.OpTestCase; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.stream.LambdaTestHelpers.assertContents; + + +@Test +public class InfiniteStreamWithLimitOpTest extends OpTestCase { + + private static final List tenAs = Arrays.asList("A", "A", "A", "A", "A", "A", "A", "A", "A", "A"); + + public void testRepeatLimit() { + assertContents(Stream.generate(() -> "A").limit(10).iterator(), tenAs.iterator()); + } + + public void testIterateLimit() { + assertContents(Stream.iterate("A", s -> s).limit(10).iterator(), tenAs.iterator()); + } + + public void testIterateFibLimit() { + Stream fib = Stream.iterate(new int[] {0, 1}, pair -> new int[] {pair[1], pair[0] + pair[1]}) + .map(pair -> pair[0]); + + assertContents( + fib.limit(10).iterator(), + Arrays.asList(0, 1, 1, 2, 3, 5, 8, 13, 21, 34).iterator()); + } + + public void testInfiniteWithLimitToShortCircuitTerminal() { + Object[] array = Stream.generate(() -> 1).limit(4).toArray(); + assertEquals(4, array.length); + array = Stream.generate(() -> 1).limit(4).filter(i -> true).toArray(); + assertEquals(4, array.length); + List result = Stream.generate(() -> 1).limit(4).collect(Collectors.toList()); + assertEquals(result, Arrays.asList(1, 1, 1, 1)); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java new file mode 100644 index 00000000000..1efc5fde987 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.IntConsumer; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.testng.Assert.assertEquals; + +@Test +public class IntPrimitiveOpsTests { + + public void testSum() { + long sum = IntStream.range(1, 10).filter(i -> i % 2 == 0).sum(); + assertEquals(sum, 20); + } + + public void testMap() { + long sum = IntStream.range(1, 10).filter(i -> i % 2 == 0).map(i -> i * 2).sum(); + assertEquals(sum, 40); + } + + public void testParSum() { + long sum = IntStream.range(1, 10).parallel().filter(i -> i % 2 == 0).sum(); + assertEquals(sum, 20); + } + + @Test(groups = { "serialization-hostile" }) + public void testTee() { + int[] teeSum = new int[1]; + long sum = IntStream.range(1, 10).filter(i -> i % 2 == 0).peek(i -> { teeSum[0] = teeSum[0] + i; }).sum(); + assertEquals(teeSum[0], sum); + } + + @Test(groups = { "serialization-hostile" }) + public void testForEach() { + int[] sum = new int[1]; + IntStream.range(1, 10).filter(i -> i % 2 == 0).forEach(i -> { sum[0] = sum[0] + i; }); + assertEquals(sum[0], 20); + } + + @Test(groups = { "serialization-hostile" }) + public void testParForEach() { + AtomicInteger ai = new AtomicInteger(0); + IntStream.range(1, 10).parallel().filter(i -> i % 2 == 0).forEach(ai::addAndGet); + assertEquals(ai.get(), 20); + } + + public void testBox() { + List l = IntStream.range(1, 10).parallel().boxed().collect(Collectors.toList()); + int sum = l.stream().reduce(0, (a, b) -> a + b); + assertEquals(sum, 45); + } + + public void testUnBox() { + long sum = Arrays.asList(1, 2, 3, 4, 5).stream().mapToInt(i -> (int) i).sum(); + assertEquals(sum, 15); + } + + public void testToArray() { + { + int[] array = IntStream.range(1, 10).map(i -> i * 2).toArray(); + assertEquals(array, new int[]{2, 4, 6, 8, 10, 12, 14, 16, 18}); + } + + { + int[] array = IntStream.range(1, 10).parallel().map(i -> i * 2).toArray(); + assertEquals(array, new int[]{2, 4, 6, 8, 10, 12, 14, 16, 18}); + } + } + + public void testSort() { + Random r = new Random(); + + int[] content = IntStream.generate(() -> r.nextInt(100)).limit(10).toArray(); + int[] sortedContent = content.clone(); + Arrays.sort(sortedContent); + + { + int[] array = Arrays.stream(content).sorted().toArray(); + assertEquals(array, sortedContent); + } + + { + int[] array = Arrays.stream(content).parallel().sorted().toArray(); + assertEquals(array, sortedContent); + } + } + + public void testSortSort() { + Random r = new Random(); + + int[] content = IntStream.generate(() -> r.nextInt(100)).limit(10).toArray(); + int[] sortedContent = content.clone(); + Arrays.sort(sortedContent); + + { + int[] array = Arrays.stream(content).sorted().sorted().toArray(); + assertEquals(array, sortedContent); + } + + { + int[] array = Arrays.stream(content).parallel().sorted().sorted().toArray(); + assertEquals(array, sortedContent); + } + } + + public void testSequential() { + + int[] expected = IntStream.range(1, 1000).toArray(); + + class AssertingConsumer implements IntConsumer { + private final int[] array; + int offset; + + AssertingConsumer(int[] array) { + this.array = array; + } + + @Override + public void accept(int value) { + assertEquals(array[offset++], value); + } + + public int getCount() { return offset; } + } + + { + AssertingConsumer consumer = new AssertingConsumer(expected); + IntStream.range(1, 1000).sequential().forEach(consumer); + assertEquals(expected.length, consumer.getCount()); + } + + { + AssertingConsumer consumer = new AssertingConsumer(expected); + IntStream.range(1, 1000).parallel().sequential().forEach(consumer); + assertEquals(expected.length, consumer.getCount()); + } + } + + public void testLimit() { + int[] expected = IntStream.range(1, 10).toArray(); + + { + int[] actual = IntStream.iterate(1, i -> i + 1).limit(9).toArray(); + Assert.assertTrue(Arrays.equals(expected, actual)); + } + + { + int[] actual = IntStream.range(1, 100).parallel().limit(9).toArray(); + Assert.assertTrue(Arrays.equals(expected, actual)); + } + } + +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntReduceTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntReduceTest.java new file mode 100644 index 00000000000..baf90075f79 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntReduceTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.stream.IntStream; +import java.util.stream.IntStreamTestDataProvider; +import java.util.stream.OpTestCase; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.OptionalInt; +import java.util.stream.TestData; + +import static java.util.stream.LambdaTestHelpers.*; + +public class IntReduceTest extends OpTestCase { + public void testReduce() { + int[] a = IntStream.range(1, 11).toArray(); + + assertEquals(55, Arrays.stream(a).reduce(irPlus).getAsInt()); + assertEquals(55, Arrays.stream(a).reduce(0, irPlus)); + assertEquals(10, Arrays.stream(a).reduce(irMax).getAsInt()); + assertEquals(1, Arrays.stream(a).reduce(irMin).getAsInt()); + + assertEquals(0, IntStream.empty().reduce(0, irPlus)); + assertFalse(IntStream.empty().reduce(irPlus).isPresent()); + + assertEquals(110, Arrays.stream(a).map(irDoubler).reduce(irPlus).getAsInt()); + assertEquals(20, Arrays.stream(a).map(irDoubler).reduce(irMax).getAsInt()); + assertEquals(2, Arrays.stream(a).map(irDoubler).reduce(irMin).getAsInt()); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testOps(String name, TestData.OfInt data) { + assertEquals(0, (int) exerciseTerminalOps(data, s -> s.filter(ipFalse), s -> s.reduce(0, irPlus))); + + OptionalInt seedless = exerciseTerminalOps(data, s -> s.reduce(irPlus)); + int folded = exerciseTerminalOps(data, s -> s.reduce(0, irPlus)); + assertEquals(folded, seedless.orElse(0)); + + seedless = exerciseTerminalOps(data, s -> s.reduce(irMin)); + folded = exerciseTerminalOps(data, s -> s.reduce(Integer.MAX_VALUE, irMin)); + assertEquals(folded, seedless.orElse(Integer.MAX_VALUE)); + + seedless = exerciseTerminalOps(data, s -> s.reduce(irMax)); + folded = exerciseTerminalOps(data, s -> s.reduce(Integer.MIN_VALUE, irMax)); + assertEquals(folded, seedless.orElse(Integer.MIN_VALUE)); + + seedless = exerciseTerminalOps(data, s -> s.map(irDoubler), s -> s.reduce(irPlus)); + folded = exerciseTerminalOps(data, s -> s.map(irDoubler), s -> s.reduce(0, irPlus)); + assertEquals(folded, seedless.orElse(0)); + + seedless = exerciseTerminalOps(data, s -> s.map(irDoubler), s -> s.reduce(irMin)); + folded = exerciseTerminalOps(data, s -> s.map(irDoubler), s -> s.reduce(Integer.MAX_VALUE, irMin)); + assertEquals(folded, seedless.orElse(Integer.MAX_VALUE)); + + seedless = exerciseTerminalOps(data, s -> s.map(irDoubler), s -> s.reduce(irMax)); + folded = exerciseTerminalOps(data, s -> s.map(irDoubler), s -> s.reduce(Integer.MIN_VALUE, irMax)); + assertEquals(folded, seedless.orElse(Integer.MIN_VALUE)); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntSliceOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntSliceOpTest.java new file mode 100644 index 00000000000..6521f8b7abd --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntSliceOpTest.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.Collection; +import java.util.stream.*; + +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import static java.util.stream.LambdaTestHelpers.assertCountSum; + +/** + * SliceOpTest + * + * @author Brian Goetz + */ +@Test +public class IntSliceOpTest extends OpTestCase { + + private static final int[] EMPTY_INT_ARRAY = new int[0]; + + public void testSkip() { + assertCountSum(IntStream.range(0, 0).substream(0).boxed(), 0, 0); + assertCountSum(IntStream.range(0, 0).substream(4).boxed(), 0, 0); + assertCountSum(IntStream.range(1, 5).substream(4).boxed(), 0, 0); + assertCountSum(IntStream.range(1, 5).substream(2).boxed(), 2, 7); + assertCountSum(IntStream.range(1, 5).substream(0).boxed(), 4, 10); + + assertCountSum(IntStream.range(0, 0).parallel().substream(0).boxed(), 0, 0); + assertCountSum(IntStream.range(0, 0).parallel().substream(4).boxed(), 0, 0); + assertCountSum(IntStream.range(1, 5).parallel().substream(4).boxed(), 0, 0); + assertCountSum(IntStream.range(1, 5).parallel().substream(2).boxed(), 2, 7); + assertCountSum(IntStream.range(1, 5).parallel().substream(0).boxed(), 4, 10); + + exerciseOps(EMPTY_INT_ARRAY, s -> s.substream(0), EMPTY_INT_ARRAY); + exerciseOps(EMPTY_INT_ARRAY, s -> s.substream(10), EMPTY_INT_ARRAY); + + exerciseOps(IntStream.range(1, 2).toArray(), s -> s.substream(0), IntStream.range(1, 2).toArray()); + exerciseOps(IntStream.range(1, 2).toArray(), s -> s.substream(1), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(0), IntStream.range(1, 101).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(10), IntStream.range(11, 101).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(100), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(200), EMPTY_INT_ARRAY); + } + + public void testLimit() { + assertCountSum(IntStream.range(0, 0).limit(4).boxed(), 0, 0); + assertCountSum(IntStream.range(1, 3).limit(4).boxed(), 2, 3); + assertCountSum(IntStream.range(1, 5).limit(4).boxed(), 4, 10); + assertCountSum(IntStream.range(1, 9).limit(4).boxed(), 4, 10); + + assertCountSum(IntStream.range(0, 0).parallel().limit(4).boxed(), 0, 0); + assertCountSum(IntStream.range(1, 3).parallel().limit(4).boxed(), 2, 3); + assertCountSum(IntStream.range(1, 5).parallel().limit(4).boxed(), 4, 10); + assertCountSum(IntStream.range(1, 9).parallel().limit(4).boxed(), 4, 10); + + exerciseOps(EMPTY_INT_ARRAY, s -> s.limit(0), EMPTY_INT_ARRAY); + exerciseOps(EMPTY_INT_ARRAY, s -> s.limit(10), EMPTY_INT_ARRAY); + + exerciseOps(IntStream.range(1, 2).toArray(), s -> s.limit(0), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 2).toArray(), s -> s.limit(1), IntStream.range(1, 2).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.limit(0), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.limit(10), IntStream.range(1, 11).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.limit(10).limit(10), IntStream.range(1, 11).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.limit(100), IntStream.range(1, 101).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.limit(100).limit(10), IntStream.range(1, 11).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.limit(200), IntStream.range(1, 101).toArray()); + } + + public void testSkipLimit() { + exerciseOps(EMPTY_INT_ARRAY, s -> s.substream(0).limit(0), EMPTY_INT_ARRAY); + exerciseOps(EMPTY_INT_ARRAY, s -> s.substream(0).limit(10), EMPTY_INT_ARRAY); + exerciseOps(EMPTY_INT_ARRAY, s -> s.substream(10).limit(0), EMPTY_INT_ARRAY); + exerciseOps(EMPTY_INT_ARRAY, s -> s.substream(10).limit(10), EMPTY_INT_ARRAY); + + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(0).limit(100), IntStream.range(1, 101).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(0).limit(10), IntStream.range(1, 11).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(0).limit(0), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(10).limit(100), IntStream.range(11, 101).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(10).limit(10), IntStream.range(11, 21).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(10).limit(0), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(100).limit(100), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(100).limit(10), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(100).limit(0), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(200).limit(100), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(200).limit(10), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(200).limit(0), EMPTY_INT_ARRAY); + } + + public void testSlice() { + exerciseOps(EMPTY_INT_ARRAY, s -> s.substream(0, 0), EMPTY_INT_ARRAY); + exerciseOps(EMPTY_INT_ARRAY, s -> s.substream(10, 10), EMPTY_INT_ARRAY); + + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(0, 100), IntStream.range(1, 101).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(0, 10), IntStream.range(1, 11).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(0, 0), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(10, 110), IntStream.range(11, 101).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(10, 20), IntStream.range(11, 21).toArray()); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(10, 10), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(100, 200), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(100, 110), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(100, 100), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(200, 300), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(200, 210), EMPTY_INT_ARRAY); + exerciseOps(IntStream.range(1, 101).toArray(), s -> s.substream(200, 200), EMPTY_INT_ARRAY); + } + + private int sliceSize(int dataSize, int skip, int limit) { + int size = Math.max(0, dataSize - skip); + if (limit >= 0) + size = Math.min(size, limit); + return size; + } + + private int sliceSize(int dataSize, int skip) { + return Math.max(0, dataSize - skip); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testSkipOps(String name, TestData.OfInt data) { + List skips = sizes(data.size()); + + for (int s : skips) { + Collection sr = exerciseOps(data, st -> st.substream(s)); + assertEquals(sr.size(), sliceSize(data.size(), s)); + + sr = exerciseOps(data, st -> st.substream(s).substream(s / 2)); + assertEquals(sr.size(), sliceSize(sliceSize(data.size(), s), s / 2)); + } + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testSkipLimitOps(String name, TestData.OfInt data) { + List skips = sizes(data.size()); + List limits = skips; + + for (int s : skips) { + for (int limit : limits) { + Collection sr = exerciseOps(data, st -> st.substream(s).limit(limit)); + assertEquals(sr.size(), sliceSize(sliceSize(data.size(), s), 0, limit)); + + sr = exerciseOps(data, st -> st.substream(s, limit+s)); + assertEquals(sr.size(), sliceSize(data.size(), s, limit)); + } + } + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testLimitOps(String name, TestData.OfInt data) { + List limits = sizes(data.size()); + + for (int limit : limits) { + Collection sr = exerciseOps(data, st -> st.limit(limit)); + assertEquals(sr.size(), sliceSize(data.size(), 0, limit)); + + sr = exerciseOps(data, st -> st.limit(limit).limit(limit / 2)); + assertEquals(sr.size(), sliceSize(sliceSize(data.size(), 0, limit), 0, limit / 2)); + } + } + + public void testLimitSort() { + exerciseOps(IntStream.range(1, 101).map(i -> 101 - i).toArray(), s -> s.limit(10).sorted()); + } + + @Test(groups = { "serialization-hostile" }) + public void testLimitShortCircuit() { + for (int l : Arrays.asList(0, 10)) { + AtomicInteger ai = new AtomicInteger(); + IntStream.range(1, 101) + .peek(i -> ai.getAndIncrement()) + .limit(l).toArray(); + // For the case of a zero limit, one element will get pushed through the sink chain + assertEquals(ai.get(), l, "tee block was called too many times"); + } + } + + public void testSkipParallel() { + int[] l = IntStream.range(1, 1001).parallel().substream(200).limit(200).sequential().toArray(); + assertEquals(l.length, 200); + assertEquals(l[l.length - 1], 400); + } + + public void testLimitParallel() { + int[] l = IntStream.range(1, 1001).parallel().limit(500).sequential().toArray(); + assertEquals(l.length, 500); + assertEquals(l[l.length - 1], 500); + } + + private List sizes(int size) { + if (size < 4) { + return Arrays.asList(0, 1, 2, 3, 4, 6); + } + else { + return Arrays.asList(0, 1, size / 2, size - 1, size, size + 1, 2 * size); + } + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntUniqOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntUniqOpTest.java new file mode 100644 index 00000000000..8205d4d510d --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntUniqOpTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.Collection; +import java.util.stream.*; + +import org.testng.annotations.Test; + +import static java.util.stream.LambdaTestHelpers.assertCountSum; +import static java.util.stream.LambdaTestHelpers.assertUnique; + +/** + * UniqOpTest + */ +@Test +public class IntUniqOpTest extends OpTestCase { + + public void testUniqOp() { + assertCountSum(IntStream.generate(() -> 0).limit(10).distinct().boxed(), 1, 0); + assertCountSum(IntStream.generate(() -> 1).limit(10).distinct().boxed(), 1, 1); + assertCountSum(IntStream.range(0, 0).distinct().boxed(), 0, 0); + assertCountSum(IntStream.range(1, 11).distinct().boxed(), 10, 55); + assertCountSum(IntStream.range(1, 11).distinct().boxed(), 10, 55); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testOp(String name, TestData.OfInt data) { + Collection result = exerciseOps(data, s -> s.distinct().boxed()); + + assertUnique(result); + if (data.size() > 0) + assertTrue(result.size() > 0); + else + assertTrue(result.size() == 0); + assertTrue(result.size() <= data.size()); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testOpSorted(String name, TestData.OfInt data) { + Collection result = withData(data). + stream(s -> s.sorted().distinct().boxed()). + parallelEqualityAsserter(LambdaTestHelpers::assertContentsUnordered). + exercise(); + + assertUnique(result); + if (data.size() > 0) + assertTrue(result.size() > 0); + else + assertTrue(result.size() == 0); + assertTrue(result.size() <= data.size()); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java new file mode 100644 index 00000000000..fc8fa2a6763 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.LongConsumer; +import java.util.stream.Collectors; +import java.util.stream.LongStream; + +import static org.testng.Assert.assertEquals; + +@Test +public class LongPrimitiveOpsTests { + + public void testSum() { + long sum = LongStream.range(1, 10).filter(i -> i % 2 == 0).sum(); + assertEquals(sum, 20); + } + + public void testMap() { + long sum = LongStream.range(1, 10).filter(i -> i % 2 == 0).map(i -> i * 2).sum(); + assertEquals(sum, 40); + } + + public void testParSum() { + long sum = LongStream.range(1, 10).parallel().filter(i -> i % 2 == 0).sum(); + assertEquals(sum, 20); + } + + @Test(groups = { "serialization-hostile" }) + public void testTee() { + long[] teeSum = new long[1]; + long sum = LongStream.range(1, 10).filter(i -> i % 2 == 0).peek(i -> { teeSum[0] = teeSum[0] + i; }).sum(); + assertEquals(teeSum[0], sum); + } + + @Test(groups = { "serialization-hostile" }) + public void testForEach() { + long[] sum = new long[1]; + LongStream.range(1, 10).filter(i -> i % 2 == 0).forEach(i -> { sum[0] = sum[0] + i; }); + assertEquals(sum[0], 20); + } + + @Test(groups = { "serialization-hostile" }) + public void testParForEach() { + AtomicLong ai = new AtomicLong(0); + LongStream.range(1, 10).parallel().filter(i -> i % 2 == 0).forEach(ai::addAndGet); + assertEquals(ai.get(), 20); + } + + public void testBox() { + List l = LongStream.range(1, 10).parallel().boxed().collect(Collectors.toList()); + long sum = l.stream().reduce(0L, (a, b) -> a + b); + assertEquals(sum, 45); + } + + public void testUnBox() { + long sum = Arrays.asList(1L, 2L, 3L, 4L, 5L).stream().mapToLong(i -> (long) i).sum(); + assertEquals(sum, 15); + } + + public void testToArray() { + { + long[] array = LongStream.range(1, 10).map(i -> i * 2).toArray(); + assertEquals(array, new long[]{2, 4, 6, 8, 10, 12, 14, 16, 18}); + } + + { + long[] array = LongStream.range(1, 10).parallel().map(i -> i * 2).toArray(); + assertEquals(array, new long[]{2, 4, 6, 8, 10, 12, 14, 16, 18}); + } + } + + public void testSort() { + Random r = new Random(); + + long[] content = LongStream.generate(() -> r.nextLong()).limit(10).toArray(); + long[] sortedContent = content.clone(); + Arrays.sort(sortedContent); + + { + long[] array = Arrays.stream(content).sorted().toArray(); + assertEquals(array, sortedContent); + } + + { + long[] array = Arrays.stream(content).parallel().sorted().toArray(); + assertEquals(array, sortedContent); + } + } + + public void testSortSort() { + Random r = new Random(); + + long[] content = LongStream.generate(() -> r.nextLong()).limit(10).toArray(); + long[] sortedContent = content.clone(); + Arrays.sort(sortedContent); + + { + long[] array = Arrays.stream(content).sorted().sorted().toArray(); + assertEquals(array, sortedContent); + } + + { + long[] array = Arrays.stream(content).parallel().sorted().sorted().toArray(); + assertEquals(array, sortedContent); + } + } + + public void testSequential() { + + long[] expected = LongStream.range(1, 1000).toArray(); + + class AssertingConsumer implements LongConsumer { + private final long[] array; + int offset; + + AssertingConsumer(long[] array) { + this.array = array; + } + + @Override + public void accept(long value) { + assertEquals(array[offset++], value); + } + + public int getCount() { return offset; } + } + + { + AssertingConsumer consumer = new AssertingConsumer(expected); + LongStream.range(1, 1000).sequential().forEach(consumer); + assertEquals(expected.length, consumer.getCount()); + } + + { + AssertingConsumer consumer = new AssertingConsumer(expected); + LongStream.range(1, 1000).parallel().sequential().forEach(consumer); + assertEquals(expected.length, consumer.getCount()); + } + } + + public void testLimit() { + long[] expected = LongStream.range(1, 10).toArray(); + + { + long[] actual = LongStream.iterate(1, i -> i + 1).limit(9).toArray(); + Assert.assertTrue(Arrays.equals(expected, actual)); + } + + { + long[] actual = LongStream.range(1, 100).parallel().limit(9).toArray(); + Assert.assertTrue(Arrays.equals(expected, actual)); + } + } + +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MapOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MapOpTest.java new file mode 100644 index 00000000000..9225ddd9223 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MapOpTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.annotations.Test; + +import java.util.function.DoubleToIntFunction; +import java.util.function.DoubleToLongFunction; +import java.util.function.Function; +import java.util.function.IntToDoubleFunction; +import java.util.function.IntToLongFunction; +import java.util.function.LongToDoubleFunction; +import java.util.function.LongToIntFunction; +import java.util.function.ToDoubleFunction; +import java.util.function.ToIntFunction; +import java.util.function.ToLongFunction; +import java.util.stream.*; + +import static java.util.stream.LambdaTestHelpers.*; + +/** + * MapOpTest + * + * @author Brian Goetz + */ +@Test +public class MapOpTest extends OpTestCase { + + public void testMap() { + assertCountSum(countTo(0).stream().map(mId), 0, 0); + assertCountSum(countTo(10).stream().map(mId), 10, 55); + assertCountSum(countTo(10).stream().map(mZero), 10, 0); + assertCountSum(countTo(0).stream().map(mDoubler), 0, 0); + assertCountSum(countTo(10).stream().map(mDoubler), 10, 110); + assertCountSum(countTo(10).stream().map(mDoubler).map(mDoubler), 10, 220); + + exerciseOps(countTo(0), s -> s.map(LambdaTestHelpers.identity()), countTo(0)); + exerciseOps(countTo(1000), s -> s.map(LambdaTestHelpers.identity()), countTo(1000)); + // @@@ Force cast to integer so output is Stream rather an IntStream + // this just ensures that no warnings are logged about boxing + // when the result is compared with the output + exerciseOps(countTo(1000), s -> s.map(e -> (Integer) (1000 + e)), range(1001, 2000)); + } + + public void testEveryMapShape() { + assertCountSum(countTo(1000).stream() + .mapToInt(i -> i - 1) + .mapToObj(i -> i + 1) + .mapToLong(i -> i - 1) + .mapToObj(i -> i + 1) + .mapToDouble(i -> i - 1) + .mapToObj(i -> i + 1) + .mapToInt(i -> (int) (double) i) + .mapToLong(i -> i) + .mapToDouble(i -> i) + .mapToLong(i -> (long) i) + .mapToInt(i -> (int) i) + .mapToObj(i -> i), + 1000, countTo(1000).stream().mapToInt(i -> i).sum()); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + exerciseOpsInt(data, s -> s.map(mId), s -> s.map(e -> e), s -> s.map(e -> e), s -> s.map(e -> e)); + exerciseOpsInt(data, s -> s.map(mZero), s -> s.map(e -> 0), s -> s.map(e -> 0), s -> s.map(e -> 0)); + exerciseOpsInt(data, s -> s.map(mDoubler), s -> s.map(e -> 2*e), s -> s.map(e -> 2*e), s -> s.map(e -> 2*e)); + exerciseOpsInt(data, s -> s.map(LambdaTestHelpers.compose(mId, mDoubler)), s -> s.map(e -> 2*e), s -> s.map(e -> 2*e), s -> s.map(e -> 2*e)); + exerciseOpsInt(data, s -> s.map(LambdaTestHelpers.compose(mDoubler, mDoubler)), s -> s.map(e -> 4*e), s -> s.map(e -> 4*e), s -> s.map(e -> 4*e)); + exerciseOps(data, s -> s.mapToInt(i -> i)); + exerciseOps(data, s -> s.mapToLong(i -> i)); + exerciseOps(data, s -> s.mapToDouble(i -> i)); + } + + // + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOps(String name, TestData.OfInt data) { + exerciseOps(data, s -> s.mapToObj(i -> i)); + exerciseOps(data, s -> s.map(i -> 0)); + exerciseOps(data, s -> s.map(i -> i * 2)); + exerciseOps(data, s -> s.longs()); + exerciseOps(data, s -> s.doubles()); + exerciseOps(data, s -> s.boxed()); + exerciseOps(data, s -> s.mapToObj(Integer::toString)); + exerciseOps(data, s -> s.mapToLong(i -> i)); + exerciseOps(data, s -> s.mapToDouble(i -> i)); + } + + // + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOps(String name, TestData.OfLong data) { + exerciseOps(data, s -> s.mapToObj(i -> i)); + exerciseOps(data, s -> s.map(i -> 0L)); + exerciseOps(data, s -> s.map(i -> i * 2L)); + exerciseOps(data, s -> s.doubles()); + exerciseOps(data, s -> s.boxed()); + exerciseOps(data, s -> s.mapToObj(e -> Long.toString(e))); + exerciseOps(data, s -> s.mapToInt(i -> (int) i)); + exerciseOps(data, s -> s.mapToDouble(i -> i)); + } + + // + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOps(String name, TestData.OfDouble data) { + exerciseOps(data, s -> s.mapToObj(i -> i)); + exerciseOps(data, s -> s.map(i -> 0.0)); + exerciseOps(data, s -> s.map(i -> i * 2.0)); + exerciseOps(data, s -> s.boxed()); + exerciseOps(data, s -> s.mapToObj(e -> Double.toString(e))); + exerciseOps(data, s -> s.mapToLong(i -> (long) i)); + exerciseOps(data, s -> s.mapToInt(i -> (int) i)); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MatchOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MatchOpTest.java new file mode 100644 index 00000000000..a6516118915 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MatchOpTest.java @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.PrimitiveIterator; +import java.util.function.DoublePredicate; +import java.util.function.DoubleSupplier; +import java.util.function.Function; +import java.util.function.IntPredicate; +import java.util.function.IntSupplier; +import java.util.function.LongPredicate; +import java.util.function.LongSupplier; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.DoubleStream; +import java.util.stream.DoubleStreamTestDataProvider; +import java.util.stream.IntStream; +import java.util.stream.IntStreamTestDataProvider; +import java.util.stream.LongStream; +import java.util.stream.LongStreamTestDataProvider; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.StreamTestDataProvider; +import java.util.stream.TestData; + +import org.testng.annotations.Test; + +import static java.util.stream.LambdaTestHelpers.countTo; +import static java.util.stream.LambdaTestHelpers.dpEven; +import static java.util.stream.LambdaTestHelpers.dpFalse; +import static java.util.stream.LambdaTestHelpers.dpOdd; +import static java.util.stream.LambdaTestHelpers.dpTrue; +import static java.util.stream.LambdaTestHelpers.ipEven; +import static java.util.stream.LambdaTestHelpers.ipFalse; +import static java.util.stream.LambdaTestHelpers.ipOdd; +import static java.util.stream.LambdaTestHelpers.ipTrue; +import static java.util.stream.LambdaTestHelpers.lpEven; +import static java.util.stream.LambdaTestHelpers.lpFalse; +import static java.util.stream.LambdaTestHelpers.lpOdd; +import static java.util.stream.LambdaTestHelpers.lpTrue; +import static java.util.stream.LambdaTestHelpers.pEven; +import static java.util.stream.LambdaTestHelpers.pFalse; +import static java.util.stream.LambdaTestHelpers.pOdd; +import static java.util.stream.LambdaTestHelpers.pTrue; + +/** + * MatchOpTest + * + * @author Brian Goetz + */ +@Test +public class MatchOpTest extends OpTestCase { + private enum Kind { ANY, ALL, NONE } + + @SuppressWarnings("unchecked") + private static final Predicate[] INTEGER_PREDICATES + = (Predicate[]) new Predicate[]{pTrue, pFalse, pEven, pOdd}; + + @SuppressWarnings({"serial", "rawtypes"}) + private final Map kinds + = new HashMap, Function, Boolean>>>() {{ + put(Kind.ANY, p -> s -> s.anyMatch(p)); + put(Kind.ALL, p -> s -> s.allMatch(p)); + put(Kind.NONE, p -> s -> s.noneMatch(p)); + }}; + + @SuppressWarnings("unchecked") + private Map, Function, Boolean>>> kinds() { + return (Map, Function, Boolean>>>) kinds; + } + + private void assertPredicates(List source, Kind kind, Predicate[] predicates, boolean... answers) { + for (int i = 0; i < predicates.length; i++) { + boolean match = this.kinds().get(kind).apply(predicates[i]).apply(source.stream()); + assertEquals(answers[i], match, kind.toString() + predicates[i].toString()); + } + } + + public void testStreamMatches() { + assertPredicates(countTo(0), Kind.ANY, INTEGER_PREDICATES, false, false, false, false); + assertPredicates(countTo(0), Kind.ALL, INTEGER_PREDICATES, true, true, true, true); + assertPredicates(countTo(0), Kind.NONE, INTEGER_PREDICATES, true, true, true, true); + + assertPredicates(countTo(1), Kind.ANY, INTEGER_PREDICATES, true, false, false, true); + assertPredicates(countTo(1), Kind.ALL, INTEGER_PREDICATES, true, false, false, true); + assertPredicates(countTo(1), Kind.NONE, INTEGER_PREDICATES, false, true, true, false); + + assertPredicates(countTo(5), Kind.ANY, INTEGER_PREDICATES, true, false, true, true); + assertPredicates(countTo(5), Kind.ALL, INTEGER_PREDICATES, true, false, false, false); + assertPredicates(countTo(5), Kind.NONE, INTEGER_PREDICATES, false, true, false, false); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testStream(String name, TestData.OfRef data) { + for (Predicate p : INTEGER_PREDICATES) { + for (Kind kind : Kind.values()) { + exerciseTerminalOps(data, this.kinds().get(kind).apply(p)); + exerciseTerminalOps(data, s -> s.filter(pFalse), this.kinds().get(kind).apply(p)); + exerciseTerminalOps(data, s -> s.filter(pEven), this.kinds().get(kind).apply(p)); + } + } + } + + public void testInfinite() { + class CycleSupplier implements Supplier { + final Iterable source; + Iterator i = Collections.emptyIterator(); + + CycleSupplier(Iterable source) { + this.source = source; + } + + @Override + public T get() { + if (!i.hasNext()) { + i = source.iterator(); + } + return i.next(); + } + } + + assertFalse(Stream.generate(new CycleSupplier<>(Arrays.asList(1, 2, 3, 4))).allMatch(i -> i > 3)); + assertTrue(Stream.generate(new CycleSupplier<>(Arrays.asList(1, 2, 3, 4))).anyMatch(i -> i > 3)); + assertFalse(Stream.generate(new CycleSupplier<>(Arrays.asList(1, 2, 3, 4))).noneMatch(i -> i > 3)); + assertFalse(Stream.generate(new CycleSupplier<>(Arrays.asList(1, 2, 3, 4))).parallel().allMatch(i -> i > 3)); + assertTrue(Stream.generate(new CycleSupplier<>(Arrays.asList(1, 2, 3, 4))).parallel().anyMatch(i -> i > 3)); + assertFalse(Stream.generate(new CycleSupplier<>(Arrays.asList(1, 2, 3, 4))).parallel().noneMatch(i -> i > 3)); + } + + // + + private static final IntPredicate[] INT_PREDICATES + = new IntPredicate[]{ipTrue, ipFalse, ipEven, ipOdd}; + + @SuppressWarnings("serial") + private final Map>> intKinds + = new HashMap>>() {{ + put(Kind.ANY, p -> s -> s.anyMatch(p)); + put(Kind.ALL, p -> s -> s.allMatch(p)); + put(Kind.NONE, p -> s -> s.noneMatch(p)); + }}; + + private void assertIntPredicates(Supplier source, Kind kind, IntPredicate[] predicates, boolean... answers) { + for (int i = 0; i < predicates.length; i++) { + boolean match = intKinds.get(kind).apply(predicates[i]).apply(source.get()); + assertEquals(answers[i], match, kind.toString() + predicates[i].toString()); + } + } + + public void testIntStreamMatches() { + assertIntPredicates(() -> IntStream.range(0, 0), Kind.ANY, INT_PREDICATES, false, false, false, false); + assertIntPredicates(() -> IntStream.range(0, 0), Kind.ALL, INT_PREDICATES, true, true, true, true); + assertIntPredicates(() -> IntStream.range(0, 0), Kind.NONE, INT_PREDICATES, true, true, true, true); + + assertIntPredicates(() -> IntStream.range(1, 2), Kind.ANY, INT_PREDICATES, true, false, false, true); + assertIntPredicates(() -> IntStream.range(1, 2), Kind.ALL, INT_PREDICATES, true, false, false, true); + assertIntPredicates(() -> IntStream.range(1, 2), Kind.NONE, INT_PREDICATES, false, true, true, false); + + assertIntPredicates(() -> IntStream.range(1, 6), Kind.ANY, INT_PREDICATES, true, false, true, true); + assertIntPredicates(() -> IntStream.range(1, 6), Kind.ALL, INT_PREDICATES, true, false, false, false); + assertIntPredicates(() -> IntStream.range(1, 6), Kind.NONE, INT_PREDICATES, false, true, false, false); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntStream(String name, TestData.OfInt data) { + for (IntPredicate p : INT_PREDICATES) + for (Kind kind : Kind.values()) { + exerciseTerminalOps(data, intKinds.get(kind).apply(p)); + exerciseTerminalOps(data, s -> s.filter(ipFalse), intKinds.get(kind).apply(p)); + exerciseTerminalOps(data, s -> s.filter(ipEven), intKinds.get(kind).apply(p)); + } + } + + public void testIntInfinite() { + class CycleSupplier implements IntSupplier { + final Supplier source; + PrimitiveIterator.OfInt i = null; + + CycleSupplier(Supplier source) { + this.source = source; + } + + @Override + public int getAsInt() { + if (i == null || !i.hasNext()) { + i = source.get(); + } + return i.nextInt(); + } + } + + Supplier source = () -> Arrays.stream(new int[]{1, 2, 3, 4}).iterator(); + + assertFalse(IntStream.generate(new CycleSupplier(source)).allMatch(i -> i > 3)); + assertTrue(IntStream.generate(new CycleSupplier(source)).anyMatch(i -> i > 3)); + assertFalse(IntStream.generate(new CycleSupplier(source)).noneMatch(i -> i > 3)); + assertFalse(IntStream.generate(new CycleSupplier(source)).parallel().allMatch(i -> i > 3)); + assertTrue(IntStream.generate(new CycleSupplier(source)).parallel().anyMatch(i -> i > 3)); + assertFalse(IntStream.generate(new CycleSupplier(source)).parallel().noneMatch(i -> i > 3)); + } + + // + + private static final LongPredicate[] LONG_PREDICATES + = new LongPredicate[]{lpTrue, lpFalse, lpEven, lpOdd}; + + @SuppressWarnings("serial") + private final Map>> longKinds + = new HashMap>>() {{ + put(Kind.ANY, p -> s -> s.anyMatch(p)); + put(Kind.ALL, p -> s -> s.allMatch(p)); + put(Kind.NONE, p -> s -> s.noneMatch(p)); + }}; + + private void assertLongPredicates(Supplier source, Kind kind, LongPredicate[] predicates, boolean... answers) { + for (int i = 0; i < predicates.length; i++) { + boolean match = longKinds.get(kind).apply(predicates[i]).apply(source.get()); + assertEquals(answers[i], match, kind.toString() + predicates[i].toString()); + } + } + + public void testLongStreamMatches() { + assertLongPredicates(() -> LongStream.range(0, 0), Kind.ANY, LONG_PREDICATES, false, false, false, false); + assertLongPredicates(() -> LongStream.range(0, 0), Kind.ALL, LONG_PREDICATES, true, true, true, true); + assertLongPredicates(() -> LongStream.range(0, 0), Kind.NONE, LONG_PREDICATES, true, true, true, true); + + assertLongPredicates(() -> LongStream.range(1, 2), Kind.ANY, LONG_PREDICATES, true, false, false, true); + assertLongPredicates(() -> LongStream.range(1, 2), Kind.ALL, LONG_PREDICATES, true, false, false, true); + assertLongPredicates(() -> LongStream.range(1, 2), Kind.NONE, LONG_PREDICATES, false, true, true, false); + + assertLongPredicates(() -> LongStream.range(1, 6), Kind.ANY, LONG_PREDICATES, true, false, true, true); + assertLongPredicates(() -> LongStream.range(1, 6), Kind.ALL, LONG_PREDICATES, true, false, false, false); + assertLongPredicates(() -> LongStream.range(1, 6), Kind.NONE, LONG_PREDICATES, false, true, false, false); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongStream(String name, TestData.OfLong data) { + for (LongPredicate p : LONG_PREDICATES) + for (Kind kind : Kind.values()) { + exerciseTerminalOps(data, longKinds.get(kind).apply(p)); + exerciseTerminalOps(data, s -> s.filter(lpFalse), longKinds.get(kind).apply(p)); + exerciseTerminalOps(data, s -> s.filter(lpEven), longKinds.get(kind).apply(p)); + } + } + + public void testLongInfinite() { + class CycleSupplier implements LongSupplier { + final Supplier source; + PrimitiveIterator.OfLong i = null; + + CycleSupplier(Supplier source) { + this.source = source; + } + + @Override + public long getAsLong() { + if (i == null || !i.hasNext()) { + i = source.get(); + } + return i.nextLong(); + } + } + + Supplier source = () -> Arrays.stream(new long[]{1, 2, 3, 4}).iterator(); + + assertFalse(LongStream.generate(new CycleSupplier(source)).allMatch(i -> i > 3)); + assertTrue(LongStream.generate(new CycleSupplier(source)).anyMatch(i -> i > 3)); + assertFalse(LongStream.generate(new CycleSupplier(source)).noneMatch(i -> i > 3)); + assertFalse(LongStream.generate(new CycleSupplier(source)).parallel().allMatch(i -> i > 3)); + assertTrue(LongStream.generate(new CycleSupplier(source)).parallel().anyMatch(i -> i > 3)); + assertFalse(LongStream.generate(new CycleSupplier(source)).parallel().noneMatch(i -> i > 3)); + } + + // + + private static final DoublePredicate[] DOUBLE_PREDICATES + = new DoublePredicate[]{dpTrue, dpFalse, dpEven, dpOdd}; + + @SuppressWarnings("serial") + private final Map>> doubleKinds + = new HashMap>>() {{ + put(Kind.ANY, p -> s -> s.anyMatch(p)); + put(Kind.ALL, p -> s -> s.allMatch(p)); + put(Kind.NONE, p -> s -> s.noneMatch(p)); + }}; + + private void assertDoublePredicates(Supplier source, Kind kind, DoublePredicate[] predicates, boolean... answers) { + for (int i = 0; i < predicates.length; i++) { + boolean match = doubleKinds.get(kind).apply(predicates[i]).apply(source.get()); + assertEquals(answers[i], match, kind.toString() + predicates[i].toString()); + } + } + + public void testDoubleStreamMatches() { + assertDoublePredicates(() -> LongStream.range(0, 0).doubles(), Kind.ANY, DOUBLE_PREDICATES, false, false, false, false); + assertDoublePredicates(() -> LongStream.range(0, 0).doubles(), Kind.ALL, DOUBLE_PREDICATES, true, true, true, true); + assertDoublePredicates(() -> LongStream.range(0, 0).doubles(), Kind.NONE, DOUBLE_PREDICATES, true, true, true, true); + + assertDoublePredicates(() -> LongStream.range(1, 2).doubles(), Kind.ANY, DOUBLE_PREDICATES, true, false, false, true); + assertDoublePredicates(() -> LongStream.range(1, 2).doubles(), Kind.ALL, DOUBLE_PREDICATES, true, false, false, true); + assertDoublePredicates(() -> LongStream.range(1, 2).doubles(), Kind.NONE, DOUBLE_PREDICATES, false, true, true, false); + + assertDoublePredicates(() -> LongStream.range(1, 6).doubles(), Kind.ANY, DOUBLE_PREDICATES, true, false, true, true); + assertDoublePredicates(() -> LongStream.range(1, 6).doubles(), Kind.ALL, DOUBLE_PREDICATES, true, false, false, false); + assertDoublePredicates(() -> LongStream.range(1, 6).doubles(), Kind.NONE, DOUBLE_PREDICATES, false, true, false, false); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleStream(String name, TestData.OfDouble data) { + for (DoublePredicate p : DOUBLE_PREDICATES) + for (Kind kind : Kind.values()) { + exerciseTerminalOps(data, doubleKinds.get(kind).apply(p)); + exerciseTerminalOps(data, s -> s.filter(dpFalse), doubleKinds.get(kind).apply(p)); + exerciseTerminalOps(data, s -> s.filter(dpEven), doubleKinds.get(kind).apply(p)); + } + } + + public void testDoubleInfinite() { + class CycleSupplier implements DoubleSupplier { + final Supplier source; + PrimitiveIterator.OfDouble i = null; + + CycleSupplier(Supplier source) { + this.source = source; + } + + @Override + public double getAsDouble() { + if (i == null || !i.hasNext()) { + i = source.get(); + } + return i.nextDouble(); + } + } + + Supplier source = () -> Arrays.stream(new double[]{1, 2, 3, 4}).iterator(); + + assertFalse(DoubleStream.generate(new CycleSupplier(source)).allMatch(i -> i > 3)); + assertTrue(DoubleStream.generate(new CycleSupplier(source)).anyMatch(i -> i > 3)); + assertFalse(DoubleStream.generate(new CycleSupplier(source)).noneMatch(i -> i > 3)); + assertFalse(DoubleStream.generate(new CycleSupplier(source)).parallel().allMatch(i -> i > 3)); + assertTrue(DoubleStream.generate(new CycleSupplier(source)).parallel().anyMatch(i -> i > 3)); + assertFalse(DoubleStream.generate(new CycleSupplier(source)).parallel().noneMatch(i -> i > 3)); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MinMaxTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MinMaxTest.java new file mode 100644 index 00000000000..6ae36097dbc --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/MinMaxTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.OptionalLong; +import java.util.stream.*; + +import org.testng.annotations.Test; + +import static java.util.stream.LambdaTestHelpers.countTo; + +/** + * MinMaxTest + * + * @author Brian Goetz + */ +@Test +public class MinMaxTest extends OpTestCase { + public void testMinMax() { + assertTrue(!countTo(0).stream().min(Integer::compare).isPresent()); + assertTrue(!countTo(0).stream().max(Integer::compare).isPresent()); + assertEquals(1, (int) countTo(1000).stream().min(Integer::compare).get()); + assertEquals(1000, (int) countTo(1000).stream().max(Integer::compare).get()); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + exerciseTerminalOps(data, s -> s.min(Integer::compare)); + exerciseTerminalOps(data, s -> s.max(Integer::compare)); + } + + public void testIntMinMax() { + assertEquals(IntStream.empty().min(), OptionalInt.empty()); + assertEquals(IntStream.empty().max(), OptionalInt.empty()); + assertEquals(1, IntStream.range(1, 1001).min().getAsInt()); + assertEquals(1000, IntStream.range(1, 1001).max().getAsInt()); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOps(String name, TestData.OfInt data) { + exerciseTerminalOps(data, s -> s.min()); + exerciseTerminalOps(data, s -> s.max()); + } + + public void testLongMinMax() { + assertEquals(LongStream.empty().min(), OptionalLong.empty()); + assertEquals(LongStream.empty().max(), OptionalLong.empty()); + assertEquals(1, LongStream.range(1, 1001).min().getAsLong()); + assertEquals(1000, LongStream.range(1, 1001).max().getAsLong()); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOps(String name, TestData.OfLong data) { + exerciseTerminalOps(data, s -> s.min()); + exerciseTerminalOps(data, s -> s.max()); + } + + public void testDoubleMinMax() { + assertEquals(DoubleStream.empty().min(), OptionalDouble.empty()); + assertEquals(DoubleStream.empty().max(), OptionalDouble.empty()); + assertEquals(1.0, LongStream.range(1, 1001).doubles().min().getAsDouble()); + assertEquals(1000.0, LongStream.range(1, 1001).doubles().max().getAsDouble()); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOps(String name, TestData.OfDouble data) { + exerciseTerminalOps(data, s -> s.min()); + exerciseTerminalOps(data, s -> s.max()); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveAverageOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveAverageOpTest.java new file mode 100644 index 00000000000..82491e5a908 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveAverageOpTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.stream.*; + +import org.testng.annotations.Test; + +public class PrimitiveAverageOpTest extends OpTestCase { + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testOps(String name, TestData.OfInt data) { + exerciseTerminalOps(data, s -> s.average()); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testOps(String name, TestData.OfLong data) { + exerciseTerminalOps(data, s -> s.average()); + } + + // @@@ For Double depending on the input data the average algorithm may produce slightly + // different results for the sequential and parallel evaluation.results are within + // While the following works at the moment, it could change when double data, not cast from long + // values is introduced, or if the average/sum algorithm is modified. + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testOps(String name, TestData.OfDouble data) { + exerciseTerminalOps(data, s -> s.average()); + } + +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveSumTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveSumTest.java new file mode 100644 index 00000000000..98c93513d05 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveSumTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.stream.*; + +import org.testng.annotations.Test; + +public class PrimitiveSumTest extends OpTestCase { + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testOps(String name, TestData.OfInt data) { + exerciseTerminalOps(data, s -> s.sum()); + + withData(data). + terminal(s -> (long) s.sum()). + expectedResult(data.stream().longs().reduce(0, LambdaTestHelpers.lrPlus)). + exercise(); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testOps(String name, TestData.OfLong data) { + exerciseTerminalOps(data, s -> s.sum()); + + withData(data). + terminal(s -> s.sum()). + expectedResult(data.stream().reduce(0, LambdaTestHelpers.lrPlus)). + exercise(); + } + + // @@@ For Double depending on the input data the average algorithm may produce slightly + // different results for the sequential and parallel evaluation.results are within + // While the following works at the moment, it could change when double data, not cast from long + // values is introduced, or if the sum algorithm is modified. + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testOps(String name, TestData.OfDouble data) { + exerciseTerminalOps(data, s -> s.sum()); + + withData(data). + terminal(s -> s.sum()). + expectedResult(data.stream().reduce(0, LambdaTestHelpers.drPlus)). + exercise(); + } +} + diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/RangeTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/RangeTest.java new file mode 100644 index 00000000000..182b98c50c1 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/RangeTest.java @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.TestData; + +import org.testng.annotations.Test; + +/** + * Primitive range tests + * + * @author Brian Goetz + */ +@Test +public class RangeTest extends OpTestCase { + + public void testInfiniteRangeFindFirst() { + Integer first = Stream.iterate(0, i -> i + 1).filter(i -> i > 10000).findFirst().get(); + assertEquals(first, Stream.iterate(0, i -> i + 1).parallel().filter(i -> i > 10000).findFirst().get()); + + // Limit is required to transform the infinite stream to a finite stream + // since the exercising requires a finite stream + withData(TestData.Factory.ofSupplier( + "", () -> Stream.iterate(0, i -> i + 1).filter(i -> i > 10000).limit(20000))). + terminal(s->s.findFirst()).expectedResult(Optional.of(10001)).exercise(); + } + + // + + public void testIntRangeErrors() { + for (int start : Arrays.asList(1, 10, -1, -10)) { + for (int end : Arrays.asList(1, 10, -1, -10)) { + for (int step : Arrays.asList(0, 1, -1, Integer.MAX_VALUE, Integer.MIN_VALUE)) { + if (step > 0) + executeAndNoCatch(() -> IntStream.range(start, end, step)); + else + executeAndCatch(() -> IntStream.range(start, end, step)); + } + } + } + } + + public void testIntRange() { + // Without step + for (int start : Arrays.asList(1, 10, -1, -10)) { + for (int end : Arrays.asList(1, 10, -1, -10)) { + int step = 1; + int size = (start < end) ? end - start : 0; + int[] exp = new int[size]; + if (start < end) { + for (int i = start, p = 0; i < end; i++, p++) { + exp[p] = i; + } + } + + int[] inc = IntStream.range(start, end).toArray(); + assertEquals(inc.length, size); + assertTrue(Arrays.equals(exp, inc)); + + withData(intRangeData(start, end, step)).stream(s -> s). + expectedResult(exp).exercise(); + } + } + + // With step + for (int start : Arrays.asList(1, 10, -1, -10)) { + for (int end : Arrays.asList(1, 10, -1, -10)) { + for (int step : Arrays.asList(1, -1, -2, 2)) { + if (step > 0) { + int d = end - start; + int size = (start < end) ? (d / step) + ((d % step == 0) ? 0 : 1) : 0; + int[] exp = new int[size]; + if (start < end) { + for (int i = start, p = 0; i < end; i += step, p++) { + exp[p] = i; + } + } + + int[] inc = IntStream.range(start, end, step).toArray(); + assertEquals(inc.length, size); + assertTrue(Arrays.equals(exp, inc)); + + withData(intRangeData(start, end, step)).stream(s -> s). + expectedResult(exp).exercise(); + } + } + } + } + } + + TestData.OfInt intRangeData(int start, int end, int step) { + return TestData.Factory.ofIntSupplier("int range", () -> IntStream.range(start, end, step)); + } + + public void tesIntRangeReduce() { + withData(intRangeData(0, 10000, 1)). + terminal(s -> s.reduce(0, Integer::sum)).exercise(); + } + + public void testIntInfiniteRangeLimit() { + withData(TestData.Factory.ofIntSupplier( + "int range", () -> IntStream.iterate(0, i -> i + 1).limit(10000))). + terminal(s -> s.reduce(0, Integer::sum)).exercise(); + } + + public void testIntInfiniteRangeFindFirst() { + int first = IntStream.iterate(0, i -> i + 1).filter(i -> i > 10000).findFirst().getAsInt(); + assertEquals(first, IntStream.iterate(0, i -> i + 1).parallel().filter(i -> i > 10000).findFirst().getAsInt()); + } + + // + + public void testLongRangeErrors() { + for (long start : Arrays.asList(1, 10, -1, -10)) { + for (long end : Arrays.asList(1, 10, -1, -10)) { + for (long step : Arrays.asList(0L, 1L, -1L, Long.MAX_VALUE, Long.MIN_VALUE)) { + if (step > 0) + executeAndNoCatch(() -> LongStream.range(start, end, step)); + else + executeAndCatch(() -> LongStream.range(start, end, step)); + } + } + } + } + + public void testLongRange() { + // Without step + for (long start : Arrays.asList(1, 1000, -1, -1000)) { + for (long end : Arrays.asList(1, 1000, -1, -1000)) { + long step = 1; + long size = start < end ? end - start : 0; + long[] exp = new long[(int) size]; + if (start < end) { + for (long i = start, p = 0; i < end; i++, p++) { + exp[(int) p] = i; + } + } + + long[] inc = LongStream.range(start, end).toArray(); + assertEquals(inc.length, size); + assertTrue(Arrays.equals(exp, inc)); + + withData(longRangeData(start, end, step)).stream(s -> s). + expectedResult(exp).exercise(); + } + } + + // With step + for (long start : Arrays.asList(1, 1000, -1, -1000)) { + for (long end : Arrays.asList(1, 1000, -1, -1000)) { + for (long step : Arrays.asList(1, -1, -2, 2)) { + if (step > 0) { + + long d = end - start; + long size = start < end ? (d / step) + ((d % step == 0) ? 0 : 1) : 0; + long[] exp = new long[(int) size]; + if (start < end) { + for (long i = start, p = 0; i < end; i += step, p++) { + exp[(int) p] = i; + } + } + + long[] inc = LongStream.range(start, end, step).toArray(); + assertEquals(inc.length, size); + assertTrue(Arrays.equals(exp, inc)); + + withData(longRangeData(start, end, step)).stream(s -> s). + expectedResult(exp).exercise(); + } + } + } + } + } + + TestData.OfLong longRangeData(long start, long end, long step) { + return TestData.Factory.ofLongSupplier("long range", () -> LongStream.range(start, end, step)); + } + + public void testLongRangeReduce() { + withData(longRangeData(0, 10000, 1)). + terminal(s -> s.reduce(0, Long::sum)).exercise(); + } + + public void testLongInfiniteRangeLimit() { + withData(TestData.Factory.ofLongSupplier( + "long range", () -> LongStream.iterate(0, i -> i + 1).limit(10000))). + terminal(s -> s.reduce(0, Long::sum)).exercise(); + } + + public void testLongInfiniteRangeFindFirst() { + long first = LongStream.iterate(0, i -> i + 1).filter(i -> i > 10000).findFirst().getAsLong(); + assertEquals(first, LongStream.iterate(0, i -> i + 1).parallel().filter(i -> i > 10000).findFirst().getAsLong()); + } + + // + + public void testDoubleRangeErrors() { + for (double start : Arrays.asList(1, 10, -1, -10)) { + for (double end : Arrays.asList(1, 10, -1, -10)) { + for (double step : Arrays.asList(0.0, +0.0, -0.0, 1.0, -1.0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY)) { + try { + if (step > 0) + executeAndNoCatch(() -> DoubleStream.range(start, end, step)); + else + executeAndCatch(() -> DoubleStream.range(start, end, step)); + } + catch (AssertionError e) { + System.out.printf("start=%f, end=%f, step=%f%n", start, end, step); + throw e; + } + } + } + } + + for (double start : Arrays.asList(0.0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN)) { + for (double end : Arrays.asList(0.0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN)) { + for (double step : Arrays.asList(1.0, -1.0, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN)) { + try { + if ((start == 0.0 && end == 0.0 && step > 0) + || (start > end && step > 0)) { + executeAndNoCatch(() -> DoubleStream.range(start, end, step)); + } + else { + executeAndCatch(() -> DoubleStream.range(start, end, step)); + } + } + catch (AssertionError e) { + System.out.printf("start=%f, end=%f, step=%f%n", start, end, step); + throw e; + } + } + } + } + } + + public void testDoubleRange() { + // Without step + for (double start : Arrays.asList(1, 1000, -1, -1000)) { + for (double end : Arrays.asList(1, 1000, -1, -1000)) { + double step = 1; + double size = start < end ? Math.ceil((end - start) / step) : 0; + double[] exp = new double[(int) size]; + for (long i = 0; i < size; i++) { + exp[(int) i] = start + i * step; + } + + double[] inc = DoubleStream.range(start, end).toArray(); + assertEquals(inc.length, (int) size); + assertTrue(Arrays.equals(exp, inc)); + + withData(doubleRangeData(start, end, step)).stream(s -> s). + expectedResult(exp).exercise(); + } + } + + // With step + for (double start : Arrays.asList(1, 1000, -1, -1000)) { + for (double end : Arrays.asList(1, 1000, -1, -1000)) { + for (double step : Arrays.asList(1, -1, -2, 2)) { + if (step <= 0) + continue; + double size = start < end ? Math.ceil((end - start) / step) : 0; + double[] exp = new double[(int) size]; + for (long i = 0; i < size; i++) { + exp[(int) i] = start + i * step; + } + + double[] inc = DoubleStream.range(start, end, step).toArray(); + assertEquals(inc.length, (int) size); + assertTrue(Arrays.equals(exp, inc)); + + withData(doubleRangeData(start, end, step)).stream(s -> s). + expectedResult(exp).exercise(); + } + } + } + + // With non-integer values + for (double step : Arrays.asList(Math.PI / 1000.0, Math.PI / 1000.0, Math.PI / 10000.0)) { + double start = -Math.PI; + double end = Math.PI; + double size = start < end ? Math.ceil((end - start) / step) : 0; + double[] exp = new double[(int) size]; + for (long i = 0; i < size; i++) { + exp[(int) i] = start + i * step; + } + + withData(doubleRangeData(start, end, step)).stream(s -> s). + expectedResult(exp).exercise(); + } + } + + TestData.OfDouble doubleRangeData(double start, double end, double step) { + return TestData.Factory.ofDoubleSupplier("double range", () -> DoubleStream.range(start, end, step)); + } + + public void tesDoubleRangeReduce() { + withData(doubleRangeData(0, 10000, 1)). + terminal(s -> s.reduce(0, Double::sum)).exercise(); + } + + public void testDoubleInfiniteRangeLimit() { + withData(TestData.Factory.ofDoubleSupplier( + "double range", () -> DoubleStream.iterate(0, i -> i + 1).limit(10000))). + terminal(s -> s.reduce(0, Double::sum)).exercise(); + } + + public void testDoubleInfiniteRangeFindFirst() { + double first = DoubleStream.iterate(0, i -> i + 1).filter(i -> i > 10000).findFirst().getAsDouble(); + assertEquals(first, DoubleStream.iterate(0, i -> i + 1).parallel().filter(i -> i > 10000).findFirst().getAsDouble()); + } + + // + + private static int[] reverse(int[] a) { + int[] b = new int[a.length]; + for (int i = 0; i < a.length; i++) { + b[b.length - i - 1] = a[i]; + } + return b; + } + + private static long[] reverse(long[] a) { + long[] b = new long[a.length]; + for (int i = 0; i < a.length; i++) { + b[b.length - i - 1] = a[i]; + } + return b; + } + + private static double[] reverse(double[] a) { + double[] b = new double[a.length]; + for (int i = 0; i < a.length; i++) { + b[b.length - i - 1] = a[i]; + } + return b; + } + + private void executeAndCatch(Runnable r) { + executeAndCatch(IllegalArgumentException.class, r); + } + + private void executeAndNoCatch(Runnable r) { + executeAndCatch(null, r); + } + + private void executeAndCatch(Class expected, Runnable r) { + Exception caught = null; + try { + r.run(); + } + catch (Exception e) { + caught = e; + } + + if (expected != null) { + assertNotNull(caught, + String.format("No Exception was thrown, expected an Exception of %s to be thrown", + expected.getName())); + assertTrue(expected.isInstance(caught), + String.format("Exception thrown %s not an instance of %s", + caught.getClass().getName(), expected.getName())); + } + else { + if (caught != null) { + assertNull(caught, + String.format("Unexpected exception of %s was thrown", + caught.getClass().getName())); + } + } + } + +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceByOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceByOpTest.java new file mode 100644 index 00000000000..539ed9beada --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceByOpTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.List; +import java.util.stream.LambdaTestHelpers; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.StreamTestDataProvider; +import org.testng.annotations.Test; + +import java.util.HashSet; +import java.util.Map; +import java.util.stream.TestData; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.reducing; +import static java.util.stream.LambdaTestHelpers.*; + +/** + * ReduceByOpTest + * + * @author Brian Goetz + */ +@Test +public class ReduceByOpTest extends OpTestCase { + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + Map> gbResult = data.stream().collect(groupingBy(LambdaTestHelpers.forPredicate(pEven, true, false))); + Map result = data.stream().collect(groupingBy(LambdaTestHelpers.forPredicate(pEven, true, false), reducing(0, rPlus))); + assertEquals(result.size(), gbResult.size()); + for (Map.Entry entry : result.entrySet()) { + Boolean key = entry.getKey(); + assertEquals(entry.getValue(), data.stream().filter(e -> pEven.test(e) == key).reduce(0, rPlus)); + } + + int uniqueSize = data.into(new HashSet()).size(); + Map> mgResult = exerciseTerminalOps(data, s -> s.collect(groupingBy(mId))); + Map miResult = exerciseTerminalOps(data, s -> s.collect(groupingBy(mId, reducing(0, e -> 1, Integer::sum)))); + assertEquals(miResult.keySet().size(), uniqueSize); + for (Map.Entry entry : miResult.entrySet()) + assertEquals((int) entry.getValue(), mgResult.get(entry.getKey()).size()); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceTest.java new file mode 100644 index 00000000000..fd4c6874e49 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.StreamTestDataProvider; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.Optional; +import java.util.stream.TestData; + +import static java.util.stream.LambdaTestHelpers.*; + +/** + * ReduceOpTest + * + * @author Brian Goetz + */ +@Test +public class ReduceTest extends OpTestCase { + public void testReduce() { + List list = countTo(10); + + assertEquals(55, (int) list.stream().reduce(rPlus).get()); + assertEquals(55, (int) list.stream().reduce(0, rPlus)); + assertEquals(10, (int) list.stream().reduce(rMax).get()); + assertEquals(1, (int) list.stream().reduce(rMin).get()); + + 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 = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + assertEquals(0, (int) exerciseTerminalOps(data, s -> s.filter(pFalse), s -> s.reduce(0, rPlus, rPlus))); + + Optional seedless = exerciseTerminalOps(data, s -> s.reduce(rPlus)); + Integer folded = exerciseTerminalOps(data, s -> s.reduce(0, rPlus, rPlus)); + assertEquals(folded, seedless.orElse(0)); + + seedless = exerciseTerminalOps(data, s -> s.reduce(rMin)); + folded = exerciseTerminalOps(data, s -> s.reduce(Integer.MAX_VALUE, rMin, rMin)); + assertEquals(folded, seedless.orElse(Integer.MAX_VALUE)); + + seedless = exerciseTerminalOps(data, s -> s.reduce(rMax)); + folded = exerciseTerminalOps(data, s -> s.reduce(Integer.MIN_VALUE, rMax, rMax)); + assertEquals(folded, seedless.orElse(Integer.MIN_VALUE)); + + seedless = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(rPlus)); + folded = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(0, rPlus, rPlus)); + assertEquals(folded, seedless.orElse(0)); + + seedless = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(rMin)); + folded = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(Integer.MAX_VALUE, rMin, rMin)); + assertEquals(folded, seedless.orElse(Integer.MAX_VALUE)); + + seedless = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(rMax)); + folded = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(Integer.MIN_VALUE, rMax, rMax)); + assertEquals(folded, seedless.orElse(Integer.MIN_VALUE)); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java new file mode 100644 index 00000000000..e74810002fb --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.stream.LambdaTestHelpers; +import java.util.stream.OpTestCase; +import java.util.stream.StreamTestDataProvider; +import org.testng.annotations.Test; + +import java.util.Comparators; +import java.util.Iterator; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; +import java.util.Spliterator; +import java.util.stream.Stream; +import java.util.stream.TestData; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * SequentialOpTest + * + * @author Brian Goetz + */ +public class SequentialOpTest extends OpTestCase { + @SuppressWarnings({"rawtypes", "unchecked"}) + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class, + groups = { "serialization-hostile" }) + public void testLazy(String name, TestData.OfRef data) { + Function id = LambdaTestHelpers.identity(); + AtomicInteger counter = new AtomicInteger(); + Supplier>[] suppliers = new Supplier[] { () -> data.stream(), () -> data.parallelStream() }; + UnaryOperator>[] configs + = new UnaryOperator[] { + (UnaryOperator>) s -> s.peek(e -> { counter.incrementAndGet(); }), + (UnaryOperator>) s -> s.map(id).peek(e -> { counter.incrementAndGet(); }).sequential().map(id), + (UnaryOperator>) s -> s.map(id).peek(e -> { counter.incrementAndGet(); }).parallel().map(id), + (UnaryOperator>) s -> s.sequential().map(id).peek(e -> { + counter.incrementAndGet(); + }).map(id), + (UnaryOperator>) s -> s.parallel().map(id).peek(e -> { counter.incrementAndGet(); }).map(id) + }; + + for (Supplier> supp : suppliers) + for (UnaryOperator> config : configs) { + counter.set(0); + Stream stream = config.apply(supp.get()); + assertEquals(0, counter.get()); + + Iterator iterator = stream.iterator(); + assertEquals(0, counter.get()); + + if (iterator.hasNext()) + iterator.next(); + assertTrue(data.size() == 0 || counter.get() > 0); + + counter.set(0); + stream = config.apply(supp.get()); + Spliterator spliterator = stream.spliterator(); + assertEquals(0, counter.get()); + + spliterator.forEachRemaining(e -> { + }); + assertTrue(data.size() == 0 || counter.get() > 0); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testMixedSeqPar(String name, TestData.OfRef data) { + Function id = LambdaTestHelpers.identity(); + UnaryOperator>[] changers + = new UnaryOperator[] { + (UnaryOperator>) s -> s, + (UnaryOperator>) s -> s.sequential(), + (UnaryOperator>) s -> s.parallel() + }; + UnaryOperator>[] stuff + = new UnaryOperator[] { + (UnaryOperator>) s -> s, + (UnaryOperator>) s -> s.map(id), + (UnaryOperator>) s -> s.sorted(Comparators.naturalOrder()), + (UnaryOperator>) s -> s.map(id).sorted(Comparators.naturalOrder()).map(id), + (UnaryOperator>) s -> s.filter(LambdaTestHelpers.pEven).sorted(Comparators.naturalOrder()).map(id), + }; + + for (UnaryOperator> c1 : changers) + for (UnaryOperator> s1 : stuff) + for (UnaryOperator> c2 : changers) + for (UnaryOperator> s2 : stuff) { + UnaryOperator> composed = s -> s2.apply(c2.apply(s1.apply(c1.apply(s)))); + exerciseOps(data, composed); + } + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java new file mode 100644 index 00000000000..5074ce93c03 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.annotations.Test; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.StreamTestDataProvider; +import java.util.stream.TestData; + +import static java.util.stream.LambdaTestHelpers.*; + +/** + * SliceOpTest + * + * @author Brian Goetz + */ +@Test +public class SliceOpTest extends OpTestCase { + + public void testSkip() { + assertCountSum(countTo(0).stream().substream(0), 0, 0); + assertCountSum(countTo(0).stream().substream(4), 0, 0); + assertCountSum(countTo(4).stream().substream(4), 0, 0); + assertCountSum(countTo(4).stream().substream(2), 2, 7); + assertCountSum(countTo(4).stream().substream(0), 4, 10); + + assertCountSum(countTo(0).parallelStream().substream(0), 0, 0); + assertCountSum(countTo(0).parallelStream().substream(4), 0, 0); + assertCountSum(countTo(4).parallelStream().substream(4), 0, 0); + assertCountSum(countTo(4).parallelStream().substream(2), 2, 7); + assertCountSum(countTo(4).parallelStream().substream(0), 4, 10); + + exerciseOps(Collections.emptyList(), s -> s.substream(0), Collections.emptyList()); + exerciseOps(Collections.emptyList(), s -> s.substream(10), Collections.emptyList()); + + exerciseOps(countTo(1), s -> s.substream(0), countTo(1)); + exerciseOps(countTo(1), s -> s.substream(1), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(0), countTo(100)); + exerciseOps(countTo(100), s -> s.substream(10), range(11, 100)); + exerciseOps(countTo(100), s -> s.substream(100), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(200), Collections.emptyList()); + } + + public void testLimit() { + assertCountSum(countTo(0).stream().limit(4), 0, 0); + assertCountSum(countTo(2).stream().limit(4), 2, 3); + assertCountSum(countTo(4).stream().limit(4), 4, 10); + assertCountSum(countTo(8).stream().limit(4), 4, 10); + + assertCountSum(countTo(0).parallelStream().limit(4), 0, 0); + assertCountSum(countTo(2).parallelStream().limit(4), 2, 3); + assertCountSum(countTo(4).parallelStream().limit(4), 4, 10); + assertCountSum(countTo(8).parallelStream().limit(4), 4, 10); + + exerciseOps(Collections.emptyList(), s -> s.limit(0), Collections.emptyList()); + exerciseOps(Collections.emptyList(), s -> s.limit(10), Collections.emptyList()); + exerciseOps(countTo(1), s -> s.limit(0), Collections.emptyList()); + exerciseOps(countTo(1), s -> s.limit(1), countTo(1)); + exerciseOps(countTo(100), s -> s.limit(0), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.limit(10), countTo(10)); + exerciseOps(countTo(100), s -> s.limit(10).limit(10), countTo(10)); + exerciseOps(countTo(100), s -> s.limit(100), countTo(100)); + exerciseOps(countTo(100), s -> s.limit(100).limit(10), countTo(10)); + exerciseOps(countTo(100), s -> s.limit(200), countTo(100)); + } + + public void testSkipLimit() { + exerciseOps(Collections.emptyList(), s -> s.substream(0).limit(0), Collections.emptyList()); + exerciseOps(Collections.emptyList(), s -> s.substream(0).limit(10), Collections.emptyList()); + exerciseOps(Collections.emptyList(), s -> s.substream(10).limit(0), Collections.emptyList()); + exerciseOps(Collections.emptyList(), s -> s.substream(10).limit(10), Collections.emptyList()); + + exerciseOps(countTo(100), s -> s.substream(0).limit(100), countTo(100)); + exerciseOps(countTo(100), s -> s.substream(0).limit(10), countTo(10)); + exerciseOps(countTo(100), s -> s.substream(0).limit(0), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(10).limit(100), range(11, 100)); + exerciseOps(countTo(100), s -> s.substream(10).limit(10), range(11, 20)); + exerciseOps(countTo(100), s -> s.substream(10).limit(0), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(100).limit(100), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(100).limit(10), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(100).limit(0), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(200).limit(100), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(200).limit(10), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(200).limit(0), Collections.emptyList()); + } + + public void testSlice() { + exerciseOps(Collections.emptyList(), s -> s.substream(0, 0), Collections.emptyList()); + exerciseOps(Collections.emptyList(), s -> s.substream(0, 10), Collections.emptyList()); + exerciseOps(Collections.emptyList(), s -> s.substream(10, 10), Collections.emptyList()); + exerciseOps(Collections.emptyList(), s -> s.substream(10, 20), Collections.emptyList()); + + exerciseOps(countTo(100), s -> s.substream(0, 100), countTo(100)); + exerciseOps(countTo(100), s -> s.substream(0, 10), countTo(10)); + exerciseOps(countTo(100), s -> s.substream(0, 0), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(10, 110), range(11, 100)); + exerciseOps(countTo(100), s -> s.substream(10, 20), range(11, 20)); + exerciseOps(countTo(100), s -> s.substream(10, 10), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(100, 200), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(100, 110), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(100, 100), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(200, 300), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(200, 210), Collections.emptyList()); + exerciseOps(countTo(100), s -> s.substream(200, 200), Collections.emptyList()); + } + + private int sliceSize(int dataSize, int skip, int limit) { + int size = Math.max(0, dataSize - skip); + if (limit >= 0) + size = Math.min(size, limit); + return size; + } + + private int sliceSize(int dataSize, int skip) { + return Math.max(0, dataSize - skip); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testSkipOps(String name, TestData.OfRef data) { + List skips = sizes(data.size()); + + for (int s : skips) { + Collection sr = exerciseOpsInt(data, + st -> st.substream(s), + st -> st.substream(s), + st -> st.substream(s), + st -> st.substream(s)); + assertEquals(sr.size(), sliceSize(data.size(), s)); + + sr = exerciseOpsInt(data, + st -> st.substream(s).substream(s / 2), + st -> st.substream(s).substream(s / 2), + st -> st.substream(s).substream(s / 2), + st -> st.substream(s).substream(s / 2)); + assertEquals(sr.size(), sliceSize(sliceSize(data.size(), s), s/2)); + } + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testSkipLimitOps(String name, TestData.OfRef data) { + List skips = sizes(data.size()); + List limits = skips; + + for (int s : skips) { + for (int limit : limits) { + Collection sr = exerciseOpsInt(data, + st -> st.substream(s).limit(limit), + st -> st.substream(s).limit(limit), + st -> st.substream(s).limit(limit), + st -> st.substream(s).limit(limit)); + assertEquals(sr.size(), sliceSize(sliceSize(data.size(), s), 0, limit)); + + sr = exerciseOpsInt(data, + st -> st.substream(s, limit+s), + st -> st.substream(s, limit+s), + st -> st.substream(s, limit+s), + st -> st.substream(s, limit+s)); + assertEquals(sr.size(), sliceSize(data.size(), s, limit)); + } + } + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testLimitOps(String name, TestData.OfRef data) { + List limits = sizes(data.size()); + + for (int limit : limits) { + Collection sr = exerciseOpsInt(data, + st -> st.limit(limit), + st -> st.limit(limit), + st -> st.limit(limit), + st -> st.limit(limit)); + assertEquals(sr.size(), sliceSize(data.size(), 0, limit)); + + sr = exerciseOpsInt(data, + st -> st.limit(limit).limit(limit / 2), + st -> st.limit(limit).limit(limit / 2), + st -> st.limit(limit).limit(limit / 2), + st -> st.limit(limit).limit(limit / 2)); + assertEquals(sr.size(), sliceSize(sliceSize(data.size(), 0, limit), 0, limit/2)); + } + } + + public void testLimitSort() { + List l = countTo(100); + Collections.reverse(l); + exerciseOps(l, s -> s.limit(10).sorted(Comparators.naturalOrder())); + } + + @Test(groups = { "serialization-hostile" }) + public void testLimitShortCircuit() { + for (int l : Arrays.asList(0, 10)) { + AtomicInteger ai = new AtomicInteger(); + countTo(100).stream() + .peek(i -> ai.getAndIncrement()) + .limit(l).toArray(); + // For the case of a zero limit, one element will get pushed through the sink chain + assertEquals(ai.get(), l, "tee block was called too many times"); + } + } + + public void testSkipParallel() { + List l = countTo(1000).parallelStream().substream(200).limit(200).sequential().collect(Collectors.toList()); + assertEquals(l.size(), 200); + assertEquals(l.get(l.size() -1).intValue(), 400); + } + + public void testLimitParallel() { + List l = countTo(1000).parallelStream().limit(500).sequential().collect(Collectors.toList()); + assertEquals(l.size(), 500); + assertEquals(l.get(l.size() -1).intValue(), 500); + } + + private List sizes(int size) { + if (size < 4) { + return Arrays.asList(0, 1, 2, 3, 4, 6); + } + else { + return Arrays.asList(0, 1, size / 2, size - 1, size, size + 1, 2 * size); + } + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java new file mode 100644 index 00000000000..2d1886b70c8 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.annotations.Test; + +import java.util.*; +import java.util.Spliterators; +import java.util.stream.*; + +import static java.util.stream.LambdaTestHelpers.*; + +/** + * SortedOpTest + * + * @author Brian Goetz + */ +@Test +public class SortedOpTest extends OpTestCase { + public void testSorted() { + assertCountSum(countTo(0).stream().sorted(), 0, 0); + assertCountSum(countTo(10).stream().sorted(), 10, 55); + assertCountSum(countTo(10).stream().sorted(cInteger.reverseOrder()), 10, 55); + + List to10 = countTo(10); + assertSorted(to10.stream().sorted(cInteger.reverseOrder()).iterator(), cInteger.reverseOrder()); + + Collections.reverse(to10); + assertSorted(to10.stream().sorted().iterator()); + + Spliterator s = to10.stream().sorted().spliterator(); + assertTrue(s.hasCharacteristics(Spliterator.SORTED)); + + s = to10.stream().sorted(cInteger.reverseOrder()).spliterator(); + assertFalse(s.hasCharacteristics(Spliterator.SORTED)); + } + + @Test(groups = { "serialization-hostile" }) + public void testSequentialShortCircuitTerminal() { + // The sorted op for sequential evaluation will buffer all elements when accepting + // then at the end sort those elements and push those elements downstream + + List l = Arrays.asList(5, 4, 3, 2, 1); + + // Find + assertEquals(l.stream().sorted().findFirst(), Optional.of(1)); + assertEquals(l.stream().sorted().findAny(), Optional.of(1)); + assertEquals(unknownSizeStream(l).sorted().findFirst(), Optional.of(1)); + assertEquals(unknownSizeStream(l).sorted().findAny(), Optional.of(1)); + + // Match + assertEquals(l.stream().sorted().anyMatch(i -> i == 2), true); + assertEquals(l.stream().sorted().noneMatch(i -> i == 2), false); + assertEquals(l.stream().sorted().allMatch(i -> i == 2), false); + assertEquals(unknownSizeStream(l).sorted().anyMatch(i -> i == 2), true); + assertEquals(unknownSizeStream(l).sorted().noneMatch(i -> i == 2), false); + assertEquals(unknownSizeStream(l).sorted().allMatch(i -> i == 2), false); + } + + private Stream unknownSizeStream(List l) { + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(l.iterator(), 0)); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + Collection result = exerciseOpsInt(data, Stream::sorted, IntStream::sorted, LongStream::sorted, DoubleStream::sorted); + assertSorted(result.iterator()); + assertContentsUnordered(data, result); + + result = exerciseOps(data, s -> s.sorted(cInteger.reverseOrder())); + assertSorted(result.iterator(), cInteger.reverseOrder()); + assertContentsUnordered(data, result); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testSortSort(String name, TestData.OfRef data) { + // For parallel cases ensure the size is known + Collection result = withData(data) + .stream(s -> s.sorted().sorted(), + new CollectorOps.TestParallelSizedOp()) + .exercise(); + + assertSorted(result); + assertContentsUnordered(data, result); + + result = withData(data) + .stream(s -> s.sorted(cInteger.reverseOrder()).sorted(cInteger.reverseOrder()), + new CollectorOps.TestParallelSizedOp()) + .exercise(); + + assertSorted(result, cInteger.reverseOrder()); + assertContentsUnordered(data, result); + + result = withData(data) + .stream(s -> s.sorted().sorted(cInteger.reverseOrder()), + new CollectorOps.TestParallelSizedOp()) + .exercise(); + + assertSorted(result, cInteger.reverseOrder()); + assertContentsUnordered(data, result); + + result = withData(data) + .stream(s -> s.sorted(cInteger.reverseOrder()).sorted(), + new CollectorOps.TestParallelSizedOp()) + .exercise(); + + assertSorted(result); + assertContentsUnordered(data, result); + } + + // + + @Test(groups = { "serialization-hostile" }) + public void testIntSequentialShortCircuitTerminal() { + int[] a = new int[]{5, 4, 3, 2, 1}; + + // Find + assertEquals(Arrays.stream(a).sorted().findFirst(), OptionalInt.of(1)); + assertEquals(Arrays.stream(a).sorted().findAny(), OptionalInt.of(1)); + assertEquals(unknownSizeIntStream(a).sorted().findFirst(), OptionalInt.of(1)); + assertEquals(unknownSizeIntStream(a).sorted().findAny(), OptionalInt.of(1)); + + // Match + assertEquals(Arrays.stream(a).sorted().anyMatch(i -> i == 2), true); + assertEquals(Arrays.stream(a).sorted().noneMatch(i -> i == 2), false); + assertEquals(Arrays.stream(a).sorted().allMatch(i -> i == 2), false); + assertEquals(unknownSizeIntStream(a).sorted().anyMatch(i -> i == 2), true); + assertEquals(unknownSizeIntStream(a).sorted().noneMatch(i -> i == 2), false); + assertEquals(unknownSizeIntStream(a).sorted().allMatch(i -> i == 2), false); + } + + private IntStream unknownSizeIntStream(int[] a) { + return StreamSupport.intStream(Spliterators.spliteratorUnknownSize(Spliterators.iteratorFromSpliterator(Arrays.spliterator(a)), 0)); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOps(String name, TestData.OfInt data) { + Collection result = exerciseOps(data, s -> s.sorted()); + assertSorted(result); + assertContentsUnordered(data, result); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntSortSort(String name, TestData.OfInt data) { + // For parallel cases ensure the size is known + Collection result = withData(data) + .stream(s -> s.sorted().sorted(), new CollectorOps.TestParallelSizedOp.OfInt()) + .exercise(); + + assertSorted(result); + assertContentsUnordered(data, result); + } + + // + + @Test(groups = { "serialization-hostile" }) + public void testLongSequentialShortCircuitTerminal() { + long[] a = new long[]{5, 4, 3, 2, 1}; + + // Find + assertEquals(Arrays.stream(a).sorted().findFirst(), OptionalLong.of(1)); + assertEquals(Arrays.stream(a).sorted().findAny(), OptionalLong.of(1)); + assertEquals(unknownSizeLongStream(a).sorted().findFirst(), OptionalLong.of(1)); + assertEquals(unknownSizeLongStream(a).sorted().findAny(), OptionalLong.of(1)); + + // Match + assertEquals(Arrays.stream(a).sorted().anyMatch(i -> i == 2), true); + assertEquals(Arrays.stream(a).sorted().noneMatch(i -> i == 2), false); + assertEquals(Arrays.stream(a).sorted().allMatch(i -> i == 2), false); + assertEquals(unknownSizeLongStream(a).sorted().anyMatch(i -> i == 2), true); + assertEquals(unknownSizeLongStream(a).sorted().noneMatch(i -> i == 2), false); + assertEquals(unknownSizeLongStream(a).sorted().allMatch(i -> i == 2), false); + } + + private LongStream unknownSizeLongStream(long[] a) { + return StreamSupport.longStream(Spliterators.spliteratorUnknownSize(Spliterators.iteratorFromSpliterator(Arrays.spliterator(a)), 0)); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOps(String name, TestData.OfLong data) { + Collection result = exerciseOps(data, s -> s.sorted()); + assertSorted(result); + assertContentsUnordered(data, result); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongSortSort(String name, TestData.OfLong data) { + // For parallel cases ensure the size is known + Collection result = withData(data) + .stream(s -> s.sorted().sorted(), new CollectorOps.TestParallelSizedOp.OfLong()) + .exercise(); + + assertSorted(result); + assertContentsUnordered(data, result); + } + + // + + @Test(groups = { "serialization-hostile" }) + public void testDoubleSequentialShortCircuitTerminal() { + double[] a = new double[]{5.0, 4.0, 3.0, 2.0, 1.0}; + + // Find + assertEquals(Arrays.stream(a).sorted().findFirst(), OptionalDouble.of(1)); + assertEquals(Arrays.stream(a).sorted().findAny(), OptionalDouble.of(1)); + assertEquals(unknownSizeDoubleStream(a).sorted().findFirst(), OptionalDouble.of(1)); + assertEquals(unknownSizeDoubleStream(a).sorted().findAny(), OptionalDouble.of(1)); + + // Match + assertEquals(Arrays.stream(a).sorted().anyMatch(i -> i == 2.0), true); + assertEquals(Arrays.stream(a).sorted().noneMatch(i -> i == 2.0), false); + assertEquals(Arrays.stream(a).sorted().allMatch(i -> i == 2.0), false); + assertEquals(unknownSizeDoubleStream(a).sorted().anyMatch(i -> i == 2.0), true); + assertEquals(unknownSizeDoubleStream(a).sorted().noneMatch(i -> i == 2.0), false); + assertEquals(unknownSizeDoubleStream(a).sorted().allMatch(i -> i == 2.0), false); + } + + private DoubleStream unknownSizeDoubleStream(double[] a) { + return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize(Spliterators.iteratorFromSpliterator(Arrays.spliterator(a)), 0)); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOps(String name, TestData.OfDouble data) { + Collection result = exerciseOps(data, s -> s.sorted()); + assertSorted(result); + assertContentsUnordered(data, result); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleSortSort(String name, TestData.OfDouble data) { + // For parallel cases ensure the size is known + Collection result = withData(data) + .stream(s -> s.sorted().sorted(), new CollectorOps.TestParallelSizedOp.OfDouble()) + .exercise(); + + assertSorted(result); + assertContentsUnordered(data, result); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorLateBindingFailFastTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorLateBindingFailFastTest.java new file mode 100644 index 00000000000..af7ddbf066b --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorLateBindingFailFastTest.java @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2013, 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. + * + * 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.stream; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.Set; +import java.util.Spliterator; +import java.util.Stack; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.Vector; +import java.util.WeakHashMap; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import static org.testng.Assert.*; + +/** + * @test + * @summary Spliterator last-binding and fail-fast tests + * @run testng SpliteratorLateBindingFailFastTest + */ + +@Test(groups = { "serialization-hostile" }) +public class SpliteratorLateBindingFailFastTest { + + private interface Source { + Collection asCollection(); + void update(); + } + + private static class SpliteratorDataBuilder { + final List data; + + final T newValue; + + final List exp; + + final Map mExp; + + SpliteratorDataBuilder(List data, T newValue, List exp) { + this.data = data; + this.newValue = newValue; + this.exp = exp; + this.mExp = createMap(exp); + } + + Map createMap(List l) { + Map m = new LinkedHashMap<>(); + for (T t : l) { + m.put(t, t); + } + return m; + } + + void add(String description, Supplier> s) { + description = joiner(description).toString(); + data.add(new Object[]{description, s}); + } + + void addCollection(Function, ? extends Collection> f) { + class CollectionSource implements Source { + final Collection c = f.apply(exp); + + final Consumer> updater; + + CollectionSource(Consumer> updater) { + this.updater = updater; + } + + @Override + public Collection asCollection() { + return c; + } + + @Override + public void update() { + updater.accept(c); + } + } + + String description = "new " + f.apply(Collections.emptyList()).getClass().getName() + ".spliterator() "; + add(description + "ADD", () -> new CollectionSource(c -> c.add(newValue))); + add(description + "REMOVE", () -> new CollectionSource(c -> c.remove(c.iterator().next()))); + } + + void addList(Function, ? extends List> l) { + // @@@ If collection is instance of List then add sub-list tests + addCollection(l); + } + + void addMap(Function, ? extends Map> mapConstructor) { + class MapSource implements Source { + final Map m = mapConstructor.apply(mExp); + + final Collection c; + + final Consumer> updater; + + MapSource(Function, Collection> f, Consumer> updater) { + this.c = f.apply(m); + this.updater = updater; + } + + @Override + public Collection asCollection() { + return c; + } + + @Override + public void update() { + updater.accept(m); + } + } + + Map>> actions = new HashMap<>(); + actions.put("ADD", m -> m.put(newValue, newValue)); + actions.put("REMOVE", m -> m.remove(m.keySet().iterator().next())); + + String description = "new " + mapConstructor.apply(Collections.emptyMap()).getClass().getName(); + for (Map.Entry>> e : actions.entrySet()) { + add(description + ".keySet().spliterator() " + e.getKey(), + () -> new MapSource(m -> m.keySet(), e.getValue())); + add(description + ".values().spliterator() " + e.getKey(), + () -> new MapSource(m -> m.values(), e.getValue())); + add(description + ".entrySet().spliterator() " + e.getKey(), + () -> new MapSource>(m -> m.entrySet(), e.getValue())); + } + } + + StringBuilder joiner(String description) { + return new StringBuilder(description). + append(" {"). + append("size=").append(exp.size()). + append("}"); + } + } + + static Object[][] spliteratorDataProvider; + + @DataProvider(name = "Source") + public static Object[][] spliteratorDataProvider() { + if (spliteratorDataProvider != null) { + return spliteratorDataProvider; + } + + List data = new ArrayList<>(); + SpliteratorDataBuilder db = new SpliteratorDataBuilder<>(data, 5, Arrays.asList(1, 2, 3, 4)); + + // Collections + + db.addList(ArrayList::new); + + db.addList(LinkedList::new); + + db.addList(Vector::new); + + + db.addCollection(HashSet::new); + + db.addCollection(LinkedHashSet::new); + + db.addCollection(TreeSet::new); + + + db.addCollection(c -> { Stack s = new Stack<>(); s.addAll(c); return s;}); + + db.addCollection(PriorityQueue::new); + + // ArrayDeque fails some tests since it's fail-fast support is weaker + // than other collections and limited to detecting most, but not all, + // removals. It probably requires it's own test since it is difficult + // to abstract out the conditions under which it fails-fast. +// db.addCollection(ArrayDeque::new); + + // Maps + + db.addMap(HashMap::new); + + db.addMap(LinkedHashMap::new); + + // This fails when run through jrteg but passes when run though + // ant +// db.addMap(IdentityHashMap::new); + + db.addMap(WeakHashMap::new); + + // @@@ Descending maps etc + db.addMap(TreeMap::new); + + return spliteratorDataProvider = data.toArray(new Object[0][]); + } + + @Test(dataProvider = "Source") + public void lateBindingTestWithForEach(String description, Supplier> ss) { + Source source = ss.get(); + Collection c = source.asCollection(); + Spliterator s = c.spliterator(); + + source.update(); + + Set r = new HashSet<>(); + s.forEachRemaining(r::add); + + assertEquals(r, new HashSet<>(c)); + } + + @Test(dataProvider = "Source") + public void lateBindingTestWithTryAdvance(String description, Supplier> ss) { + Source source = ss.get(); + Collection c = source.asCollection(); + Spliterator s = c.spliterator(); + + source.update(); + + Set r = new HashSet<>(); + while (s.tryAdvance(r::add)) { } + + assertEquals(r, new HashSet<>(c)); + } + + @Test(dataProvider = "Source") + public void lateBindingTestWithCharacteritics(String description, Supplier> ss) { + Source source = ss.get(); + Collection c = source.asCollection(); + Spliterator s = c.spliterator(); + s.characteristics(); + + Set r = new HashSet<>(); + s.forEachRemaining(r::add); + + assertEquals(r, new HashSet<>(c)); + } + + + @Test(dataProvider = "Source") + public void testFailFastTestWithTryAdvance(String description, Supplier> ss) { + { + Source source = ss.get(); + Collection c = source.asCollection(); + Spliterator s = c.spliterator(); + + s.tryAdvance(e -> { + }); + source.update(); + + executeAndCatch(() -> s.tryAdvance(e -> { })); + } + + { + Source source = ss.get(); + Collection c = source.asCollection(); + Spliterator s = c.spliterator(); + + s.tryAdvance(e -> { + }); + source.update(); + + executeAndCatch(() -> s.forEachRemaining(e -> { + })); + } + } + + @Test(dataProvider = "Source") + public void testFailFastTestWithForEach(String description, Supplier> ss) { + Source source = ss.get(); + Collection c = source.asCollection(); + Spliterator s = c.spliterator(); + + executeAndCatch(() -> s.forEachRemaining(e -> { + source.update(); + })); + } + + @Test(dataProvider = "Source") + public void testFailFastTestWithEstimateSize(String description, Supplier> ss) { + { + Source source = ss.get(); + Collection c = source.asCollection(); + Spliterator s = c.spliterator(); + + s.estimateSize(); + source.update(); + + executeAndCatch(() -> s.tryAdvance(e -> { })); + } + + { + Source source = ss.get(); + Collection c = source.asCollection(); + Spliterator s = c.spliterator(); + + s.estimateSize(); + source.update(); + + executeAndCatch(() -> s.forEachRemaining(e -> { + })); + } + } + + private void executeAndCatch(Runnable r) { + executeAndCatch(ConcurrentModificationException.class, r); + } + + private void executeAndCatch(Class expected, Runnable r) { + Exception caught = null; + try { + r.run(); + } + catch (Exception e) { + caught = e; + } + + assertNotNull(caught, + String.format("No Exception was thrown, expected an Exception of %s to be thrown", + expected.getName())); + assertTrue(expected.isInstance(caught), + String.format("Exception thrown %s not an instance of %s", + caught.getClass().getName(), expected.getName())); + } + +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java new file mode 100644 index 00000000000..d69c585b72d --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.function.Supplier; +import java.util.Spliterator; +import java.util.stream.*; + +import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; + +/** + * SpliteratorTest + * + * @author Brian Goetz + */ +@Test +public class SpliteratorTest { + + @Test(dataProvider = "Spliterator", dataProviderClass = StreamTestDataProvider.class ) + public void testSpliterator(String name, Supplier> supplier) { + SpliteratorTestHelper.testSpliterator(supplier); + } + + @Test(dataProvider = "IntSpliterator", dataProviderClass = IntStreamTestDataProvider.class ) + public void testIntSpliterator(String name, Supplier supplier) { + SpliteratorTestHelper.testIntSpliterator(supplier); + } + + @Test(dataProvider = "LongSpliterator", dataProviderClass = LongStreamTestDataProvider.class ) + public void testLongSpliterator(String name, Supplier supplier) { + SpliteratorTestHelper.testLongSpliterator(supplier); + } + + @Test(dataProvider = "DoubleSpliterator", dataProviderClass = DoubleStreamTestDataProvider.class ) + public void testDoubleSpliterator(String name, Supplier supplier) { + SpliteratorTestHelper.testDoubleSpliterator(supplier); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTraversingAndSplittingTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTraversingAndSplittingTest.java new file mode 100644 index 00000000000..de9d51cf0d9 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTraversingAndSplittingTest.java @@ -0,0 +1,1411 @@ +/* + * Copyright (c) 2013, 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. + * + * 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.stream; + +/** + * @test + * @summary Spliterator traversing and splitting tests + * @run testng SpliteratorTraversingAndSplittingTest + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.AbstractCollection; +import java.util.AbstractList; +import java.util.AbstractSet; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.Set; +import java.util.SortedSet; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.Stack; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.Vector; +import java.util.WeakHashMap; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.LinkedTransferQueue; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.Function; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; + +import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; + +@Test(groups = { "serialization-hostile" }) +public class SpliteratorTraversingAndSplittingTest { + + private static List SIZES = Arrays.asList(0, 1, 10, 100, 1000); + + private static class SpliteratorDataBuilder { + List data; + + List exp; + + Map mExp; + + SpliteratorDataBuilder(List data, List exp) { + this.data = data; + this.exp = exp; + this.mExp = createMap(exp); + } + + Map createMap(List l) { + Map m = new LinkedHashMap<>(); + for (T t : l) { + m.put(t, t); + } + return m; + } + + void add(String description, Collection expected, Supplier> s) { + description = joiner(description).toString(); + data.add(new Object[]{description, expected, s}); + } + + void add(String description, Supplier> s) { + add(description, exp, s); + } + + void addCollection(Function, ? extends Collection> c) { + add("new " + c.apply(Collections.emptyList()).getClass().getName() + ".spliterator()", + () -> c.apply(exp).spliterator()); + } + + void addList(Function, ? extends List> l) { + // @@@ If collection is instance of List then add sub-list tests + addCollection(l); + } + + void addMap(Function, ? extends Map> m) { + String description = "new " + m.apply(Collections.emptyMap()).getClass().getName(); + add(description + ".keySet().spliterator()", () -> m.apply(mExp).keySet().spliterator()); + add(description + ".values().spliterator()", () -> m.apply(mExp).values().spliterator()); + add(description + ".entrySet().spliterator()", mExp.entrySet(), () -> m.apply(mExp).entrySet().spliterator()); + } + + StringBuilder joiner(String description) { + return new StringBuilder(description). + append(" {"). + append("size=").append(exp.size()). + append("}"); + } + } + + static Object[][] spliteratorDataProvider; + + @DataProvider(name = "Spliterator") + public static Object[][] spliteratorDataProvider() { + if (spliteratorDataProvider != null) { + return spliteratorDataProvider; + } + + List data = new ArrayList<>(); + for (int size : SIZES) { + List exp = listIntRange(size); + SpliteratorDataBuilder db = new SpliteratorDataBuilder<>(data, exp); + + // Direct spliterator methods + + db.add("Spliterators.spliterator(Collection, ...)", + () -> Spliterators.spliterator(exp, 0)); + + db.add("Spliterators.spliterator(Iterator, ...)", + () -> Spliterators.spliterator(exp.iterator(), exp.size(), 0)); + + db.add("Spliterators.spliteratorUnknownSize(Iterator, ...)", + () -> Spliterators.spliteratorUnknownSize(exp.iterator(), 0)); + + db.add("Spliterators.spliterator(Spliterators.iteratorFromSpliterator(Spliterator ), ...)", + () -> Spliterators.spliterator(Spliterators.iteratorFromSpliterator(exp.spliterator()), exp.size(), 0)); + + db.add("Spliterators.spliterator(T[], ...)", + () -> Spliterators.spliterator(exp.toArray(new Integer[0]), 0)); + + db.add("Arrays.spliterator(T[], ...)", + () -> Arrays.spliterator(exp.toArray(new Integer[0]))); + + class SpliteratorFromIterator extends Spliterators.AbstractSpliterator { + Iterator it; + + SpliteratorFromIterator(Iterator it, long est) { + super(est, Spliterator.SIZED); + this.it = it; + } + + @Override + public boolean tryAdvance(Consumer action) { + if (action == null) + throw new NullPointerException(); + if (it.hasNext()) { + action.accept(it.next()); + return true; + } + else { + return false; + } + } + } + db.add("new Spliterators.AbstractSpliterator()", + () -> new SpliteratorFromIterator(exp.iterator(), exp.size())); + + // Collections + + // default method implementations + + class AbstractCollectionImpl extends AbstractCollection { + Collection c; + + AbstractCollectionImpl(Collection c) { + this.c = c; + } + + @Override + public Iterator iterator() { + return c.iterator(); + } + + @Override + public int size() { + return c.size(); + } + } + db.addCollection( + c -> new AbstractCollectionImpl(c)); + + class AbstractListImpl extends AbstractList { + List l; + + AbstractListImpl(Collection c) { + this.l = new ArrayList<>(c); + } + + @Override + public Integer get(int index) { + return l.get(index); + } + + @Override + public int size() { + return l.size(); + } + } + db.addCollection( + c -> new AbstractListImpl(c)); + + class AbstractSetImpl extends AbstractSet { + Set s; + + AbstractSetImpl(Collection c) { + this.s = new HashSet<>(c); + } + + @Override + public Iterator iterator() { + return s.iterator(); + } + + @Override + public int size() { + return s.size(); + } + } + db.addCollection( + c -> new AbstractSetImpl(c)); + + class AbstractSortedSetImpl extends AbstractSet implements SortedSet { + SortedSet s; + + AbstractSortedSetImpl(Collection c) { + this.s = new TreeSet<>(c); + } + + @Override + public Iterator iterator() { + return s.iterator(); + } + + @Override + public int size() { + return s.size(); + } + + @Override + public Comparator comparator() { + return s.comparator(); + } + + @Override + public SortedSet subSet(Integer fromElement, Integer toElement) { + return s.subSet(fromElement, toElement); + } + + @Override + public SortedSet headSet(Integer toElement) { + return s.headSet(toElement); + } + + @Override + public SortedSet tailSet(Integer fromElement) { + return s.tailSet(fromElement); + } + + @Override + public Integer first() { + return s.first(); + } + + @Override + public Integer last() { + return s.last(); + } + + @Override + public Spliterator spliterator() { + return SortedSet.super.spliterator(); + } + } + db.addCollection( + c -> new AbstractSortedSetImpl(c)); + + // + + db.add("Arrays.asList().spliterator()", + () -> Spliterators.spliterator(Arrays.asList(exp.toArray(new Integer[0])), 0)); + + db.addList(ArrayList::new); + + db.addList(LinkedList::new); + + db.addList(Vector::new); + + + db.addCollection(HashSet::new); + + db.addCollection(LinkedHashSet::new); + + db.addCollection(TreeSet::new); + + + db.addCollection(c -> { Stack s = new Stack<>(); s.addAll(c); return s;}); + + db.addCollection(PriorityQueue::new); + + db.addCollection(ArrayDeque::new); + + + db.addCollection(ConcurrentSkipListSet::new); + + if (size > 0) { + db.addCollection(c -> { + ArrayBlockingQueue abq = new ArrayBlockingQueue<>(size); + abq.addAll(c); + return abq; + }); + } + + db.addCollection(PriorityBlockingQueue::new); + + db.addCollection(LinkedBlockingQueue::new); + + db.addCollection(LinkedTransferQueue::new); + + db.addCollection(ConcurrentLinkedQueue::new); + + db.addCollection(LinkedBlockingDeque::new); + + db.addCollection(CopyOnWriteArrayList::new); + + db.addCollection(CopyOnWriteArraySet::new); + + if (size == 1) { + db.addCollection(c -> Collections.singleton(exp.get(0))); + db.addCollection(c -> Collections.singletonList(exp.get(0))); + } + + // Collections.synchronized/unmodifiable/checked wrappers + db.addCollection(Collections::unmodifiableCollection); + db.addCollection(c -> Collections.unmodifiableSet(new HashSet<>(c))); + db.addCollection(c -> Collections.unmodifiableSortedSet(new TreeSet<>(c))); + db.addList(c -> Collections.unmodifiableList(new ArrayList<>(c))); + db.addMap(Collections::unmodifiableMap); + db.addMap(m -> Collections.unmodifiableSortedMap(new TreeMap<>(m))); + + db.addCollection(Collections::synchronizedCollection); + db.addCollection(c -> Collections.synchronizedSet(new HashSet<>(c))); + db.addCollection(c -> Collections.synchronizedSortedSet(new TreeSet<>(c))); + db.addList(c -> Collections.synchronizedList(new ArrayList<>(c))); + db.addMap(Collections::synchronizedMap); + db.addMap(m -> Collections.synchronizedSortedMap(new TreeMap<>(m))); + + db.addCollection(c -> Collections.checkedCollection(c, Integer.class)); + db.addCollection(c -> Collections.checkedQueue(new ArrayDeque<>(c), Integer.class)); + db.addCollection(c -> Collections.checkedSet(new HashSet<>(c), Integer.class)); + db.addCollection(c -> Collections.checkedSortedSet(new TreeSet<>(c), Integer.class)); + db.addList(c -> Collections.checkedList(new ArrayList<>(c), Integer.class)); + db.addMap(c -> Collections.checkedMap(c, Integer.class, Integer.class)); + db.addMap(m -> Collections.checkedSortedMap(new TreeMap<>(m), Integer.class, Integer.class)); + + // Maps + + db.addMap(HashMap::new); + + db.addMap(LinkedHashMap::new); + + db.addMap(IdentityHashMap::new); + + db.addMap(WeakHashMap::new); + + // @@@ Descending maps etc + db.addMap(TreeMap::new); + + db.addMap(ConcurrentHashMap::new); + + db.addMap(ConcurrentSkipListMap::new); + } + + return spliteratorDataProvider = data.toArray(new Object[0][]); + } + + private static List listIntRange(int upTo) { + List exp = new ArrayList<>(); + for (int i = 0; i < upTo; i++) + exp.add(i); + return Collections.unmodifiableList(exp); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testNullPointerException(String description, Collection exp, Supplier s) { + executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining(null)); + executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance(null)); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testForEach(String description, Collection exp, Supplier s) { + testForEach(exp, s, (Consumer b) -> b); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testTryAdvance(String description, Collection exp, Supplier s) { + testTryAdvance(exp, s, (Consumer b) -> b); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testMixedTryAdvanceForEach(String description, Collection exp, Supplier s) { + testMixedTryAdvanceForEach(exp, s, (Consumer b) -> b); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testMixedTraverseAndSplit(String description, Collection exp, Supplier s) { + testMixedTraverseAndSplit(exp, s, (Consumer b) -> b); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testSplitAfterFullTraversal(String description, Collection exp, Supplier s) { + testSplitAfterFullTraversal(s, (Consumer b) -> b); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testSplitOnce(String description, Collection exp, Supplier s) { + testSplitOnce(exp, s, (Consumer b) -> b); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testSplitSixDeep(String description, Collection exp, Supplier s) { + testSplitSixDeep(exp, s, (Consumer b) -> b); + } + + @Test(dataProvider = "Spliterator") + @SuppressWarnings({"unchecked", "rawtypes"}) + public void testSplitUntilNull(String description, Collection exp, Supplier s) { + testSplitUntilNull(exp, s, (Consumer b) -> b); + } + + // + + private static class SpliteratorOfIntDataBuilder { + List data; + + List exp; + + SpliteratorOfIntDataBuilder(List data, List exp) { + this.data = data; + this.exp = exp; + } + + void add(String description, List expected, Supplier s) { + description = joiner(description).toString(); + data.add(new Object[]{description, expected, s}); + } + + void add(String description, Supplier s) { + add(description, exp, s); + } + + StringBuilder joiner(String description) { + return new StringBuilder(description). + append(" {"). + append("size=").append(exp.size()). + append("}"); + } + } + + static Object[][] spliteratorOfIntDataProvider; + + @DataProvider(name = "Spliterator.OfInt") + public static Object[][] spliteratorOfIntDataProvider() { + if (spliteratorOfIntDataProvider != null) { + return spliteratorOfIntDataProvider; + } + + List data = new ArrayList<>(); + for (int size : SIZES) { + int exp[] = arrayIntRange(size); + SpliteratorOfIntDataBuilder db = new SpliteratorOfIntDataBuilder(data, listIntRange(size)); + + db.add("Spliterators.spliterator(int[], ...)", + () -> Spliterators.spliterator(exp, 0)); + + db.add("Arrays.spliterator(int[], ...)", + () -> Arrays.spliterator(exp)); + + db.add("Spliterators.spliterator(PrimitiveIterator.OfInt, ...)", + () -> Spliterators.spliterator(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), exp.length, 0)); + + db.add("Spliterators.spliteratorUnknownSize(PrimitiveIterator.OfInt, ...)", + () -> Spliterators.spliteratorUnknownSize(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), 0)); + + class IntSpliteratorFromArray extends Spliterators.AbstractIntSpliterator { + int[] a; + int index = 0; + + IntSpliteratorFromArray(int[] a) { + super(a.length, Spliterator.SIZED); + this.a = a; + } + + @Override + public boolean tryAdvance(IntConsumer action) { + if (action == null) + throw new NullPointerException(); + if (index < a.length) { + action.accept(a[index++]); + return true; + } + else { + return false; + } + } + } + db.add("new Spliterators.AbstractIntAdvancingSpliterator()", + () -> new IntSpliteratorFromArray(exp)); + } + + return spliteratorOfIntDataProvider = data.toArray(new Object[0][]); + } + + private static int[] arrayIntRange(int upTo) { + int[] exp = new int[upTo]; + for (int i = 0; i < upTo; i++) + exp[i] = i; + return exp; + } + + private static UnaryOperator> intBoxingConsumer() { + class BoxingAdapter implements Consumer, IntConsumer { + private final Consumer b; + + BoxingAdapter(Consumer b) { + this.b = b; + } + + @Override + public void accept(Integer value) { + throw new IllegalStateException(); + } + + @Override + public void accept(int value) { + b.accept(value); + } + } + + return b -> new BoxingAdapter(b); + } + + @Test(dataProvider = "Spliterator.OfInt") + public void testIntNullPointerException(String description, Collection exp, Supplier s) { + executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((IntConsumer) null)); + executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((IntConsumer) null)); + } + + @Test(dataProvider = "Spliterator.OfInt") + public void testIntForEach(String description, Collection exp, Supplier s) { + testForEach(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfInt") + public void testIntTryAdvance(String description, Collection exp, Supplier s) { + testTryAdvance(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfInt") + public void testIntMixedTryAdvanceForEach(String description, Collection exp, Supplier s) { + testMixedTryAdvanceForEach(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfInt") + public void testIntMixedTraverseAndSplit(String description, Collection exp, Supplier s) { + testMixedTraverseAndSplit(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfInt") + public void testIntSplitAfterFullTraversal(String description, Collection exp, Supplier s) { + testSplitAfterFullTraversal(s, intBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfInt") + public void testIntSplitOnce(String description, Collection exp, Supplier s) { + testSplitOnce(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfInt") + public void testIntSplitSixDeep(String description, Collection exp, Supplier s) { + testSplitSixDeep(exp, s, intBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfInt") + public void testIntSplitUntilNull(String description, Collection exp, Supplier s) { + testSplitUntilNull(exp, s, intBoxingConsumer()); + } + + // + + private static class SpliteratorOfLongDataBuilder { + List data; + + List exp; + + SpliteratorOfLongDataBuilder(List data, List exp) { + this.data = data; + this.exp = exp; + } + + void add(String description, List expected, Supplier s) { + description = joiner(description).toString(); + data.add(new Object[]{description, expected, s}); + } + + void add(String description, Supplier s) { + add(description, exp, s); + } + + StringBuilder joiner(String description) { + return new StringBuilder(description). + append(" {"). + append("size=").append(exp.size()). + append("}"); + } + } + + static Object[][] spliteratorOfLongDataProvider; + + @DataProvider(name = "Spliterator.OfLong") + public static Object[][] spliteratorOfLongDataProvider() { + if (spliteratorOfLongDataProvider != null) { + return spliteratorOfLongDataProvider; + } + + List data = new ArrayList<>(); + for (int size : SIZES) { + long exp[] = arrayLongRange(size); + SpliteratorOfLongDataBuilder db = new SpliteratorOfLongDataBuilder(data, listLongRange(size)); + + db.add("Spliterators.spliterator(long[], ...)", + () -> Spliterators.spliterator(exp, 0)); + + db.add("Arrays.spliterator(long[], ...)", + () -> Arrays.spliterator(exp)); + + db.add("Spliterators.spliterator(PrimitiveIterator.OfLong, ...)", + () -> Spliterators.spliterator(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), exp.length, 0)); + + db.add("Spliterators.spliteratorUnknownSize(PrimitiveIterator.OfLong, ...)", + () -> Spliterators.spliteratorUnknownSize(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), 0)); + + class LongSpliteratorFromArray extends Spliterators.AbstractLongSpliterator { + long[] a; + int index = 0; + + LongSpliteratorFromArray(long[] a) { + super(a.length, Spliterator.SIZED); + this.a = a; + } + + @Override + public boolean tryAdvance(LongConsumer action) { + if (action == null) + throw new NullPointerException(); + if (index < a.length) { + action.accept(a[index++]); + return true; + } + else { + return false; + } + } + } + db.add("new Spliterators.AbstractLongAdvancingSpliterator()", + () -> new LongSpliteratorFromArray(exp)); + } + + return spliteratorOfLongDataProvider = data.toArray(new Object[0][]); + } + + private static List listLongRange(int upTo) { + List exp = new ArrayList<>(); + for (long i = 0; i < upTo; i++) + exp.add(i); + return Collections.unmodifiableList(exp); + } + + private static long[] arrayLongRange(int upTo) { + long[] exp = new long[upTo]; + for (int i = 0; i < upTo; i++) + exp[i] = i; + return exp; + } + + private static UnaryOperator> longBoxingConsumer() { + class BoxingAdapter implements Consumer, LongConsumer { + private final Consumer b; + + BoxingAdapter(Consumer b) { + this.b = b; + } + + @Override + public void accept(Long value) { + throw new IllegalStateException(); + } + + @Override + public void accept(long value) { + b.accept(value); + } + } + + return b -> new BoxingAdapter(b); + } + + @Test(dataProvider = "Spliterator.OfLong") + public void testLongNullPointerException(String description, Collection exp, Supplier s) { + executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((LongConsumer) null)); + executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((LongConsumer) null)); + } + + @Test(dataProvider = "Spliterator.OfLong") + public void testLongForEach(String description, Collection exp, Supplier s) { + testForEach(exp, s, longBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfLong") + public void testLongTryAdvance(String description, Collection exp, Supplier s) { + testTryAdvance(exp, s, longBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfLong") + public void testLongMixedTryAdvanceForEach(String description, Collection exp, Supplier s) { + testMixedTryAdvanceForEach(exp, s, longBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfLong") + public void testLongMixedTraverseAndSplit(String description, Collection exp, Supplier s) { + testMixedTraverseAndSplit(exp, s, longBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfLong") + public void testLongSplitAfterFullTraversal(String description, Collection exp, Supplier s) { + testSplitAfterFullTraversal(s, longBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfLong") + public void testLongSplitOnce(String description, Collection exp, Supplier s) { + testSplitOnce(exp, s, longBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfLong") + public void testLongSplitSixDeep(String description, Collection exp, Supplier s) { + testSplitSixDeep(exp, s, longBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfLong") + public void testLongSplitUntilNull(String description, Collection exp, Supplier s) { + testSplitUntilNull(exp, s, longBoxingConsumer()); + } + + // + + private static class SpliteratorOfDoubleDataBuilder { + List data; + + List exp; + + SpliteratorOfDoubleDataBuilder(List data, List exp) { + this.data = data; + this.exp = exp; + } + + void add(String description, List expected, Supplier s) { + description = joiner(description).toString(); + data.add(new Object[]{description, expected, s}); + } + + void add(String description, Supplier s) { + add(description, exp, s); + } + + StringBuilder joiner(String description) { + return new StringBuilder(description). + append(" {"). + append("size=").append(exp.size()). + append("}"); + } + } + + static Object[][] spliteratorOfDoubleDataProvider; + + @DataProvider(name = "Spliterator.OfDouble") + public static Object[][] spliteratorOfDoubleDataProvider() { + if (spliteratorOfDoubleDataProvider != null) { + return spliteratorOfDoubleDataProvider; + } + + List data = new ArrayList<>(); + for (int size : SIZES) { + double exp[] = arrayDoubleRange(size); + SpliteratorOfDoubleDataBuilder db = new SpliteratorOfDoubleDataBuilder(data, listDoubleRange(size)); + + db.add("Spliterators.spliterator(double[], ...)", + () -> Spliterators.spliterator(exp, 0)); + + db.add("Arrays.spliterator(double[], ...)", + () -> Arrays.spliterator(exp)); + + db.add("Spliterators.spliterator(PrimitiveIterator.OfDouble, ...)", + () -> Spliterators.spliterator(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), exp.length, 0)); + + db.add("Spliterators.spliteratorUnknownSize(PrimitiveIterator.OfDouble, ...)", + () -> Spliterators.spliteratorUnknownSize(Spliterators.iteratorFromSpliterator(Arrays.spliterator(exp)), 0)); + + class DoubleSpliteratorFromArray extends Spliterators.AbstractDoubleSpliterator { + double[] a; + int index = 0; + + DoubleSpliteratorFromArray(double[] a) { + super(a.length, Spliterator.SIZED); + this.a = a; + } + + @Override + public boolean tryAdvance(DoubleConsumer action) { + if (action == null) + throw new NullPointerException(); + if (index < a.length) { + action.accept(a[index++]); + return true; + } + else { + return false; + } + } + } + db.add("new Spliterators.AbstractDoubleAdvancingSpliterator()", + () -> new DoubleSpliteratorFromArray(exp)); + } + + return spliteratorOfDoubleDataProvider = data.toArray(new Object[0][]); + } + + private static List listDoubleRange(int upTo) { + List exp = new ArrayList<>(); + for (double i = 0; i < upTo; i++) + exp.add(i); + return Collections.unmodifiableList(exp); + } + + private static double[] arrayDoubleRange(int upTo) { + double[] exp = new double[upTo]; + for (int i = 0; i < upTo; i++) + exp[i] = i; + return exp; + } + + private static UnaryOperator> doubleBoxingConsumer() { + class BoxingAdapter implements Consumer, DoubleConsumer { + private final Consumer b; + + BoxingAdapter(Consumer b) { + this.b = b; + } + + @Override + public void accept(Double value) { + throw new IllegalStateException(); + } + + @Override + public void accept(double value) { + b.accept(value); + } + } + + return b -> new BoxingAdapter(b); + } + + @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleNullPointerException(String description, Collection exp, Supplier s) { + executeAndCatch(NullPointerException.class, () -> s.get().forEachRemaining((DoubleConsumer) null)); + executeAndCatch(NullPointerException.class, () -> s.get().tryAdvance((DoubleConsumer) null)); + } + + @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleForEach(String description, Collection exp, Supplier s) { + testForEach(exp, s, doubleBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleTryAdvance(String description, Collection exp, Supplier s) { + testTryAdvance(exp, s, doubleBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleMixedTryAdvanceForEach(String description, Collection exp, Supplier s) { + testMixedTryAdvanceForEach(exp, s, doubleBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleMixedTraverseAndSplit(String description, Collection exp, Supplier s) { + testMixedTraverseAndSplit(exp, s, doubleBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleSplitAfterFullTraversal(String description, Collection exp, Supplier s) { + testSplitAfterFullTraversal(s, doubleBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleSplitOnce(String description, Collection exp, Supplier s) { + testSplitOnce(exp, s, doubleBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleSplitSixDeep(String description, Collection exp, Supplier s) { + testSplitSixDeep(exp, s, doubleBoxingConsumer()); + } + + @Test(dataProvider = "Spliterator.OfDouble") + public void testDoubleSplitUntilNull(String description, Collection exp, Supplier s) { + testSplitUntilNull(exp, s, doubleBoxingConsumer()); + } + + // + + private static > void testForEach( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + ArrayList fromForEach = new ArrayList<>(); + spliterator = supplier.get(); + Consumer addToFromForEach = boxingAdapter.apply(fromForEach::add); + spliterator.forEachRemaining(addToFromForEach); + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + // Assert that tryAdvance now produce no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + // assert that size, tryAdvance, and forEach are consistent + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, exp.size()); + } + assertEquals(fromForEach.size(), exp.size()); + + assertContents(fromForEach, exp, isOrdered); + } + + private static > void testTryAdvance( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + spliterator = supplier.get(); + ArrayList fromTryAdvance = new ArrayList<>(); + Consumer addToFromTryAdvance = boxingAdapter.apply(fromTryAdvance::add); + while (spliterator.tryAdvance(addToFromTryAdvance)) { } + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + // Assert that tryAdvance now produce no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + // assert that size, tryAdvance, and forEach are consistent + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, exp.size()); + } + assertEquals(fromTryAdvance.size(), exp.size()); + + assertContents(fromTryAdvance, exp, isOrdered); + } + + private static > void testMixedTryAdvanceForEach( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + // tryAdvance first few elements, then forEach rest + ArrayList dest = new ArrayList<>(); + spliterator = supplier.get(); + Consumer addToDest = boxingAdapter.apply(dest::add); + for (int i = 0; i < 10 && spliterator.tryAdvance(addToDest); i++) { } + spliterator.forEachRemaining(addToDest); + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + // Assert that tryAdvance now produce no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, dest.size()); + } + assertEquals(dest.size(), exp.size()); + + if (isOrdered) { + assertEquals(dest, exp); + } + else { + assertContentsUnordered(dest, exp); + } + } + + private static > void testMixedTraverseAndSplit( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + ArrayList dest = new ArrayList<>(); + spliterator = supplier.get(); + Consumer b = boxingAdapter.apply(dest::add); + + Spliterator 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 > void testSplitAfterFullTraversal( + Supplier supplier, + UnaryOperator> boxingAdapter) { + // Full traversal using tryAdvance + Spliterator spliterator = supplier.get(); + while (spliterator.tryAdvance(boxingAdapter.apply(e -> { }))) { } + Spliterator split = spliterator.trySplit(); + assertNull(split); + + // Full traversal using forEach + spliterator = supplier.get(); + spliterator.forEachRemaining(boxingAdapter.apply(e -> { + })); + split = spliterator.trySplit(); + assertNull(split); + + // Full traversal using tryAdvance then forEach + spliterator = supplier.get(); + spliterator.tryAdvance(boxingAdapter.apply(e -> { })); + spliterator.forEachRemaining(boxingAdapter.apply(e -> { + })); + split = spliterator.trySplit(); + assertNull(split); + } + + private static > void testSplitOnce( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + ArrayList fromSplit = new ArrayList<>(); + Spliterator s1 = supplier.get(); + Spliterator s2 = s1.trySplit(); + long s1Size = s1.getExactSizeIfKnown(); + long s2Size = (s2 != null) ? s2.getExactSizeIfKnown() : 0; + Consumer addToFromSplit = boxingAdapter.apply(fromSplit::add); + if (s2 != null) + s2.forEachRemaining(addToFromSplit); + s1.forEachRemaining(addToFromSplit); + + if (sizeIfKnown >= 0) { + assertEquals(sizeIfKnown, fromSplit.size()); + if (s1Size >= 0 && s2Size >= 0) + assertEquals(sizeIfKnown, s1Size + s2Size); + } + assertContents(fromSplit, exp, isOrdered); + } + + private static > void testSplitSixDeep( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + S spliterator = supplier.get(); + boolean isOrdered = spliterator.hasCharacteristics(Spliterator.ORDERED); + + for (int depth=0; depth < 6; depth++) { + List dest = new ArrayList<>(); + spliterator = supplier.get(); + + assertSpliterator(spliterator); + + // verify splitting with forEach + visit(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false); + assertContents(dest, exp, isOrdered); + + // verify splitting with tryAdvance + dest.clear(); + spliterator = supplier.get(); + visit(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), true); + assertContents(dest, exp, isOrdered); + } + } + + private static > + void visit(int depth, int curLevel, + List dest, S spliterator, UnaryOperator> boxingAdapter, + int rootCharacteristics, boolean useTryAdvance) { + if (curLevel < depth) { + long beforeSize = spliterator.getExactSizeIfKnown(); + Spliterator split = spliterator.trySplit(); + if (split != null) { + assertSpliterator(split, rootCharacteristics); + assertSpliterator(spliterator, rootCharacteristics); + + if ((rootCharacteristics & Spliterator.SUBSIZED) != 0 && + (rootCharacteristics & Spliterator.SIZED) != 0) { + assertEquals(beforeSize, split.estimateSize() + spliterator.estimateSize()); + } + visit(depth, curLevel + 1, dest, split, boxingAdapter, rootCharacteristics, useTryAdvance); + } + visit(depth, curLevel + 1, dest, spliterator, boxingAdapter, rootCharacteristics, useTryAdvance); + } + else { + long sizeIfKnown = spliterator.getExactSizeIfKnown(); + if (useTryAdvance) { + Consumer addToDest = boxingAdapter.apply(dest::add); + int count = 0; + while (spliterator.tryAdvance(addToDest)) { + ++count; + } + + if (sizeIfKnown >= 0) + assertEquals(sizeIfKnown, count); + + // Assert that forEach now produces no elements + spliterator.forEachRemaining(boxingAdapter.apply( + e -> fail("Spliterator.forEach produced an element after spliterator exhausted: " + e))); + + Spliterator split = spliterator.trySplit(); + assertNull(split); + } + else { + List leafDest = new ArrayList<>(); + Consumer addToLeafDest = boxingAdapter.apply(leafDest::add); + spliterator.forEachRemaining(addToLeafDest); + + if (sizeIfKnown >= 0) + assertEquals(sizeIfKnown, leafDest.size()); + + // Assert that forEach now produces no elements + spliterator.tryAdvance(boxingAdapter.apply( + e -> fail("Spliterator.tryAdvance produced an element after spliterator exhausted: " + e))); + + Spliterator split = spliterator.trySplit(); + assertNull(split); + + dest.addAll(leafDest); + } + } + } + + private static > void testSplitUntilNull( + Collection exp, + Supplier supplier, + UnaryOperator> boxingAdapter) { + Spliterator s = supplier.get(); + boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED); + assertSpliterator(s); + + List splits = new ArrayList<>(); + Consumer c = boxingAdapter.apply(splits::add); + + testSplitUntilNull(new SplitNode(c, s)); + assertContents(splits, exp, isOrdered); + } + + private static class SplitNode { + // Constant for every node + final Consumer c; + final int rootCharacteristics; + + final Spliterator s; + + SplitNode(Consumer c, Spliterator s) { + this(c, s.characteristics(), s); + } + + private SplitNode(Consumer c, int rootCharacteristics, Spliterator s) { + this.c = c; + this.rootCharacteristics = rootCharacteristics; + this.s = s; + } + + SplitNode fromSplit(Spliterator split) { + return new SplitNode<>(c, rootCharacteristics, split); + } + } + + /** + * Set the maximum stack capacity to 0.25MB. This should be more than enough to detect a bad spliterator + * while not unduly disrupting test infrastructure given the test data sizes that are used are small. + * Note that j.u.c.ForkJoinPool sets the max queue size to 64M (1 << 26). + */ + private static final int MAXIMUM_STACK_CAPACITY = 1 << 18; // 0.25MB + + private static void testSplitUntilNull(SplitNode e) { + // Use an explicit stack to avoid a StackOverflowException when testing a Spliterator + // that when repeatedly split produces a right-balanced (and maybe degenerate) tree, or + // for a spliterator that is badly behaved. + Deque> stack = new ArrayDeque<>(); + stack.push(e); + + int iteration = 0; + while (!stack.isEmpty()) { + assertTrue(iteration++ < MAXIMUM_STACK_CAPACITY, "Exceeded maximum stack modification count of 1 << 18"); + + e = stack.pop(); + Spliterator parentAndRightSplit = e.s; + + long parentEstimateSize = parentAndRightSplit.estimateSize(); + assertTrue(parentEstimateSize >= 0, + String.format("Split size estimate %d < 0", parentEstimateSize)); + + long parentSize = parentAndRightSplit.getExactSizeIfKnown(); + Spliterator leftSplit = parentAndRightSplit.trySplit(); + if (leftSplit == null) { + parentAndRightSplit.forEachRemaining(e.c); + continue; + } + + assertSpliterator(leftSplit, e.rootCharacteristics); + assertSpliterator(parentAndRightSplit, e.rootCharacteristics); + + if (parentEstimateSize != Long.MAX_VALUE && leftSplit.estimateSize() > 0 && parentAndRightSplit.estimateSize() > 0) { + assertTrue(leftSplit.estimateSize() < parentEstimateSize, + String.format("Left split size estimate %d >= parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + assertTrue(parentAndRightSplit.estimateSize() < parentEstimateSize, + String.format("Right split size estimate %d >= parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + } + else { + assertTrue(leftSplit.estimateSize() <= parentEstimateSize, + String.format("Left split size estimate %d > parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + assertTrue(parentAndRightSplit.estimateSize() <= parentEstimateSize, + String.format("Right split size estimate %d > parent split size estimate %d", + leftSplit.estimateSize(), parentEstimateSize)); + } + + long leftSize = leftSplit.getExactSizeIfKnown(); + long rightSize = parentAndRightSplit.getExactSizeIfKnown(); + if (parentSize >= 0 && leftSize >= 0 && rightSize >= 0) + assertEquals(parentSize, leftSize + rightSize, + String.format("exact left split size %d + exact right split size %d != parent exact split size %d", + leftSize, rightSize, parentSize)); + + // Add right side to stack first so left side is popped off first + stack.push(e.fromSplit(parentAndRightSplit)); + stack.push(e.fromSplit(leftSplit)); + } + } + + private static void assertSpliterator(Spliterator s, int rootCharacteristics) { + if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) { + assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED), + "Child split is not SUBSIZED when root split is SUBSIZED"); + } + assertSpliterator(s); + } + + private static void assertSpliterator(Spliterator s) { + if (s.hasCharacteristics(Spliterator.SUBSIZED)) { + assertTrue(s.hasCharacteristics(Spliterator.SIZED)); + } + if (s.hasCharacteristics(Spliterator.SIZED)) { + assertTrue(s.estimateSize() != Long.MAX_VALUE); + assertTrue(s.getExactSizeIfKnown() >= 0); + } + try { + s.getComparator(); + assertTrue(s.hasCharacteristics(Spliterator.SORTED)); + } catch (IllegalStateException e) { + assertFalse(s.hasCharacteristics(Spliterator.SORTED)); + } + } + + private static void assertContents(Collection actual, Collection expected, boolean isOrdered) { + if (isOrdered) { + assertEquals(actual, expected); + } + else { + assertContentsUnordered(actual, expected); + } + } + + private static void assertContentsUnordered(Iterable actual, Iterable expected) { + assertEquals(toBoxedMultiset(actual), toBoxedMultiset(expected)); + } + + private static Map toBoxedMultiset(Iterable c) { + Map result = new HashMap<>(); + c.forEach(e -> { + if (result.containsKey(e)) result.put(e, result.get(e) + 1); + else result.put(e, 1); + }); + return result; + } + + private void executeAndCatch(Class expected, Runnable r) { + Exception caught = null; + try { + r.run(); + } + catch (Exception e) { + caught = e; + } + + assertNotNull(caught, + String.format("No Exception was thrown, expected an Exception of %s to be thrown", + expected.getName())); + assertTrue(expected.isInstance(caught), + String.format("Exception thrown %s not an instance of %s", + caught.getClass().getName(), expected.getName())); + } + +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java new file mode 100644 index 00000000000..8898c104df9 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2013, 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. + * + * 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.stream; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LambdaTestHelpers; +import java.util.stream.LongStream; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.StreamBuilder; +import java.util.stream.TestData; + +import static java.util.stream.Collectors.toList; + +@Test +public class StreamBuilderTest extends OpTestCase { + + List sizes = Arrays.asList(0, 1, 4, 16, 256, + 1023, 1024, 1025, + 2047, 2048, 2049, + 1024 * 32 - 1, 1024 * 32, 1024 * 32 + 1); + + @DataProvider(name = "sizes") + public Object[][] createStreamBuilders() { + return sizes.stream().map(i -> new Object[] { i }).toArray(Object[][]::new); + } + + private void checkException(Class ce, Runnable r) { + Exception caught = null; + try { + r.run(); + } catch (Exception e) { + caught = e; + } + + assertNotNull(caught); + assertTrue(ce.isInstance(caught)); + } + + private void checkISE(Runnable r) { + checkException(IllegalStateException.class, r); + } + + // + + @Test + public void testSingleton() { + TestData.OfRef data = TestData.Factory.ofSupplier("[0, 1)", + () -> Stream.of(1)); + + withData(data). + stream(s -> s). + expectedResult(Collections.singletonList(1)). + exercise(); + + withData(data). + stream(s -> s.map(LambdaTestHelpers.identity())). + expectedResult(Collections.singletonList(1)). + exercise(); + } + + @Test(dataProvider = "sizes") + public void testAfterBuilding(int size) { + StreamBuilder sb = Stream.builder(); + IntStream.range(0, size).boxed().forEach(sb); + sb.build(); + + checkISE(() -> sb.accept(1)); + checkISE(() -> sb.add(1)); + checkISE(() -> sb.build()); + } + + @Test(dataProvider = "sizes") + public void testStreamBuilder(int size) { + testStreamBuilder(size, (s) -> { + StreamBuilder sb = Stream.builder(); + IntStream.range(0, s).boxed().forEach(sb); + return sb.build(); + }); + + testStreamBuilder(size, (s) -> { + StreamBuilder sb = Stream.builder(); + IntStream.range(0, s).boxed().forEach(i -> { + StreamBuilder _sb = sb.add(i); + assertTrue(sb == _sb); + }); + return sb.build(); + }); + } + + private void testStreamBuilder(int size, Function> supplier) { + TestData.OfRef data = TestData.Factory.ofSupplier(String.format("[0, %d)", size), + () -> supplier.apply(size)); + + withData(data). + stream(s -> s). + expectedResult(IntStream.range(0, size).boxed().collect(toList())). + exercise(); + + withData(data). + stream(s -> s.map(LambdaTestHelpers.identity())). + expectedResult(IntStream.range(0, size).boxed().collect(toList())). + exercise(); + } + + // + + @Test + public void testIntSingleton() { + TestData.OfInt data = TestData.Factory.ofIntSupplier("[0, 1)", + () -> IntStream.of(1)); + + withData(data). + stream(s -> s). + expectedResult(Collections.singletonList(1)). + exercise(); + + withData(data). + stream(s -> s.map(i -> i)). + expectedResult(Collections.singletonList(1)). + exercise(); + } + + @Test(dataProvider = "sizes") + public void testIntAfterBuilding(int size) { + StreamBuilder.OfInt sb = IntStream.builder(); + IntStream.range(0, size).forEach(sb); + sb.build(); + + checkISE(() -> sb.accept(1)); + checkISE(() -> sb.add(1)); + checkISE(() -> sb.build()); + } + + @Test(dataProvider = "sizes") + public void testIntStreamBuilder(int size) { + testIntStreamBuilder(size, (s) -> { + StreamBuilder.OfInt sb = IntStream.builder(); + IntStream.range(0, s).forEach(sb); + return sb.build(); + }); + + testIntStreamBuilder(size, (s) -> { + StreamBuilder.OfInt sb = IntStream.builder(); + IntStream.range(0, s).forEach(i -> { + StreamBuilder.OfInt _sb = sb.add(i); + assertTrue(sb == _sb); + }); + return sb.build(); + }); + } + + private void testIntStreamBuilder(int size, Function supplier) { + TestData.OfInt data = TestData.Factory.ofIntSupplier(String.format("[0, %d)", size), + () -> supplier.apply(size)); + + withData(data). + stream(s -> s). + expectedResult(IntStream.range(0, size).toArray()). + exercise(); + + withData(data). + stream(s -> s.map(i -> i)). + expectedResult(IntStream.range(0, size).toArray()). + exercise(); + } + + // + + @Test + public void testLongSingleton() { + TestData.OfLong data = TestData.Factory.ofLongSupplier("[0, 1)", + () -> LongStream.of(1)); + + withData(data). + stream(s -> s). + expectedResult(Collections.singletonList(1L)). + exercise(); + + withData(data). + stream(s -> s.map(i -> i)). + expectedResult(Collections.singletonList(1L)). + exercise(); + } + + @Test(dataProvider = "sizes") + public void testLongAfterBuilding(int size) { + StreamBuilder.OfLong sb = LongStream.builder(); + LongStream.range(0, size).forEach(sb); + sb.build(); + + checkISE(() -> sb.accept(1)); + checkISE(() -> sb.add(1)); + checkISE(() -> sb.build()); + } + + @Test(dataProvider = "sizes") + public void testLongStreamBuilder(int size) { + testLongStreamBuilder(size, (s) -> { + StreamBuilder.OfLong sb = LongStream.builder(); + LongStream.range(0, s).forEach(sb); + return sb.build(); + }); + + testLongStreamBuilder(size, (s) -> { + StreamBuilder.OfLong sb = LongStream.builder(); + LongStream.range(0, s).forEach(i -> { + StreamBuilder.OfLong _sb = sb.add(i); + assertTrue(sb == _sb); + }); + return sb.build(); + }); + } + + private void testLongStreamBuilder(int size, Function supplier) { + TestData.OfLong data = TestData.Factory.ofLongSupplier(String.format("[0, %d)", size), + () -> supplier.apply(size)); + + withData(data). + stream(s -> s). + expectedResult(LongStream.range(0, size).toArray()). + exercise(); + + withData(data). + stream(s -> s.map(i -> i)). + expectedResult(LongStream.range(0, size).toArray()). + exercise(); + } + + // + + @Test + public void testDoubleSingleton() { + TestData.OfDouble data = TestData.Factory.ofDoubleSupplier("[0, 1)", () -> DoubleStream.of(1)); + + withData(data). + stream(s -> s). + expectedResult(Collections.singletonList(1.0)). + exercise(); + + withData(data). + stream(s -> s.map(i -> i)). + expectedResult(Collections.singletonList(1.0)). + exercise(); + } + + @Test(dataProvider = "sizes") + public void testDoubleAfterBuilding(int size) { + StreamBuilder.OfDouble sb = DoubleStream.builder(); + DoubleStream.range(0, size).forEach(sb); + sb.build(); + + checkISE(() -> sb.accept(1)); + checkISE(() -> sb.add(1)); + checkISE(() -> sb.build()); + } + + @Test(dataProvider = "sizes") + public void testDoubleStreamBuilder(int size) { + testDoubleStreamBuilder(size, (s) -> { + StreamBuilder.OfDouble sb = DoubleStream.builder(); + DoubleStream.range(0, s).forEach(sb); + return sb.build(); + }); + + testDoubleStreamBuilder(size, (s) -> { + StreamBuilder.OfDouble sb = DoubleStream.builder(); + DoubleStream.range(0, s).forEach(i -> { + StreamBuilder.OfDouble _sb = sb.add(i); + assertTrue(sb == _sb); + }); + return sb.build(); + }); + } + + private void testDoubleStreamBuilder(int size, Function supplier) { + TestData.OfDouble data = TestData.Factory.ofDoubleSupplier(String.format("[0, %d)", size), + () -> supplier.apply(size)); + + withData(data). + stream(s -> s). + expectedResult(DoubleStream.range(0, size).toArray()). + exercise(); + + withData(data). + stream(s -> s.map(i -> i)). + expectedResult(DoubleStream.range(0, size).toArray()). + exercise(); + } + +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamLinkTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamLinkTest.java new file mode 100644 index 00000000000..e7629adae88 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamLinkTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.stream.*; + +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +@Test +public class StreamLinkTest extends OpTestCase { + + private Function apply(int n, Function f) { + return s -> { + for (int i = 0; i < n; i++) { + s = f.apply(s); + } + return s; + }; + } + + private List sizes = Arrays.asList(0, 1, 2, 3, 4, 5, 255, 1000); + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testManyStreams(String name, TestData.OfRef data) { + for (int n : sizes) { + List expected = data.stream().map(e -> (Integer) (e + n)).collect(Collectors.toList()); + + withData(data). + stream(apply(n, (Stream s) -> s.map(e -> (Integer) (e + 1)))). + expectedResult(expected). + exercise(); + } + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntManyStreams(String name, TestData.OfInt data) { + for (int n : sizes) { + int[] expected = data.stream().map(e -> e + n).toArray(); + + withData(data). + stream(apply(n, (IntStream s) -> s.map(e -> e + 1))). + expectedResult(expected). + exercise(); + } + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongManyStreams(String name, TestData.OfLong data) { + for (int n : sizes) { + long[] expected = data.stream().map(e -> e + n).toArray(); + + withData(data). + stream(apply(n, (LongStream s) -> s.map(e -> e + 1L))). + expectedResult(expected). + exercise(); + } + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleManyStreams(String name, TestData.OfDouble data) { + for (int n : sizes) { + double[] expected = data.stream().map(e -> accumulate(e, n)).toArray(); + + withData(data). + stream(apply(n, (DoubleStream s) -> s.map(e -> e + 1.0))). + expectedResult(expected). + exercise(); + } + } + private double accumulate(double e, int n) { + while (n-- > 0) { + e = e + 1.0; + } + return e; + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamParSeqTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamParSeqTest.java new file mode 100644 index 00000000000..650edc1f1cb --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamParSeqTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013, 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. + * + * 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.stream; + +import org.testng.annotations.Test; + +import java.util.Arrays; +import java.util.stream.Stream; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +@Test +public class StreamParSeqTest { + + public void testParSeq() { + Stream s = Arrays.asList(1, 2, 3, 4).stream().parallel(); + assertTrue(s.isParallel()); + + s = s.sequential(); + assertFalse(s.isParallel()); + + s = s.sequential(); + assertFalse(s.isParallel()); + + s = s.parallel(); + assertTrue(s.isParallel()); + + s = s.parallel(); + assertTrue(s.isParallel()); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java new file mode 100644 index 00000000000..bc56b2f77ec --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.Function; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.function.UnaryOperator; +import java.util.stream.DoubleStream; +import java.util.stream.DoubleStreamTestDataProvider; +import java.util.stream.IntStream; +import java.util.stream.IntStreamTestDataProvider; +import java.util.stream.LambdaTestHelpers; +import java.util.stream.LongStream; +import java.util.stream.LongStreamTestDataProvider; +import java.util.stream.OpTestCase; +import java.util.stream.SpliteratorTestHelper; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import java.util.stream.StreamTestDataProvider; +import java.util.stream.TestData; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import static java.util.stream.LambdaTestHelpers.countTo; +import static java.util.stream.LambdaTestHelpers.dpEven; +import static java.util.stream.LambdaTestHelpers.ipEven; +import static java.util.stream.LambdaTestHelpers.irDoubler; +import static java.util.stream.LambdaTestHelpers.lpEven; +import static java.util.stream.LambdaTestHelpers.mDoubler; +import static java.util.stream.LambdaTestHelpers.pEven; +import static java.util.stream.LambdaTestHelpers.permuteStreamFunctions; + +@Test +public class StreamSpliteratorTest extends OpTestCase { + + private static class ProxyNoExactSizeSpliterator implements Spliterator { + final Spliterator sp; + final boolean proxyEstimateSize; + int splits = 0; + int prefixSplits = 0; + + long sizeOnTraversal = -1; + + ProxyNoExactSizeSpliterator(Spliterator sp, boolean proxyEstimateSize) { + this.sp = sp; + this.proxyEstimateSize = proxyEstimateSize; + } + + @Override + public Spliterator trySplit() { + splits++; + Spliterator prefix = sp.trySplit(); + if (prefix != null) + prefixSplits++; + return prefix; + } + + @Override + public boolean tryAdvance(Consumer consumer) { + if (sizeOnTraversal == -1) + sizeOnTraversal = sp.getExactSizeIfKnown(); + return sp.tryAdvance(consumer); + } + + @Override + public void forEachRemaining(Consumer consumer) { + sizeOnTraversal = sp.getExactSizeIfKnown(); + sp.forEachRemaining(consumer); + } + + @Override + public long estimateSize() { + return proxyEstimateSize ? sp.estimateSize() : Long.MAX_VALUE; + } + + @Override + public Comparator getComparator() { + return sp.getComparator(); + } + + @Override + public int characteristics() { + if (proxyEstimateSize) + return sp.characteristics(); + else + return sp.characteristics() & ~(Spliterator.SUBSIZED | Spliterator.SIZED); + } + + private static class OfInt extends ProxyNoExactSizeSpliterator implements Spliterator.OfInt { + final Spliterator.OfInt psp; + + private OfInt(Spliterator.OfInt sp, boolean proxyEstimateSize) { + super(sp, proxyEstimateSize); + this.psp = sp; + } + + @Override + public Spliterator.OfInt trySplit() { + splits++; + Spliterator.OfInt prefix = psp.trySplit(); + if (prefix != null) + prefixSplits++; + return prefix; + } + + @Override + public boolean tryAdvance(Consumer consumer) { + return Spliterator.OfInt.super.tryAdvance(consumer); + } + + @Override + public void forEachRemaining(Consumer consumer) { + Spliterator.OfInt.super.forEachRemaining(consumer); + } + + @Override + public boolean tryAdvance(IntConsumer consumer) { + if (sizeOnTraversal == -1) + sizeOnTraversal = sp.getExactSizeIfKnown(); + return psp.tryAdvance(consumer); + } + + @Override + public void forEachRemaining(IntConsumer consumer) { + sizeOnTraversal = sp.getExactSizeIfKnown(); + psp.forEachRemaining(consumer); + } + } + + private static class OfLong extends ProxyNoExactSizeSpliterator implements Spliterator.OfLong { + final Spliterator.OfLong psp; + + private OfLong(Spliterator.OfLong sp, boolean proxyEstimateSize) { + super(sp, proxyEstimateSize); + this.psp = sp; + } + + @Override + public Spliterator.OfLong trySplit() { + splits++; + Spliterator.OfLong prefix = psp.trySplit(); + if (prefix != null) + prefixSplits++; + return prefix; + } + + @Override + public boolean tryAdvance(Consumer consumer) { + return Spliterator.OfLong.super.tryAdvance(consumer); + } + + @Override + public void forEachRemaining(Consumer consumer) { + Spliterator.OfLong.super.forEachRemaining(consumer); + } + + @Override + public boolean tryAdvance(LongConsumer consumer) { + if (sizeOnTraversal == -1) + sizeOnTraversal = sp.getExactSizeIfKnown(); + return psp.tryAdvance(consumer); + } + + @Override + public void forEachRemaining(LongConsumer consumer) { + sizeOnTraversal = sp.getExactSizeIfKnown(); + psp.forEachRemaining(consumer); + } + } + + private static class OfDouble extends ProxyNoExactSizeSpliterator + implements Spliterator.OfDouble { + final Spliterator.OfDouble psp; + + private OfDouble(Spliterator.OfDouble sp, boolean proxyEstimateSize) { + super(sp, proxyEstimateSize); + this.psp = sp; + } + + @Override + public Spliterator.OfDouble trySplit() { + splits++; + Spliterator.OfDouble prefix = psp.trySplit(); + if (prefix != null) + prefixSplits++; + return prefix; + } + + @Override + public boolean tryAdvance(Consumer consumer) { + return Spliterator.OfDouble.super.tryAdvance(consumer); + } + + @Override + public void forEachRemaining(Consumer consumer) { + Spliterator.OfDouble.super.forEachRemaining(consumer); + } + + @Override + public boolean tryAdvance(DoubleConsumer consumer) { + if (sizeOnTraversal == -1) + sizeOnTraversal = sp.getExactSizeIfKnown(); + return psp.tryAdvance(consumer); + } + + @Override + public void forEachRemaining(DoubleConsumer consumer) { + sizeOnTraversal = sp.getExactSizeIfKnown(); + psp.forEachRemaining(consumer); + } + } + } + + public void testSplitting() { + // Size is assumed to be larger than the target size for no splitting + // @@@ Need way to obtain the target size + List l = countTo(1000); + + List>> terminalOps = Arrays.asList( + s -> s.toArray(), + s -> s.forEach(e -> { }), + s -> s.reduce(Integer::sum) + ); + + List>> intermediateOps = Arrays.asList( + s -> s.parallel(), + // The following ensures the wrapping spliterator is tested + s -> s.map(LambdaTestHelpers.identity()).parallel() + ); + + for (Consumer> terminalOp : terminalOps) { + for (UnaryOperator> intermediateOp : intermediateOps) { + for (boolean proxyEstimateSize : new boolean[]{false, true}) { + Spliterator sp = intermediateOp.apply(l.stream()).spliterator(); + ProxyNoExactSizeSpliterator psp = new ProxyNoExactSizeSpliterator<>(sp, proxyEstimateSize); + Stream s = StreamSupport.parallelStream(psp); + terminalOp.accept(s); + Assert.assertTrue(psp.splits > 0, + String.format("Number of splits should be greater that zero when proxyEstimateSize is %s", + proxyEstimateSize)); + Assert.assertTrue(psp.prefixSplits > 0, + String.format("Number of non-null prefix splits should be greater that zero when proxyEstimateSize is %s", + proxyEstimateSize)); + Assert.assertTrue(psp.sizeOnTraversal < l.size(), + String.format("Size on traversal of last split should be less than the size of the list, %d, when proxyEstimateSize is %s", + l.size(), proxyEstimateSize)); + } + } + } + } + + @Test(dataProvider = "StreamTestData", + dataProviderClass = StreamTestDataProvider.class, + groups = { "serialization-hostile" }) + public void testStreamSpliterators(String name, TestData.OfRef data) { + for (Function, Stream> f : streamFunctions()) { + withData(data). + stream((Stream in) -> { + Stream out = f.apply(in); + return StreamSupport.stream(() -> out.spliterator(), OpTestCase.getStreamFlags(out)); + }). + exercise(); + + withData(data). + stream((Stream in) -> { + Stream out = f.apply(in); + return StreamSupport.parallelStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out)); + }). + exercise(); + } + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testSpliterators(String name, TestData.OfRef data) { + for (Function, Stream> f : streamFunctions()) { + SpliteratorTestHelper.testSpliterator(() -> f.apply(data.stream()).spliterator()); + } + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testParSpliterators(String name, TestData.OfRef data) { + for (Function, Stream> f : streamFunctions()) { + SpliteratorTestHelper.testSpliterator(() -> f.apply(data.parallelStream()).spliterator()); + } + } + + private List, Stream>> streamFunctions; + + List, Stream>> streamFunctions() { + if (streamFunctions == null) { + List, Stream>> opFunctions = Arrays.asList( + s -> s.filter(pEven), + s -> s.map(mDoubler), + // @@@ Add distinct once asserting results with or without order + // is correctly supported +// s -> s.distinct(), + s -> s.sorted()); + + streamFunctions = permuteStreamFunctions(opFunctions); + } + + return streamFunctions; + } + + // + + public void testIntSplitting() { + List> terminalOps = Arrays.asList( + s -> s.toArray(), + s -> s.forEach(e -> {}), + s -> s.reduce(Integer::sum) + ); + + List> intermediateOps = Arrays.asList( + s -> s.parallel(), + // The following ensures the wrapping spliterator is tested + s -> s.map(i -> i).parallel() + ); + + for (Consumer terminalOp : terminalOps) { + for (UnaryOperator intermediateOp : intermediateOps) { + for (boolean proxyEstimateSize : new boolean[]{false, true}) { + // Size is assumed to be larger than the target size for no splitting + // @@@ Need way to obtain the target size + Spliterator.OfInt sp = intermediateOp.apply(IntStream.range(0, 1000)).spliterator(); + ProxyNoExactSizeSpliterator.OfInt psp = new ProxyNoExactSizeSpliterator.OfInt(sp, proxyEstimateSize); + IntStream s = StreamSupport.intParallelStream(psp); + terminalOp.accept(s); + Assert.assertTrue(psp.splits > 0, + String.format("Number of splits should be greater that zero when proxyEstimateSize is %s", + proxyEstimateSize)); + Assert.assertTrue(psp.prefixSplits > 0, + String.format("Number of non-null prefix splits should be greater that zero when proxyEstimateSize is %s", + proxyEstimateSize)); + Assert.assertTrue(psp.sizeOnTraversal < 1000, + String.format("Size on traversal of last split should be less than the size of the list, %d, when proxyEstimateSize is %s", + 1000, proxyEstimateSize)); + } + } + } + } + + @Test(dataProvider = "IntStreamTestData", + dataProviderClass = IntStreamTestDataProvider.class, + groups = { "serialization-hostile" }) + public void testIntStreamSpliterators(String name, TestData.OfInt data) { + for (Function f : intStreamFunctions()) { + withData(data). + stream(in -> { + IntStream out = f.apply(in); + return StreamSupport.intStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out)); + }). + exercise(); + + withData(data). + stream((in) -> { + IntStream out = f.apply(in); + return StreamSupport.intParallelStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out)); + }). + exercise(); + } + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntSpliterators(String name, TestData.OfInt data) { + for (Function f : intStreamFunctions()) { + SpliteratorTestHelper.testIntSpliterator(() -> f.apply(data.stream()).spliterator()); + } + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntParSpliterators(String name, TestData.OfInt data) { + for (Function f : intStreamFunctions()) { + SpliteratorTestHelper.testIntSpliterator(() -> f.apply(data.parallelStream()).spliterator()); + } + } + + private List> intStreamFunctions; + + List> intStreamFunctions() { + if (intStreamFunctions == null) { + List> opFunctions = Arrays.asList( + s -> s.filter(ipEven), + s -> s.map(irDoubler), + s -> s.sorted()); + + intStreamFunctions = permuteStreamFunctions(opFunctions); + } + + return intStreamFunctions; + } + + // + + public void testLongSplitting() { + List> terminalOps = Arrays.asList( + s -> s.toArray(), + s -> s.forEach(e -> {}), + s -> s.reduce(Long::sum) + ); + + List> intermediateOps = Arrays.asList( + s -> s.parallel(), + // The following ensures the wrapping spliterator is tested + s -> s.map(i -> i).parallel() + ); + + for (Consumer terminalOp : terminalOps) { + for (UnaryOperator intermediateOp : intermediateOps) { + for (boolean proxyEstimateSize : new boolean[]{false, true}) { + // Size is assumed to be larger than the target size for no splitting + // @@@ Need way to obtain the target size + Spliterator.OfLong sp = intermediateOp.apply(LongStream.range(0, 1000)).spliterator(); + ProxyNoExactSizeSpliterator.OfLong psp = new ProxyNoExactSizeSpliterator.OfLong(sp, proxyEstimateSize); + LongStream s = StreamSupport.longParallelStream(psp); + terminalOp.accept(s); + Assert.assertTrue(psp.splits > 0, + String.format("Number of splits should be greater that zero when proxyEstimateSize is %s", + proxyEstimateSize)); + Assert.assertTrue(psp.prefixSplits > 0, + String.format("Number of non-null prefix splits should be greater that zero when proxyEstimateSize is %s", + proxyEstimateSize)); + Assert.assertTrue(psp.sizeOnTraversal < 1000, + String.format("Size on traversal of last split should be less than the size of the list, %d, when proxyEstimateSize is %s", + 1000, proxyEstimateSize)); + } + } + } + } + + @Test(dataProvider = "LongStreamTestData", + dataProviderClass = LongStreamTestDataProvider.class, + groups = { "serialization-hostile" }) + public void testLongStreamSpliterators(String name, TestData.OfLong data) { + for (Function f : longStreamFunctions()) { + withData(data). + stream(in -> { + LongStream out = f.apply(in); + return StreamSupport.longStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out)); + }). + exercise(); + + withData(data). + stream((in) -> { + LongStream out = f.apply(in); + return StreamSupport.longParallelStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out)); + }). + exercise(); + } + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongSpliterators(String name, TestData.OfLong data) { + for (Function f : longStreamFunctions()) { + SpliteratorTestHelper.testLongSpliterator(() -> f.apply(data.stream()).spliterator()); + } + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongParSpliterators(String name, TestData.OfLong data) { + for (Function f : longStreamFunctions()) { + SpliteratorTestHelper.testLongSpliterator(() -> f.apply(data.parallelStream()).spliterator()); + } + } + + private List> longStreamFunctions; + + List> longStreamFunctions() { + if (longStreamFunctions == null) { + List> opFunctions = Arrays.asList( + s -> s.filter(lpEven), + s -> s.map(x -> x * 2L), + s -> s.sorted()); + + longStreamFunctions = permuteStreamFunctions(opFunctions); + } + + return longStreamFunctions; + } + + // + + public void testDoubleSplitting() { + List> terminalOps = Arrays.asList( + s -> s.toArray(), + s -> s.forEach(e -> {}), + s -> s.reduce(Double::sum) + ); + + List> intermediateOps = Arrays.asList( + s -> s.parallel(), + // The following ensures the wrapping spliterator is tested + s -> s.map(i -> i).parallel() + ); + + for (Consumer terminalOp : terminalOps) { + for (UnaryOperator intermediateOp : intermediateOps) { + for (boolean proxyEstimateSize : new boolean[]{false, true}) { + // Size is assumed to be larger than the target size for no splitting + // @@@ Need way to obtain the target size + Spliterator.OfDouble sp = intermediateOp.apply(DoubleStream.range(0, 1000)).spliterator(); + ProxyNoExactSizeSpliterator.OfDouble psp = new ProxyNoExactSizeSpliterator.OfDouble(sp, proxyEstimateSize); + DoubleStream s = StreamSupport.doubleParallelStream(psp); + terminalOp.accept(s); + Assert.assertTrue(psp.splits > 0, + String.format("Number of splits should be greater that zero when proxyEstimateSize is %s", + proxyEstimateSize)); + Assert.assertTrue(psp.prefixSplits > 0, + String.format("Number of non-null prefix splits should be greater that zero when proxyEstimateSize is %s", + proxyEstimateSize)); + Assert.assertTrue(psp.sizeOnTraversal < 1000, + String.format("Size on traversal of last split should be less than the size of the list, %d, when proxyEstimateSize is %s", + 1000, proxyEstimateSize)); + } + } + } + } + + @Test(dataProvider = "DoubleStreamTestData", + dataProviderClass = DoubleStreamTestDataProvider.class, + groups = { "serialization-hostile" }) + public void testDoubleStreamSpliterators(String name, TestData.OfDouble data) { + for (Function f : doubleStreamFunctions()) { + withData(data). + stream(in -> { + DoubleStream out = f.apply(in); + return StreamSupport.doubleStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out)); + }). + exercise(); + + withData(data). + stream((in) -> { + DoubleStream out = f.apply(in); + return StreamSupport.doubleParallelStream(() -> out.spliterator(), OpTestCase.getStreamFlags(out)); + }). + exercise(); + } + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleSpliterators(String name, TestData.OfDouble data) { + for (Function f : doubleStreamFunctions()) { + SpliteratorTestHelper.testDoubleSpliterator(() -> f.apply(data.stream()).spliterator()); + } + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleParSpliterators(String name, TestData.OfDouble data) { + for (Function f : doubleStreamFunctions()) { + SpliteratorTestHelper.testDoubleSpliterator(() -> f.apply(data.parallelStream()).spliterator()); + } + } + + private List> doubleStreamFunctions; + + List> doubleStreamFunctions() { + if (doubleStreamFunctions == null) { + List> opFunctions = Arrays.asList( + s -> s.filter(dpEven), + s -> s.map(x -> x * 2.0), + s -> s.sorted()); + + doubleStreamFunctions = permuteStreamFunctions(opFunctions); + } + + return doubleStreamFunctions; + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SummaryStatisticsTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SummaryStatisticsTest.java new file mode 100644 index 00000000000..fb5a92fcf0c --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/SummaryStatisticsTest.java @@ -0,0 +1,88 @@ +/* + * 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. + * + * 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.stream; + +import java.util.ArrayList; +import java.util.DoubleSummaryStatistics; +import java.util.IntSummaryStatistics; +import java.util.List; +import java.util.LongSummaryStatistics; +import java.util.stream.Collectors; +import java.util.stream.OpTestCase; + +import org.testng.annotations.Test; + +import static java.util.stream.LambdaTestHelpers.countTo; + +/** + * TestSummaryStatistics + * + * @author Brian Goetz + */ +@Test +public class SummaryStatisticsTest extends OpTestCase { + public void testIntStatistics() { + List instances = new ArrayList<>(); + instances.add(countTo(1000).stream().collect(Collectors.toIntSummaryStatistics(i -> i))); + instances.add(countTo(1000).stream().mapToInt(i -> i).summaryStatistics()); + instances.add(countTo(1000).parallelStream().collect(Collectors.toIntSummaryStatistics(i -> i))); + instances.add(countTo(1000).parallelStream().mapToInt(i -> i).summaryStatistics()); + + for (IntSummaryStatistics stats : instances) { + assertEquals(stats.getCount(), 1000); + assertEquals(stats.getSum(), countTo(1000).stream().mapToInt(i -> i).sum()); + assertEquals(stats.getMax(), 1000); + assertEquals(stats.getMin(), 1); + } + } + + public void testLongStatistics() { + List instances = new ArrayList<>(); + instances.add(countTo(1000).stream().collect(Collectors.toLongSummaryStatistics(i -> i))); + instances.add(countTo(1000).stream().mapToLong(i -> i).summaryStatistics()); + instances.add(countTo(1000).parallelStream().collect(Collectors.toLongSummaryStatistics(i -> i))); + instances.add(countTo(1000).parallelStream().mapToLong(i -> i).summaryStatistics()); + + for (LongSummaryStatistics stats : instances) { + assertEquals(stats.getCount(), 1000); + assertEquals(stats.getSum(), (long) countTo(1000).stream().mapToInt(i -> i).sum()); + assertEquals(stats.getMax(), 1000L); + assertEquals(stats.getMin(), 1L); + } + } + + public void testDoubleStatistics() { + List instances = new ArrayList<>(); + instances.add(countTo(1000).stream().collect(Collectors.toDoubleSummaryStatistics(i -> i))); + instances.add(countTo(1000).stream().mapToDouble(i -> i).summaryStatistics()); + instances.add(countTo(1000).parallelStream().collect(Collectors.toDoubleSummaryStatistics(i -> i))); + instances.add(countTo(1000).parallelStream().mapToDouble(i -> i).summaryStatistics()); + + for (DoubleSummaryStatistics stats : instances) { + assertEquals(stats.getCount(), 1000); + assertEquals(stats.getSum(), (double) countTo(1000).stream().mapToInt(i -> i).sum()); + assertEquals(stats.getMax(), 1000.0); + assertEquals(stats.getMin(), 1.0); + } + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/TabulatorsTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/TabulatorsTest.java new file mode 100644 index 00000000000..2dd8c55016e --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/TabulatorsTest.java @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import java.util.stream.LambdaTestHelpers; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.StreamOpFlagTestHelper; +import java.util.stream.StreamTestDataProvider; +import java.util.stream.TestData; + +import org.testng.annotations.Test; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.groupingByConcurrent; +import static java.util.stream.Collectors.partitioningBy; +import static java.util.stream.Collectors.reducing; +import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toList; +import static java.util.stream.LambdaTestHelpers.assertContents; +import static java.util.stream.LambdaTestHelpers.assertContentsUnordered; +import static java.util.stream.LambdaTestHelpers.mDoubler; + +/** + * TabulatorsTest + * + * @author Brian Goetz + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public class TabulatorsTest extends OpTestCase { + // There are 8 versions of groupingBy: + // groupingBy: { map supplier, not } x { downstream collector, not } x { concurrent, not } + // There are 2 versions of partition: { map supplier, not } + // There are 4 versions of toMap + // mappedTo(function, mapSupplier?, mergeFunction?) + // Each variety needs at least one test + // Plus a variety of multi-level tests (groupBy(..., partition), partition(..., groupBy)) + // Plus negative tests for mapping to null + // Each test should be matched by a nest of asserters (see TabulationAssertion...) + + + private static abstract class TabulationAssertion { + abstract void assertValue(U value, + Supplier> source, + boolean ordered) throws ReflectiveOperationException; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + static class GroupedMapAssertion> extends TabulationAssertion { + private final Class clazz; + private final Function classifier; + private final TabulationAssertion downstream; + + protected GroupedMapAssertion(Function classifier, + Class clazz, + TabulationAssertion downstream) { + this.clazz = clazz; + this.classifier = classifier; + this.downstream = downstream; + } + + void assertValue(M map, + Supplier> source, + boolean ordered) throws ReflectiveOperationException { + if (!clazz.isAssignableFrom(map.getClass())) + fail(String.format("Class mismatch in GroupedMapAssertion: %s, %s", clazz, map.getClass())); + assertContentsUnordered(map.keySet(), source.get().map(classifier).collect(Collectors.toSet())); + for (Map.Entry entry : map.entrySet()) { + K key = entry.getKey(); + downstream.assertValue(entry.getValue(), + () -> source.get().filter(e -> classifier.apply(e).equals(key)), + ordered); + } + } + } + + static class PartitionAssertion extends TabulationAssertion> { + private final Predicate predicate; + private final TabulationAssertion downstream; + + protected PartitionAssertion(Predicate predicate, + TabulationAssertion downstream) { + this.predicate = predicate; + this.downstream = downstream; + } + + void assertValue(Map map, + Supplier> source, + boolean ordered) throws ReflectiveOperationException { + if (!Map.class.isAssignableFrom(map.getClass())) + fail(String.format("Class mismatch in PartitionAssertion: %s", map.getClass())); + assertEquals(2, map.size()); + downstream.assertValue(map.get(true), () -> source.get().filter(predicate), ordered); + downstream.assertValue(map.get(false), () -> source.get().filter(predicate.negate()), ordered); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + static class ListAssertion extends TabulationAssertion> { + @Override + void assertValue(List value, Supplier> source, boolean ordered) + throws ReflectiveOperationException { + if (!List.class.isAssignableFrom(value.getClass())) + fail(String.format("Class mismatch in ListAssertion: %s", value.getClass())); + Stream stream = source.get(); + List result = new ArrayList<>(); + for (Iterator it = stream.iterator(); it.hasNext(); ) // avoid capturing result::add + result.add(it.next()); + if (StreamOpFlagTestHelper.isStreamOrdered(stream) && ordered) + assertContents(value, result); + else + assertContentsUnordered(value, result); + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + static class CollectionAssertion extends TabulationAssertion> { + private final Class clazz; + private final boolean targetOrdered; + + protected CollectionAssertion(Class clazz, boolean targetOrdered) { + this.clazz = clazz; + this.targetOrdered = targetOrdered; + } + + @Override + void assertValue(Collection value, Supplier> source, boolean ordered) + throws ReflectiveOperationException { + if (!clazz.isAssignableFrom(value.getClass())) + fail(String.format("Class mismatch in CollectionAssertion: %s, %s", clazz, value.getClass())); + Stream stream = source.get(); + Collection result = clazz.newInstance(); + for (Iterator it = stream.iterator(); it.hasNext(); ) // avoid capturing result::add + result.add(it.next()); + if (StreamOpFlagTestHelper.isStreamOrdered(stream) && targetOrdered && ordered) + assertContents(value, result); + else + assertContentsUnordered(value, result); + } + } + + static class ReduceAssertion extends TabulationAssertion { + private final U identity; + private final Function mapper; + private final BinaryOperator reducer; + + ReduceAssertion(U identity, Function mapper, BinaryOperator reducer) { + this.identity = identity; + this.mapper = mapper; + this.reducer = reducer; + } + + @Override + void assertValue(U value, Supplier> source, boolean ordered) + throws ReflectiveOperationException { + Optional reduced = source.get().map(mapper).reduce(reducer); + if (value == null) + assertTrue(!reduced.isPresent()); + else if (!reduced.isPresent()) { + assertEquals(value, identity); + } + else { + assertEquals(value, reduced.get()); + } + } + } + + private + void exerciseMapTabulation(TestData> data, + Collector collector, + TabulationAssertion assertion) + throws ReflectiveOperationException { + boolean ordered = data.isOrdered() + && !collector.characteristics().contains(Collector.Characteristics.UNORDERED); + M m = withData(data) + .terminal(s -> s.collect(collector)) + .parallelEqualityAsserter(ordered ? LambdaTestHelpers::assertContentsEqual : this::nestedMapEqualityAssertion) + .exercise(); + assertion.assertValue(m, () -> data.stream(), ordered); + m = withData(data) + .terminal(s -> s.unordered().collect(collector)) + .parallelEqualityAsserter(this::nestedMapEqualityAssertion) + .exercise(); + assertion.assertValue(m, () -> data.stream(), false); + } + + private void nestedMapEqualityAssertion(Object o1, Object o2) { + if (o1 instanceof Map) { + Map m1 = (Map) o1; + Map m2 = (Map) o2; + assertContentsUnordered(m1.keySet(), m2.keySet()); + for (Object k : m1.keySet()) + nestedMapEqualityAssertion(m1.get(k), m2.get(k)); + } + else if (o1 instanceof Collection) { + assertContentsUnordered(((Collection) o1), ((Collection) o2)); + } + else + assertEquals(o1, o2); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testSimpleGroupBy(String name, TestData.OfRef data) throws ReflectiveOperationException { + Function classifier = i -> i % 3; + + // Single-level groupBy + exerciseMapTabulation(data, groupingBy(classifier), + new GroupedMapAssertion<>(classifier, HashMap.class, + new ListAssertion<>())); + exerciseMapTabulation(data, groupingByConcurrent(classifier), + new GroupedMapAssertion<>(classifier, ConcurrentHashMap.class, + new ListAssertion<>())); + + // With explicit constructors + exerciseMapTabulation(data, + groupingBy(classifier, TreeMap::new, toCollection(HashSet::new)), + new GroupedMapAssertion<>(classifier, TreeMap.class, + new CollectionAssertion(HashSet.class, false))); + exerciseMapTabulation(data, + groupingByConcurrent(classifier, ConcurrentSkipListMap::new, + toCollection(HashSet::new)), + new GroupedMapAssertion<>(classifier, ConcurrentSkipListMap.class, + new CollectionAssertion(HashSet.class, false))); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testTwoLevelGroupBy(String name, TestData.OfRef data) throws ReflectiveOperationException { + Function classifier = i -> i % 6; + Function classifier2 = i -> i % 23; + + // Two-level groupBy + exerciseMapTabulation(data, + groupingBy(classifier, groupingBy(classifier2)), + new GroupedMapAssertion<>(classifier, HashMap.class, + new GroupedMapAssertion<>(classifier2, HashMap.class, + new ListAssertion<>()))); + // with concurrent as upstream + exerciseMapTabulation(data, + groupingByConcurrent(classifier, groupingBy(classifier2)), + new GroupedMapAssertion<>(classifier, ConcurrentHashMap.class, + new GroupedMapAssertion<>(classifier2, HashMap.class, + new ListAssertion<>()))); + // with concurrent as downstream + exerciseMapTabulation(data, + groupingBy(classifier, groupingByConcurrent(classifier2)), + new GroupedMapAssertion<>(classifier, HashMap.class, + new GroupedMapAssertion<>(classifier2, ConcurrentHashMap.class, + new ListAssertion<>()))); + // with concurrent as upstream and downstream + exerciseMapTabulation(data, + groupingByConcurrent(classifier, groupingByConcurrent(classifier2)), + new GroupedMapAssertion<>(classifier, ConcurrentHashMap.class, + new GroupedMapAssertion<>(classifier2, ConcurrentHashMap.class, + new ListAssertion<>()))); + + // With explicit constructors + exerciseMapTabulation(data, + groupingBy(classifier, TreeMap::new, groupingBy(classifier2, TreeMap::new, toCollection(HashSet::new))), + new GroupedMapAssertion<>(classifier, TreeMap.class, + new GroupedMapAssertion<>(classifier2, TreeMap.class, + new CollectionAssertion(HashSet.class, false)))); + // with concurrent as upstream + exerciseMapTabulation(data, + groupingByConcurrent(classifier, ConcurrentSkipListMap::new, groupingBy(classifier2, TreeMap::new, toList())), + new GroupedMapAssertion<>(classifier, ConcurrentSkipListMap.class, + new GroupedMapAssertion<>(classifier2, TreeMap.class, + new ListAssertion<>()))); + // with concurrent as downstream + exerciseMapTabulation(data, + groupingBy(classifier, TreeMap::new, groupingByConcurrent(classifier2, ConcurrentSkipListMap::new, toList())), + new GroupedMapAssertion<>(classifier, TreeMap.class, + new GroupedMapAssertion<>(classifier2, ConcurrentSkipListMap.class, + new ListAssertion<>()))); + // with concurrent as upstream and downstream + exerciseMapTabulation(data, + groupingByConcurrent(classifier, ConcurrentSkipListMap::new, groupingByConcurrent(classifier2, ConcurrentSkipListMap::new, toList())), + new GroupedMapAssertion<>(classifier, ConcurrentSkipListMap.class, + new GroupedMapAssertion<>(classifier2, ConcurrentSkipListMap.class, + new ListAssertion<>()))); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testGroupedReduce(String name, TestData.OfRef data) throws ReflectiveOperationException { + Function classifier = i -> i % 3; + + // Single-level simple reduce + exerciseMapTabulation(data, + groupingBy(classifier, reducing(0, Integer::sum)), + new GroupedMapAssertion<>(classifier, HashMap.class, + new ReduceAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum))); + // with concurrent + exerciseMapTabulation(data, + groupingByConcurrent(classifier, reducing(0, Integer::sum)), + new GroupedMapAssertion<>(classifier, ConcurrentHashMap.class, + new ReduceAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum))); + + // With explicit constructors + exerciseMapTabulation(data, + groupingBy(classifier, TreeMap::new, reducing(0, Integer::sum)), + new GroupedMapAssertion<>(classifier, TreeMap.class, + new ReduceAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum))); + // with concurrent + exerciseMapTabulation(data, + groupingByConcurrent(classifier, ConcurrentSkipListMap::new, reducing(0, Integer::sum)), + new GroupedMapAssertion<>(classifier, ConcurrentSkipListMap.class, + new ReduceAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum))); + + // Single-level map-reduce + exerciseMapTabulation(data, + groupingBy(classifier, reducing(0, mDoubler, Integer::sum)), + new GroupedMapAssertion<>(classifier, HashMap.class, + new ReduceAssertion<>(0, mDoubler, Integer::sum))); + // with concurrent + exerciseMapTabulation(data, + groupingByConcurrent(classifier, reducing(0, mDoubler, Integer::sum)), + new GroupedMapAssertion<>(classifier, ConcurrentHashMap.class, + new ReduceAssertion<>(0, mDoubler, Integer::sum))); + + // With explicit constructors + exerciseMapTabulation(data, + groupingBy(classifier, TreeMap::new, reducing(0, mDoubler, Integer::sum)), + new GroupedMapAssertion<>(classifier, TreeMap.class, + new ReduceAssertion<>(0, mDoubler, Integer::sum))); + // with concurrent + exerciseMapTabulation(data, + groupingByConcurrent(classifier, ConcurrentSkipListMap::new, reducing(0, mDoubler, Integer::sum)), + new GroupedMapAssertion<>(classifier, ConcurrentSkipListMap.class, + new ReduceAssertion<>(0, mDoubler, Integer::sum))); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testSimplePartition(String name, TestData.OfRef data) throws ReflectiveOperationException { + Predicate classifier = i -> i % 3 == 0; + + // Single-level partition to downstream List + exerciseMapTabulation(data, + partitioningBy(classifier), + new PartitionAssertion<>(classifier, new ListAssertion<>())); + exerciseMapTabulation(data, + partitioningBy(classifier, toList()), + new PartitionAssertion<>(classifier, new ListAssertion<>())); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testTwoLevelPartition(String name, TestData.OfRef data) throws ReflectiveOperationException { + Predicate classifier = i -> i % 3 == 0; + Predicate classifier2 = i -> i % 7 == 0; + + // Two level partition + exerciseMapTabulation(data, + partitioningBy(classifier, partitioningBy(classifier2)), + new PartitionAssertion<>(classifier, + new PartitionAssertion(classifier2, new ListAssertion<>()))); + + // Two level partition with reduce + exerciseMapTabulation(data, + partitioningBy(classifier, reducing(0, Integer::sum)), + new PartitionAssertion<>(classifier, + new ReduceAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum))); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/TeeOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/TeeOpTest.java new file mode 100644 index 00000000000..777158fd435 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/TeeOpTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; +import java.util.stream.*; + +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static java.util.stream.LambdaTestHelpers.*; + +/** + * TeeOpTest + */ +@Test(groups = { "serialization-hostile" }) +public class TeeOpTest extends OpTestCase { + + public void testTee() { + List copy = new ArrayList<>(); + + assertCountSum(countTo(0).stream().peek(copy::add), 0, 0); + assertCountSum(copy.iterator(), 0, 0); + + copy.clear(); + assertCountSum(countTo(10).stream().peek(copy::add), 10, 55); + assertCountSum(copy.iterator(), 10, 55); + + copy.clear(); + assertCountSum(countTo(10).stream().map(mDoubler).peek(copy::add), 10, 110); + assertCountSum(copy.iterator(), 10, 110); + } + + static class AbstractRecordingConsumer { + List list; + + void before(TestData td) { + // Tee block can be called concurrently + list = Collections.synchronizedList(new ArrayList<>()); + } + + void after(TestData td) { + // No guarantees in parallel tests that calls to tee block will + // be in the encounter order, if defined, of the data + // @@@ Consider passing more meta-data about evaluation + assertContentsUnordered(list, td.into(new ArrayList())); + } + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, final TestData.OfRef data) { + class RecordingConsumer extends AbstractRecordingConsumer implements Consumer { + public void accept(Integer t) { + list.add(t); + } + } + final RecordingConsumer b = new RecordingConsumer(); + + withData(data) + .stream(s -> s.peek(b)) + .before(b::before) + .after(b::after) + .exercise(); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOps(String name, final TestData.OfInt data) { + class RecordingConsumer extends AbstractRecordingConsumer implements IntConsumer { + public void accept(int t) { + list.add(t); + } + } + final RecordingConsumer b = new RecordingConsumer(); + + withData(data) + .stream(s -> s.peek(b)) + .before(b::before) + .after(b::after) + .exercise(); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOps(String name, final TestData.OfLong data) { + class RecordingConsumer extends AbstractRecordingConsumer implements LongConsumer { + public void accept(long t) { + list.add(t); + } + } + final RecordingConsumer b = new RecordingConsumer(); + + withData(data) + .stream(s -> s.peek(b)) + .before(b::before) + .after(b::after) + .exercise(); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOps(String name, final TestData.OfDouble data) { + class RecordingConsumer extends AbstractRecordingConsumer implements DoubleConsumer { + public void accept(double t) { + list.add(t); + } + } + final RecordingConsumer b = new RecordingConsumer(); + + withData(data) + .stream(s -> s.peek(b)) + .before(b::before) + .after(b::after) + .exercise(); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ToArrayOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ToArrayOpTest.java new file mode 100644 index 00000000000..0971e89fcf1 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ToArrayOpTest.java @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2012, 2013, 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. + * + * 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.stream; + +import org.testng.annotations.Test; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.*; + +import static java.util.stream.LambdaTestHelpers.*; + + +/** + * ToArrayOpTest + * + */ +@Test +public class ToArrayOpTest extends OpTestCase { + + public void testToArray() { + assertCountSum(Arrays.asList(countTo(0).stream().toArray()), 0, 0); + assertCountSum(Arrays.asList(countTo(10).stream().toArray()), 10, 55); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOps(String name, TestData.OfRef data) { + exerciseTerminalOps(data, s -> s.toArray()); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOpsWithMap(String name, TestData.OfRef data) { + // Retain the size of the source + // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array + + Object[] objects = exerciseTerminalOps(data, s -> s.map(i -> (Integer) (i + i)), s -> s.toArray()); + assertTrue(objects.length == data.size()); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOpsWithSorted(String name, TestData.OfRef data) { + // Retain the size of the source + // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array + + Object[] objects = exerciseTerminalOps(data, s -> s.sorted(), s -> s.toArray()); + assertTrue(objects.length == data.size()); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOpsWithFlatMap(String name, TestData.OfRef data) { + // Double the size of the source + // Fixed size optimizations will not be used + + Object[] objects = exerciseTerminalOps(data, + s -> s.flatMap(e -> Arrays.stream(new Object[] { e, e })), + s -> s.toArray()); + assertTrue(objects.length == data.size() * 2); + } + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testOpsWithFilter(String name, TestData.OfRef data) { + // Reduce the size of the source + // Fixed size optimizations will not be used + + exerciseTerminalOps(data, s -> s.filter(LambdaTestHelpers.pEven), s -> s.toArray()); + } + + public void testAsArrayWithType() { + exerciseTerminalOps( + TestData.Factory.ofCollection("", Arrays.asList(1.1, 2.2, 3.4, 4.4)), + s -> // First pipeline slice using Object[] with Double elements + s.sorted() + // Second pipeline slice using Integer[] with Integer elements + .map((Double d) -> Integer.valueOf(d.intValue())).sorted(), + s -> s.toArray(Integer[]::new)); + } + + private List, Stream>> uniqueAndSortedPermutations = + LambdaTestHelpers.permuteStreamFunctions(Arrays.asList( + s -> s.distinct(), + s -> s.distinct(), + s -> s.sorted(), + s -> s.sorted() + )); + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testDistinctAndSortedPermutations(String name, TestData.OfRef data) { + for (Function, Stream> f : uniqueAndSortedPermutations) { + exerciseTerminalOps(data, f, s -> s.toArray()); + + Integer[] is = exerciseTerminalOps(data, f, s -> s.toArray(Integer[]::new)); + assertEquals(is.getClass(), Integer[].class); + + Number[] ns = exerciseTerminalOps(data, f, s -> s.toArray(Number[]::new)); + assertEquals(ns.getClass(), Number[].class); + + if (data.size() > 0) { + Exception caught = null; + try { + exerciseTerminalOps(data, f, s -> s.toArray(String[]::new)); + } catch (Exception e) { + caught = e; + } + assertTrue(caught != null); + assertEquals(caught.getClass(), ArrayStoreException.class); + } + } + } + + private List, Stream>> statefulOpPermutations = + LambdaTestHelpers.permuteStreamFunctions(Arrays.asList( + s -> s.limit(10), + s -> s.distinct(), + s -> s.sorted() + )); + + @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) + public void testStatefulOpPermutations(String name, TestData.OfRef data) { + for (Function, Stream> f : statefulOpPermutations) { + exerciseTerminalOps(data, f, s -> s.toArray()); + + Integer[] is = exerciseTerminalOps(data, f, s -> s.toArray(Integer[]::new)); + assertEquals(is.getClass(), Integer[].class); + + Number[] ns = exerciseTerminalOps(data, f, s -> s.toArray(Number[]::new)); + assertEquals(ns.getClass(), Number[].class); + + if (data.size() > 0) { + Exception caught = null; + try { + exerciseTerminalOps(data, f, s -> s.toArray(String[]::new)); + } catch (Exception e) { + caught = e; + } + assertTrue(caught != null); + assertEquals(caught.getClass(), ArrayStoreException.class); + } + } + } + + // + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOps(String name, TestData.OfInt data) { + exerciseTerminalOps(data, s -> s.toArray()); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOpsWithMap(String name, TestData.OfInt data) { + // Retain the size of the source + // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array + + int[] ints = exerciseTerminalOps(data, s -> s.map(i -> i + i), s -> s.toArray()); + assertTrue(ints.length == data.size()); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOpsWithSorted(String name, TestData.OfInt data) { + // Retain the size of the source + // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array + + int[] ints = exerciseTerminalOps(data, s -> s.sorted(), (IntStream s) -> s.toArray()); + assertTrue(ints.length == data.size()); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOpsWithFlatMap(String name, TestData.OfInt data) { + // Int the size of the source + // Fixed size optimizations will not be used + + int[] objects = exerciseTerminalOps(data, + s -> s.flatMap(e -> Arrays.stream(new int[] { e, e })), + s -> s.toArray()); + assertTrue(objects.length == data.size() * 2); + } + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntOpsWithFilter(String name, TestData.OfInt data) { + // Reduce the size of the source + // Fixed size optimizations will not be used + + exerciseTerminalOps(data, s -> s.filter(LambdaTestHelpers.ipEven), s -> s.toArray()); + } + + private List> intUniqueAndSortedPermutations = + LambdaTestHelpers.permuteStreamFunctions(Arrays.asList( + s -> s.distinct(), + s -> s.distinct(), + s -> s.sorted(), + s -> s.sorted() + )); + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntDistinctAndSortedPermutations(String name, TestData.OfInt data) { + for (Function f : intUniqueAndSortedPermutations) { + exerciseTerminalOps(data, f, s -> s.toArray()); + } + } + + private List> intStatefulOpPermutations = + LambdaTestHelpers.permuteStreamFunctions(Arrays.asList( + s -> s.limit(10), + s -> s.distinct(), + s -> s.sorted() + )); + + @Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) + public void testIntStatefulOpPermutations(String name, TestData.OfInt data) { + for (Function f : intStatefulOpPermutations) { + exerciseTerminalOps(data, f, s -> s.toArray()); + } + } + + // + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOps(String name, TestData.OfLong data) { + exerciseTerminalOps(data, s -> s.toArray()); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOpsWithMap(String name, TestData.OfLong data) { + // Retain the size of the source + // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array + + long[] longs = exerciseTerminalOps(data, s -> s.map(i -> i + i), s -> s.toArray()); + assertTrue(longs.length == data.size()); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOpsWithSorted(String name, TestData.OfLong data) { + // Retain the size of the source + // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array + + long[] longs = exerciseTerminalOps(data, s -> s.sorted(), (LongStream s) -> s.toArray()); + assertTrue(longs.length == data.size()); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOpsWithFlatMap(String name, TestData.OfLong data) { + // Long the size of the source + // Fixed size optimizations will not be used + + long[] objects = exerciseTerminalOps(data, + s -> s.flatMap(e -> Arrays.stream(new long[] { e, e })), + s -> s.toArray()); + assertTrue(objects.length == data.size() * 2); + } + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongOpsWithFilter(String name, TestData.OfLong data) { + // Reduce the size of the source + // Fixed size optimizations will not be used + + exerciseTerminalOps(data, s -> s.filter(LambdaTestHelpers.lpEven), s -> s.toArray()); + } + + private List> longUniqueAndSortedPermutations = + LambdaTestHelpers.permuteStreamFunctions(Arrays.asList( + s -> s.distinct(), + s -> s.distinct(), + s -> s.sorted(), + s -> s.sorted() + )); + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongDistinctAndSortedPermutations(String name, TestData.OfLong data) { + for (Function f : longUniqueAndSortedPermutations) { + exerciseTerminalOps(data, f, s -> s.toArray()); + } + } + + private List> longStatefulOpPermutations = + LambdaTestHelpers.permuteStreamFunctions(Arrays.asList( + s -> s.limit(10), + s -> s.distinct(), + s -> s.sorted() + )); + + @Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) + public void testLongStatefulOpPermutations(String name, TestData.OfLong data) { + for (Function f : longStatefulOpPermutations) { + exerciseTerminalOps(data, f, s -> s.toArray()); + } + } + + // + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOps(String name, TestData.OfDouble data) { + exerciseTerminalOps(data, s -> s.toArray()); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOpsWithMap(String name, TestData.OfDouble data) { + // Retain the size of the source + // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array + + double[] doubles = exerciseTerminalOps(data, s -> s.map(i -> i + i), s -> s.toArray()); + assertTrue(doubles.length == data.size()); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOpsWithSorted(String name, TestData.OfDouble data) { + // Retain the size of the source + // This should kick in the parallel evaluation optimization for tasks stuffing elements into a shared array + + double[] doubles = exerciseTerminalOps(data, s -> s.sorted(), (DoubleStream s) -> s.toArray()); + assertTrue(doubles.length == data.size()); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOpsWithFlatMap(String name, TestData.OfDouble data) { + // Double the size of the source + // Fixed size optimizations will not be used + + double[] objects = exerciseTerminalOps(data, + s -> s.flatMap(e -> Arrays.stream(new double[] { e, e })), + s -> s.toArray()); + assertTrue(objects.length == data.size() * 2); + } + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleOpsWithFilter(String name, TestData.OfDouble data) { + // Reduce the size of the source + // Fixed size optimizations will not be used + + exerciseTerminalOps(data, s -> s.filter(LambdaTestHelpers.dpEven), s -> s.toArray()); + } + + private List> doubleUniqueAndSortedPermutations = + LambdaTestHelpers.permuteStreamFunctions(Arrays.asList( + s -> s.distinct(), + s -> s.distinct(), + s -> s.sorted(), + s -> s.sorted() + )); + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleDistinctAndSortedPermutations(String name, TestData.OfDouble data) { + for (Function f : doubleUniqueAndSortedPermutations) { + exerciseTerminalOps(data, f, s -> s.toArray()); + } + } + + private List> doubleStatefulOpPermutations = + LambdaTestHelpers.permuteStreamFunctions(Arrays.asList( + s -> s.limit(10), + s -> s.distinct(), + s -> s.sorted() + )); + + @Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) + public void testDoubleStatefulOpPermutations(String name, TestData.OfDouble data) { + for (Function f : doubleStatefulOpPermutations) { + exerciseTerminalOps(data, f, s -> s.toArray()); + } + } +} diff --git a/jdk/test/jdk/lambda/ArrayCtorRefTest.java b/jdk/test/jdk/lambda/ArrayCtorRefTest.java new file mode 100644 index 00000000000..7189fc41bd2 --- /dev/null +++ b/jdk/test/jdk/lambda/ArrayCtorRefTest.java @@ -0,0 +1,74 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import java.util.function.IntFunction; +import java.util.function.Supplier; + +import static org.testng.Assert.assertTrue; + +/** + * ArrayCtorRefTest + * + * @author Brian Goetz + */ +@Test +public class ArrayCtorRefTest { + interface ArrayMaker { + public T[] make(int size); + } + + private static Supplier emptyArrayFactory(ArrayMaker maker) { + return () -> maker.make(0); + } + + public void testLambda() { + ArrayMaker am = i -> new String[i]; + String[] arr = am.make(3); + arr[0] = "Foo"; + assertTrue(arr instanceof String[]); + assertTrue(arr.length == 3); + } + + public void testIntCtorRef() { + IntFunction factory = int[]::new; + int[] arr = factory.apply(6); + assertTrue(arr.length == 6); + } + + public void testLambdaInference() { + Supplier oF = emptyArrayFactory(i -> new Object[i]); + Supplier sF = emptyArrayFactory(i -> new String[i]); + assertTrue(oF.get() instanceof Object[]); + assertTrue(sF.get() instanceof String[]); + } + + public void testCtorRef() { + ArrayMaker am = String[]::new; + String[] arr = am.make(3); + arr[0] = "Foo"; + assertTrue(arr instanceof String[]); + assertTrue(arr.length == 3); + } +} diff --git a/jdk/test/jdk/lambda/FDTest.java b/jdk/test/jdk/lambda/FDTest.java new file mode 100644 index 00000000000..adda12a56db --- /dev/null +++ b/jdk/test/jdk/lambda/FDTest.java @@ -0,0 +1,192 @@ +/* + * 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. + * + * 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. + */ + + +import shapegen.*; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.util.Pair; + +import java.net.URI; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.tools.Diagnostic; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import org.testng.annotations.Test; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.*; + +public class FDTest { + + public enum TestKind { + POSITIVE, + NEGATIVE; + + Collection getHierarchy(HierarchyGenerator hg) { + return this == POSITIVE ? + hg.getOK() : hg.getErr(); + } + } + + public static JavaCompiler comp; + public static StandardJavaFileManager fm; + + @BeforeSuite + static void init() { + // create default shared JavaCompiler - reused across multiple + // compilations + + comp = ToolProvider.getSystemJavaCompiler(); + fm = comp.getStandardFileManager(null, null, null); + } + + public static void main(String[] args) throws Exception { + init(); + + for (Pair fdtest : generateCases()) { + runTest(fdtest.fst, fdtest.snd, comp, fm); + } + } + + @Test(dataProvider = "fdCases") + public void testOneCase(TestKind tk, Hierarchy hs) + throws Exception { + FDTest.runTest(tk, hs, comp, fm); + } + + @DataProvider(name = "fdCases") + public Object[][] caseGenerator() { + List> cases = generateCases(); + Object[][] fdCases = new Object[cases.size()][]; + for (int i = 0; i < cases.size(); ++i) { + fdCases[i] = new Object[2]; + fdCases[i][0] = cases.get(i).fst; + fdCases[i][1] = cases.get(i).snd; + } + return fdCases; + } + + public static List> generateCases() { + ArrayList> list = new ArrayList<>(); + HierarchyGenerator hg = new HierarchyGenerator(); + for (TestKind tk : TestKind.values()) { + for (Hierarchy hs : tk.getHierarchy(hg)) { + list.add(new Pair<>(tk, hs)); + } + } + return list; + } + + public static void runTest(TestKind tk, Hierarchy hs, + JavaCompiler comp, StandardJavaFileManager fm) throws Exception { + new FDTest(tk, hs).run(comp, fm); + } + + TestKind tk; + Hierarchy hs; + DefenderTestSource source; + DiagnosticChecker diagChecker; + + public FDTest() {} + + FDTest(TestKind tk, Hierarchy hs) { + this.tk = tk; + this.hs = hs; + this.source = new DefenderTestSource(); + this.diagChecker = new DiagnosticChecker(); + } + + void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { + JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, + null, null, Arrays.asList(source)); + try { + ct.analyze(); + } catch (Throwable ex) { + fail("Error thrown when analyzing the following source:\n" + source.getCharContent(true)); + } + check(); + } + + void check() { + boolean errorExpected = tk == TestKind.NEGATIVE; + if (errorExpected != diagChecker.errorFound) { + fail("problem in source: \n" + + "\nerror found = " + diagChecker.errorFound + + "\nerror expected = " + errorExpected + + "\n" + dumpHierarchy() + + "\n" + source.getCharContent(true)); + } + } + + String dumpHierarchy() { + StringBuilder buf = new StringBuilder(); + buf.append("root = " + hs.root + "\n"); + for (ClassCase cc : hs.all) { + buf.append(" class name = " + cc.getName() + "\n"); + buf.append(" class OK = " + cc.get_OK() + "\n"); + buf.append(" prov = " + cc.get_mprov() + "\n"); + + } + return buf.toString(); + } + + class DefenderTestSource extends SimpleJavaFileObject { + + String source; + + public DefenderTestSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + StringBuilder buf = new StringBuilder(); + List defaultRef = new ArrayList<>(); + for (ClassCase cc : hs.all) { + Hierarchy.genClassDef(buf, cc, null, defaultRef); + } + source = buf.toString(); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + static class DiagnosticChecker implements javax.tools.DiagnosticListener { + + boolean errorFound; + + public void report(Diagnostic diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + errorFound = true; + } + } + } +} diff --git a/jdk/test/jdk/lambda/LambdaTranslationCompoundSamTest.java b/jdk/test/jdk/lambda/LambdaTranslationCompoundSamTest.java new file mode 100644 index 00000000000..a8006b4680d --- /dev/null +++ b/jdk/test/jdk/lambda/LambdaTranslationCompoundSamTest.java @@ -0,0 +1,75 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * LambdaTranslationCompoundSamTest + * + * @author Brian Goetz + */ +@Test +public class LambdaTranslationCompoundSamTest { + interface Accepts { + void accept(T t); + } + + interface AcceptsInt { + void accept(int i); + } + + interface A extends Accepts { + + default void accept(int value) { + throw new IllegalStateException(); + } + + interface OfInt extends A, AcceptsInt { + @Override + void accept(int value); + + @Override + default void accept(Integer i) { + accept(i.intValue()); + } + } + } + + protected interface Target extends A { + public interface OfInt extends Target, A.OfInt { } + } + + public void testConversion() { + int[] result = new int[4]; + + Target tb = (Integer i) -> { result[0] = i+1; }; + tb.accept((Integer) 3); + assertEquals(4, result[0]); + + Target.OfInt ti = (int i) -> { result[1] = i+1; }; + ti.accept(7); + assertEquals(8, result[1]); + } +} diff --git a/jdk/test/jdk/lambda/LambdaTranslationInInterface.java b/jdk/test/jdk/lambda/LambdaTranslationInInterface.java new file mode 100644 index 00000000000..20505a42f07 --- /dev/null +++ b/jdk/test/jdk/lambda/LambdaTranslationInInterface.java @@ -0,0 +1,59 @@ +/* + * 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. + * + * 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. + */ + +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +/** + * @author Robert Field + */ + +interface LTII { + + interface ILsp1 { + String m(); + } + + interface ILsp2 { + String m(String x); + } + + default ILsp1 t1() { + return () -> { return "yo"; }; + } + + default ILsp2 t2() { + return (x) -> { return "snur" + x; }; + } + +} + +@Test +public class LambdaTranslationInInterface implements LTII { + + public void testLambdaInDefaultMethod() { + assertEquals(t1().m(), "yo"); + assertEquals(t2().m("p"), "snurp"); + } + +} diff --git a/jdk/test/jdk/lambda/LambdaTranslationInnerConstructor.java b/jdk/test/jdk/lambda/LambdaTranslationInnerConstructor.java new file mode 100644 index 00000000000..17e6ad1451f --- /dev/null +++ b/jdk/test/jdk/lambda/LambdaTranslationInnerConstructor.java @@ -0,0 +1,70 @@ +/* + * 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. + * + * 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. + */ + +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +/** + * @author Robert Field + */ + +@Test +public class LambdaTranslationInnerConstructor { + + public void testLambdaWithInnerConstructor() { + assertEquals(seq1().m().toString(), "Cbl:nada"); + assertEquals(seq2().m("rats").toString(), "Cbl:rats"); + } + + Ib1 seq1() { + return () -> { return new Cbl(); }; + } + + Ib2 seq2() { + return (x) -> { return new Cbl(x); }; + } + + class Cbl { + String val; + + Cbl() { + this.val = "nada"; + } + + Cbl(String z) { + this.val = z; + } + + public String toString() { + return "Cbl:" + val; + } + } + + interface Ib1 { + Object m(); + } + + interface Ib2 { + Object m(String x); + } +} \ No newline at end of file diff --git a/jdk/test/jdk/lambda/LambdaTranslationTest1.java b/jdk/test/jdk/lambda/LambdaTranslationTest1.java new file mode 100644 index 00000000000..acfc904cda4 --- /dev/null +++ b/jdk/test/jdk/lambda/LambdaTranslationTest1.java @@ -0,0 +1,232 @@ +/* + * 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. + * + * 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. + */ + +import java.util.function.Consumer; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class LambdaTranslationTest1 extends LT1Sub { + + String cntxt = "blah"; + + private static final ThreadLocal result = new ThreadLocal<>(); + + private static void setResult(Object s) { result.set(s); } + private static void appendResult(Object s) { result.set(result.get().toString() + s); } + + private static void assertResult(String expected) { + assertEquals(result.get().toString(), expected); + } + + static Integer count(String s) { + return s.length(); + } + + static int icount(String s) { + return s.length(); + } + + static void eye(Integer i) { + setResult(String.format("I:%d", i)); + } + + static void ieye(int i) { + setResult(String.format("i:%d", i)); + } + + static void deye(double d) { + setResult(String.format("d:%f", d)); + } + + public void testLambdas() { + Consumer b = t -> {setResult("Sink0::" + t);}; + b.accept("Howdy"); + assertResult("Sink0::Howdy"); + + Consumer b1 = t -> {setResult("Sink1::" + t);}; + b1.accept("Rowdy"); + assertResult("Sink1::Rowdy"); + + for (int i = 5; i < 10; ++i) { + Consumer b2 = t -> {setResult("Sink2::" + t);}; + b2.accept(i); + assertResult("Sink2::" + i); + } + + Consumer b3 = t -> {setResult("Sink3::" + t);}; + for (int i = 900; i > 0; i -= 100) { + b3.accept(i); + assertResult("Sink3::" + i); + } + + cntxt = "blah"; + Consumer b4 = t -> {setResult(String.format("b4: %s .. %s", cntxt, t));}; + b4.accept("Yor"); + assertResult("b4: blah .. Yor"); + + String flaw = "flaw"; + Consumer b5 = t -> {setResult(String.format("b5: %s .. %s", flaw, t));}; + b5.accept("BB"); + assertResult("b5: flaw .. BB"); + + cntxt = "flew"; + Consumer b6 = t -> {setResult(String.format("b6: %s .. %s .. %s", t, cntxt, flaw));}; + b6.accept("flee"); + assertResult("b6: flee .. flew .. flaw"); + + Consumer b7 = t -> {setResult(String.format("b7: %s %s", t, this.protectedSuperclassMethod()));}; + b7.accept("this:"); + assertResult("b7: this: instance:flew"); + + Consumer b8 = t -> {setResult(String.format("b8: %s %s", t, super.protectedSuperclassMethod()));}; + b8.accept("super:"); + assertResult("b8: super: I'm the sub"); + + Consumer b7b = t -> {setResult(String.format("b9: %s %s", t, protectedSuperclassMethod()));}; + b7b.accept("implicit this:"); + assertResult("b9: implicit this: instance:flew"); + + Consumer b10 = t -> {setResult(String.format("b10: new LT1Thing: %s", (new LT1Thing(t)).str));}; + b10.accept("thing"); + assertResult("b10: new LT1Thing: thing"); + + Consumer b11 = t -> {setResult(String.format("b11: %s", (new LT1Thing(t) { + String get() { + return "*" + str.toString() + "*"; + } + }).get()));}; + b11.accept(999); + assertResult("b11: *999*"); + } + + public void testMethodRefs() { + LT1IA ia = LambdaTranslationTest1::eye; + ia.doit(1234); + assertResult("I:1234"); + + LT1IIA iia = LambdaTranslationTest1::ieye; + iia.doit(1234); + assertResult("i:1234"); + + LT1IA da = LambdaTranslationTest1::deye; + da.doit(1234); + assertResult("d:1234.000000"); + + LT1SA a = LambdaTranslationTest1::count; + assertEquals((Integer) 5, a.doit("howdy")); + + a = LambdaTranslationTest1::icount; + assertEquals((Integer) 6, a.doit("shower")); + } + + public void testInner() throws Exception { + (new In()).doInner(); + } + + protected String protectedSuperclassMethod() { + return "instance:" + cntxt; + } + + private class In { + + private int that = 1234; + + void doInner() { + Consumer i4 = t -> {setResult(String.format("i4: %d .. %s", that, t));}; + i4.accept("=1234"); + assertResult("i4: 1234 .. =1234"); + + Consumer i5 = t -> {setResult(""); appendResult(t); appendResult(t);}; + i5.accept("fruit"); + assertResult("fruitfruit"); + + cntxt = "human"; + Consumer b4 = t -> {setResult(String.format("b4: %s .. %s", cntxt, t));}; + b4.accept("bin"); + assertResult("b4: human .. bin"); + + final String flaw = "flaw"; + +/** + Callable c5 = () -> "["+flaw+"]" ; + System.out.printf("c5: %s\n", c5.call() ); + **/ + + Consumer b5 = t -> {setResult(String.format("b5: %s .. %s", flaw, t));}; + b5.accept("BB"); + assertResult("b5: flaw .. BB"); + + cntxt = "borg"; + Consumer b6 = t -> {setResult(String.format("b6: %s .. %s .. %s", t, cntxt, flaw));}; + b6.accept("flee"); + assertResult("b6: flee .. borg .. flaw"); + + Consumer b7b = t -> {setResult(String.format("b7b: %s %s", t, protectedSuperclassMethod()));}; + b7b.accept("implicit outer this"); + assertResult("b7b: implicit outer this instance:borg"); + + /** + Block b9 = t -> { System.out.printf("New: %s\n", (new LT1Thing(t)).str); }; + b9.apply("thing"); + + Block ba = t -> { System.out.printf("Def: %s\n", (new LT1Thing(t) { String get() { return "*" + str.toString() +"*";}}).get() ); }; + ba.apply(999); + + */ + } + } +} + +class LT1Sub { + protected String protectedSuperclassMethod() { + return "I'm the sub"; + } +} + +class LT1Thing { + final Object str; + + LT1Thing(Object s) { + str = s; + } +} + +interface LT1SA { + Integer doit(String s); +} + +interface LT1IA { + void doit(int i); +} + +interface LT1IIA { + void doit(Integer i); +} + diff --git a/jdk/test/jdk/lambda/LambdaTranslationTest2.java b/jdk/test/jdk/lambda/LambdaTranslationTest2.java new file mode 100644 index 00000000000..59263e5b9b9 --- /dev/null +++ b/jdk/test/jdk/lambda/LambdaTranslationTest2.java @@ -0,0 +1,347 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * LambdaTranslationTest2 -- end-to-end smoke tests for lambda evaluation + */ +@Test +public class LambdaTranslationTest2 { + + final String dummy = "dummy"; + + public void testLambdas() { + Predicate isEmpty = s -> s.isEmpty(); + assertTrue(isEmpty.test("")); + assertTrue(!isEmpty.test("foo")); + + Predicate oIsEmpty = s -> ((String) s).isEmpty(); + assertTrue(oIsEmpty.test("")); + assertTrue(!oIsEmpty.test("foo")); + + Predicate alwaysTrue = o -> true; + assertTrue(alwaysTrue.test("")); + assertTrue(alwaysTrue.test(null)); + + Predicate alwaysFalse = o -> false; + assertTrue(!alwaysFalse.test("")); + assertTrue(!alwaysFalse.test(null)); + + // tests local capture + String foo = "foo"; + Predicate equalsFoo = s -> s.equals(foo); + assertTrue(!equalsFoo.test("")); + assertTrue(equalsFoo.test("foo")); + + // tests instance capture + Predicate equalsDummy = s -> s.equals(dummy); + assertTrue(!equalsDummy.test("")); + assertTrue(equalsDummy.test("dummy")); + + Function ident = s -> s; + + assertEquals("blarf", ident.apply("blarf")); + assertEquals("wooga", ident.apply("wooga")); + assertTrue("wooga" == ident.apply("wooga")); + + // constant capture + Function prefixer = s -> "p" + s; + assertEquals("pblarf", prefixer.apply("blarf")); + assertEquals("pwooga", prefixer.apply("wooga")); + + // instance capture + Function prefixer2 = s -> dummy + s; + assertEquals("dummyblarf", prefixer2.apply("blarf")); + assertEquals("dummywooga", prefixer2.apply("wooga")); + } + + interface Supplier { + T make(); + } + + interface StringFactory extends Supplier { } + + interface StringFactory2 extends Supplier { + String make(); + } + + public void testBridges() { + Supplier of = () -> "y"; + Supplier ef = () -> "z"; + + assertEquals("y", of.make()); + assertEquals("y", ((Supplier) of).make()); + assertEquals("y", ((Supplier) of).make()); + + assertEquals("z", ef.make()); + assertEquals("z", ((Supplier) ef).make()); + } + + public void testBridgesImplicitSpecialization() { + StringFactory sf = () -> "x"; + + assertEquals("x", sf.make()); + assertEquals("x", ((Supplier) sf).make()); + assertEquals("x", ((Supplier) sf).make()); + assertEquals("x", ((Supplier) sf).make()); + } + + public void testBridgesExplicitSpecialization() { + StringFactory2 sf = () -> "x"; + + assertEquals("x", sf.make()); + assertEquals("x", ((Supplier) sf).make()); + assertEquals("x", ((Supplier) sf).make()); + assertEquals("x", ((Supplier) sf).make()); + } + + public void testSuperCapture() { + class A { + String make() { return "x"; } + } + + class B extends A { + void testSuperCapture() { + StringFactory sf = () -> super.make(); + assertEquals("x", sf.make()); + } + } + + new B().testSuperCapture(); + } + + interface WidenD { + public String m(float a0, double a1); + } + + interface WidenS { + public String m(byte a0, short a1); + } + + interface WidenI { + public String m(byte a0, short a1, char a2, int a3); + } + + interface WidenL { + public String m(byte a0, short a1, char a2, int a3, long a4); + } + + interface Box { + public String m(byte a0, short a1, char a2, int a3, long a4, boolean a5, float a6, double a7); + } + + static String pb(Byte a0, Short a1, Character a2, Integer a3, Long a4, Boolean a5, Float a6, Double a7) { + return String.format("b%d s%d c%c i%d j%d z%b f%f d%f", a0, a1, a2, a3, a4, a5, a6, a7); + } + + static String pwI1(int a0, int a1, int a2, int a3) { + return String.format("b%d s%d c%d i%d", a0, a1, a2, a3); + } + + static String pwI2(Integer a0, Integer a1, Integer a2, Integer a3) { + return String.format("b%d s%d c%d i%d", a0, a1, a2, a3); + } + + static String pwL1(long a0, long a1, long a2, long a3, long a4) { + return String.format("b%d s%d c%d i%d j%d", a0, a1, a2, a3, a4); + } + + static String pwL2(Long a0, Long a1, Long a2, Long a3, Long a4) { + return String.format("b%d s%d c%d i%d j%d", a0, a1, a2, a3, a4); + } + + static String pwS1(short a0, short a1) { + return String.format("b%d s%d", a0, a1); + } + + static String pwS2(Short a0, Short a1) { + return String.format("b%d s%d", a0, a1); + } + + static String pwD1(double a0, double a1) { + return String.format("f%f d%f", a0, a1); + } + + static String pwD2(Double a0, Double a1) { + return String.format("f%f d%f", a0, a1); + } + + public void testPrimitiveWidening() { + WidenS ws1 = LambdaTranslationTest2::pwS1; + assertEquals("b1 s2", ws1.m((byte) 1, (short) 2)); + + WidenD wd1 = LambdaTranslationTest2::pwD1; + assertEquals("f1.000000 d2.000000", wd1.m(1.0f, 2.0)); + + WidenI wi1 = LambdaTranslationTest2::pwI1; + assertEquals("b1 s2 c3 i4", wi1.m((byte) 1, (short) 2, (char) 3, 4)); + + WidenL wl1 = LambdaTranslationTest2::pwL1; + assertEquals("b1 s2 c3 i4 j5", wl1.m((byte) 1, (short) 2, (char) 3, 4, 5L)); + + // @@@ TODO: clarify spec on widen+box conversion + } + + interface Unbox { + public String m(Byte a0, Short a1, Character a2, Integer a3, Long a4, Boolean a5, Float a6, Double a7); + } + + static String pu(byte a0, short a1, char a2, int a3, long a4, boolean a5, float a6, double a7) { + return String.format("b%d s%d c%c i%d j%d z%b f%f d%f", a0, a1, a2, a3, a4, a5, a6, a7); + } + + public void testUnboxing() { + Unbox u = LambdaTranslationTest2::pu; + assertEquals("b1 s2 cA i4 j5 ztrue f6.000000 d7.000000", u.m((byte)1, (short) 2, 'A', 4, 5L, true, 6.0f, 7.0)); + } + + public void testBoxing() { + Box b = LambdaTranslationTest2::pb; + assertEquals("b1 s2 cA i4 j5 ztrue f6.000000 d7.000000", b.m((byte) 1, (short) 2, 'A', 4, 5L, true, 6.0f, 7.0)); + } + + static boolean cc(Object o) { + return ((String) o).equals("foo"); + } + + public void testArgCastingAdaptation() { + Predicate p = LambdaTranslationTest2::cc; + assertTrue(p.test("foo")); + assertTrue(!p.test("bar")); + } + + interface SonOfPredicate extends Predicate { } + + public void testExtendsSAM() { + SonOfPredicate p = s -> s.isEmpty(); + assertTrue(p.test("")); + assertTrue(!p.test("foo")); + } + + public void testConstructorRef() { + Supplier> lf = ArrayList::new; + List list = lf.make(); + assertTrue(list instanceof ArrayList); + assertTrue(list != lf.make()); + list.add("a"); + assertEquals("[a]", list.toString()); + } + + private static String privateMethod() { + return "private"; + } + + public void testPrivateMethodRef() { + Supplier sf = LambdaTranslationTest2::privateMethod; + assertEquals("private", sf.make()); + } + + private interface PrivateIntf { + String make(); + } + + public void testPrivateIntf() { + PrivateIntf p = () -> "foo"; + assertEquals("foo", p.make()); + } + + interface Op { + public T op(T a, T b); + } + + public void testBoxToObject() { + Op maxer = Math::max; + for (int i=-100000; i < 100000; i += 100) + for (int j=-100000; j < 100000; j += 99) { + assertEquals((int) maxer.op(i,j), Math.max(i,j)); + } + } + + protected static String protectedMethod() { + return "protected"; + } + + public void testProtectedMethodRef() { + Supplier sf = LambdaTranslationTest2::protectedMethod; + assertEquals("protected", sf.make()); + } + + class Inner1 { + String m1() { + return "Inner1.m1()"; + } + + class Inner2 { + public String m1() { + return "Inner1.Inner2.m1()"; + } + + protected String m2() { + return "Inner1.Inner2.m2()"; + } + + String m3() { + return "Inner1.Inner2.m3()"; + } + + class Inner3 { + T t = null; + Inner3(T t) { + this.t = t; + } + T m1() { + return t; + } + } + } + } + + public void testInnerClassMethodRef() { + Supplier fs = new Inner1()::m1; + assertEquals("Inner1.m1()", fs.make()); + + fs = new Inner1().new Inner2()::m1; + assertEquals("Inner1.Inner2.m1()", fs.make()); + + fs = new Inner1().new Inner2()::m2; + assertEquals("Inner1.Inner2.m2()", fs.make()); + + fs = new Inner1().new Inner2()::m3; + assertEquals("Inner1.Inner2.m3()", fs.make()); + + fs = new Inner1().new Inner2().new Inner3("Inner1.Inner2.Inner3")::m1; + assertEquals("Inner1.Inner2.Inner3", fs.make()); + + Supplier fsi = new Inner1().new Inner2().new Inner3(100)::m1; + assertEquals(100, (int)fsi.make()); + } +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestFDCCE.java b/jdk/test/jdk/lambda/MethodReferenceTestFDCCE.java new file mode 100644 index 00000000000..dd5b2c88925 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestFDCCE.java @@ -0,0 +1,146 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; +import java.lang.reflect.Array; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +/** + * Method references and raw types. + * @author Robert Field + */ + +@Test +@SuppressWarnings({"rawtypes", "unchecked"}) +public class MethodReferenceTestFDCCE { + + static void assertCCE(Throwable t) { + assertEquals(t.getClass().getName(), "java.lang.ClassCastException"); + } + + interface Pred { boolean accept(T x); } + + interface Ps { boolean accept(short x); } + + interface Oo { Object too(int x); } + + interface Reto { T m(); } + + class A {} + class B extends A {} + + static boolean isMinor(int x) { + return x < 18; + } + + static boolean tst(A x) { + return true; + } + + static Object otst(Object x) { + return x; + } + + static boolean stst(Short x) { + return x < 18; + } + + static short ritst() { + return 123; + } + + public void testMethodReferenceFDPrim1() { + Pred p = MethodReferenceTestFDCCE::isMinor; + Pred p2 = p; + assertTrue(p2.accept((Byte)(byte)15)); + } + + public void testMethodReferenceFDPrim2() { + Pred p = MethodReferenceTestFDCCE::isMinor; + Pred p2 = p; + assertTrue(p2.accept((byte)15)); + } + + public void testMethodReferenceFDPrimICCE() { + Pred p = MethodReferenceTestFDCCE::isMinor; + Pred p2 = p; + try { + p2.accept(15); // should throw CCE + fail("Exception should have been thrown"); + } catch (Throwable t) { + assertCCE(t); + } + } + + public void testMethodReferenceFDPrimOCCE() { + Pred p = MethodReferenceTestFDCCE::isMinor; + Pred p2 = p; + try { + p2.accept(new Object()); // should throw CCE + fail("Exception should have been thrown"); + } catch (Throwable t) { + assertCCE(t); + } + } + + public void testMethodReferenceFDRef() { + Pred p = MethodReferenceTestFDCCE::tst; + Pred p2 = p; + assertTrue(p2.accept(new B())); + } + + public void testMethodReferenceFDRefCCE() { + Pred p = MethodReferenceTestFDCCE::tst; + Pred p2 = p; + try { + p2.accept(new A()); // should throw CCE + fail("Exception should have been thrown"); + } catch (Throwable t) { + assertCCE(t); + } + } + + public void testMethodReferenceFDPrimPrim() { + Ps p = MethodReferenceTestFDCCE::isMinor; + assertTrue(p.accept((byte)15)); + } + + public void testMethodReferenceFDPrimBoxed() { + Ps p = MethodReferenceTestFDCCE::stst; + assertTrue(p.accept((byte)15)); + } + + public void testMethodReferenceFDPrimRef() { + Oo p = MethodReferenceTestFDCCE::otst; + assertEquals(p.too(15).getClass().getName(), "java.lang.Integer"); + } + + public void testMethodReferenceFDRet1() { + Reto p = MethodReferenceTestFDCCE::ritst; + assertEquals(p.m(), (Short)(short)123); + } + +} \ No newline at end of file diff --git a/jdk/test/jdk/lambda/MethodReferenceTestInnerDefault.java b/jdk/test/jdk/lambda/MethodReferenceTestInnerDefault.java new file mode 100644 index 00000000000..ea9a76d4c15 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestInnerDefault.java @@ -0,0 +1,79 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +interface IDSs { String m(String a); } + +interface InDefA { + default String xsA__(String s) { + return "A__xsA:" + s; + } + + default String xsAB_(String s) { + return "AB_xsA:" + s; + } + +} + +interface InDefB extends InDefA { + + default String xsAB_(String s) { + return "AB_xsB:" + s; + } + + default String xs_B_(String s) { + return "_B_xsB:" + s; + } +} + +@Test +public class MethodReferenceTestInnerDefault implements InDefB { + + public void testMethodReferenceInnerDefault() { + (new In()).testMethodReferenceInnerDefault(); + } + + class In { + + public void testMethodReferenceInnerDefault() { + IDSs q; + + q = MethodReferenceTestInnerDefault.this::xsA__; + assertEquals(q.m("*"), "A__xsA:*"); + + q = MethodReferenceTestInnerDefault.this::xsAB_; + assertEquals(q.m("*"), "AB_xsB:*"); + + q = MethodReferenceTestInnerDefault.this::xs_B_; + assertEquals(q.m("*"), "_B_xsB:*"); + } + } + +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestInnerInstance.java b/jdk/test/jdk/lambda/MethodReferenceTestInnerInstance.java new file mode 100644 index 00000000000..2aa1526bc4d --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestInnerInstance.java @@ -0,0 +1,86 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestInnerInstance { + + public void testMethodReferenceInnerInstance() { + cia().cib().testMethodReferenceInstance(); + } + + public void testMethodReferenceInnerExternal() { + cia().cib().testMethodReferenceExternal(); + } + + interface SI { + String m(Integer a); + } + + class CIA { + + String xI(Integer i) { + return "xI:" + i; + } + + public class CIB { + + public void testMethodReferenceInstance() { + SI q; + + q = CIA.this::xI; + assertEquals(q.m(55), "xI:55"); + } + + public void testMethodReferenceExternal() { + SI q; + + q = (new E())::xI; + assertEquals(q.m(77), "ExI:77"); + } + } + + CIB cib() { + return new CIB(); + } + + class E { + + String xI(Integer i) { + return "ExI:" + i; + } + } + + } + + CIA cia() { + return new CIA(); + } +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestInnerVarArgsThis.java b/jdk/test/jdk/lambda/MethodReferenceTestInnerVarArgsThis.java new file mode 100644 index 00000000000..06c58dc8ee1 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestInnerVarArgsThis.java @@ -0,0 +1,241 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; +import java.lang.reflect.Array; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestInnerVarArgsThis { + + interface NsII { + + String m(Integer a, Integer b); + } + + interface Nsiii { + + String m(int a, int b, int c); + } + + interface Nsi { + + String m(int a); + } + + interface NsaO { + + String m(Object[] a); + } + + interface Nsai { + + String m(int[] a); + } + + interface Nsvi { + + String m(int... va); + } + + class CIA { + + String xvI(Integer... vi) { + StringBuilder sb = new StringBuilder("xvI:"); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + String xIvI(Integer f, Integer... vi) { + StringBuilder sb = new StringBuilder("xIvI:"); + sb.append(f); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + String xvi(int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xvi:" + sum; + } + + String xIvi(Integer f, int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xIvi:(" + f + ")" + sum; + } + + String xvO(Object... vi) { + StringBuilder sb = new StringBuilder("xvO:"); + for (Object i : vi) { + if (i.getClass().isArray()) { + sb.append("["); + int len = Array.getLength(i); + for (int x = 0; x < len; ++x) { + sb.append(Array.get(i, x)); + sb.append(","); + } + sb.append("]"); + + } else { + sb.append(i); + } + sb.append("*"); + } + return sb.toString(); + } + + public class CIB { + + // These should be processed as var args + public void testVarArgsNsSuperclass() { + NsII q; + + q = CIA.this::xvO; + assertEquals(q.m(55, 66), "xvO:55*66*"); + } + + public void testVarArgsNsArray() { + Nsai q; + + q = CIA.this::xvO; + assertEquals(q.m(new int[]{55, 66}), "xvO:[55,66,]*"); + } + + public void testVarArgsNsII() { + NsII q; + + q = CIA.this::xvI; + assertEquals(q.m(33, 7), "xvI:33-7-"); + + q = CIA.this::xIvI; + assertEquals(q.m(50, 40), "xIvI:5040-"); + + q = CIA.this::xvi; + assertEquals(q.m(100, 23), "xvi:123"); + + q = CIA.this::xIvi; + assertEquals(q.m(9, 21), "xIvi:(9)21"); + } + + public void testVarArgsNsiii() { + Nsiii q; + + q = CIA.this::xvI; + assertEquals(q.m(3, 2, 1), "xvI:3-2-1-"); + + q = CIA.this::xIvI; + assertEquals(q.m(888, 99, 2), "xIvI:88899-2-"); + + q = CIA.this::xvi; + assertEquals(q.m(900, 80, 7), "xvi:987"); + + q = CIA.this::xIvi; + assertEquals(q.m(333, 27, 72), "xIvi:(333)99"); + } + + public void testVarArgsNsi() { + Nsi q; + + q = CIA.this::xvI; + assertEquals(q.m(3), "xvI:3-"); + + q = CIA.this::xIvI; + assertEquals(q.m(888), "xIvI:888"); + + q = CIA.this::xvi; + assertEquals(q.m(900), "xvi:900"); + + q = CIA.this::xIvi; + assertEquals(q.m(333), "xIvi:(333)0"); + } + + // These should NOT be processed as var args + public void testVarArgsNsaO() { + NsaO q; + + q = CIA.this::xvO; + assertEquals(q.m(new String[]{"yo", "there", "dude"}), "xvO:yo*there*dude*"); + } + } + + CIB cib() { + return new CIB(); + } + + class E { + + String xI(Integer i) { + return "ExI:" + i; + } + } + } + + CIA cia() { + return new CIA(); + } + + // These should be processed as var args + public void testVarArgsNsSuperclass() { + cia().cib().testVarArgsNsSuperclass(); + } + + public void testVarArgsNsArray() { + cia().cib().testVarArgsNsArray(); + } + + public void testVarArgsNsII() { + cia().cib().testVarArgsNsII(); + } + + public void testVarArgsNsiii() { + cia().cib().testVarArgsNsiii(); + } + + public void testVarArgsNsi() { + cia().cib().testVarArgsNsi(); + } + + // These should NOT be processed as var args + + public void testVarArgsNsaO() { + cia().cib().testVarArgsNsaO(); + } + + +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestInstance.java b/jdk/test/jdk/lambda/MethodReferenceTestInstance.java new file mode 100644 index 00000000000..2e0634786ff --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestInstance.java @@ -0,0 +1,61 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +class MethodReferenceTestInstance_E { + String xI(Integer i) { + return "ExI:" + i; + } +} + +@Test +public class MethodReferenceTestInstance { + + interface SI { String m(Integer a); } + + String xI(Integer i) { + return "xI:" + i; + } + + public void testMethodReferenceInstance() { + SI q; + + q = this::xI; + assertEquals(q.m(55), "xI:55"); + } + + public void testMethodReferenceExternal() { + SI q; + + q = (new MethodReferenceTestInstance_E())::xI; + assertEquals(q.m(77), "ExI:77"); + } + +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestInstanceMethod.java b/jdk/test/jdk/lambda/MethodReferenceTestInstanceMethod.java new file mode 100644 index 00000000000..b000d648fd1 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestInstanceMethod.java @@ -0,0 +1,59 @@ +/* + * 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. + * + * 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. + */ + + +import java.util.Arrays; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +@Test(groups = "lib") +public class MethodReferenceTestInstanceMethod { + public Stream generate() { + return Arrays.asList("one", "two", "three", "four", "five", "six") + .stream() + .filter(s->s.length() > 3) + .map(s -> s.toUpperCase()); + } + + class Thingy { + U blah(Function m, T val) { + return m.apply(val); + } + } + + public void testStringBuffer() { + String s = generate().collect(Collectors.toStringBuilder()).toString(); + assertEquals(s, "THREEFOURFIVE"); + } + + public void testMRInstance() { + Thingy t = new Thingy<>(); + assertEquals(t.blah(String::toUpperCase, "frogs"), "FROGS"); + } + +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestKinds.java b/jdk/test/jdk/lambda/MethodReferenceTestKinds.java new file mode 100644 index 00000000000..356b3d603d2 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestKinds.java @@ -0,0 +1,173 @@ +/* + * 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. + * + * 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. + */ + + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestKinds extends MethodReferenceTestKindsSup { + + interface S0 { String get(); } + interface S1 { String get(MethodReferenceTestKinds x); } + interface S2 { String get(MethodReferenceTestKinds x, MethodReferenceTestKinds y); } + + interface SXN0 { MethodReferenceTestKindsBase make(MethodReferenceTestKinds x); } + interface SXN1 { MethodReferenceTestKindsBase make(MethodReferenceTestKinds x, String str); } + + interface SN0 { MethodReferenceTestKindsBase make(); } + interface SN1 { MethodReferenceTestKindsBase make(String x); } + + class In extends MethodReferenceTestKindsBase { + In(String val) { + this.val = val; + } + + In() { + this("blank"); + } + } + + String instanceMethod0() { return "IM:0-" + this; } + String instanceMethod1(MethodReferenceTestKinds x) { return "IM:1-" + this + x; } + + static String staticMethod0() { return "SM:0"; } + static String staticMethod1(MethodReferenceTestKinds x) { return "SM:1-" + x; } + + MethodReferenceTestKinds(String val) { + super(val); + } + + MethodReferenceTestKinds() { + super("blank"); + } + + MethodReferenceTestKinds inst(String val) { + return new MethodReferenceTestKinds(val); + } + + public void testMRBound() { + S0 var = this::instanceMethod0; + assertEquals(var.get(), "IM:0-MethodReferenceTestKinds(blank)"); + } + + public void testMRBoundArg() { + S1 var = this::instanceMethod1; + assertEquals(var.get(inst("arg")), "IM:1-MethodReferenceTestKinds(blank)MethodReferenceTestKinds(arg)"); + } + + public void testMRUnbound() { + S1 var = MethodReferenceTestKinds::instanceMethod0; + assertEquals(var.get(inst("rcvr")), "IM:0-MethodReferenceTestKinds(rcvr)"); + } + + public void testMRUnboundArg() { + S2 var = MethodReferenceTestKinds::instanceMethod1; + assertEquals(var.get(inst("rcvr"), inst("arg")), "IM:1-MethodReferenceTestKinds(rcvr)MethodReferenceTestKinds(arg)"); + } + + public void testMRSuper() { + S0 var = super::instanceMethod0; + assertEquals(var.get(), "SIM:0-MethodReferenceTestKinds(blank)"); + } + + public void testMRSuperArg() { + S1 var = super::instanceMethod1; + assertEquals(var.get(inst("arg")), "SIM:1-MethodReferenceTestKinds(blank)MethodReferenceTestKinds(arg)"); + } + + public void testMRStatic() { + S0 var = MethodReferenceTestKinds::staticMethod0; + assertEquals(var.get(), "SM:0"); + } + + public void testMRStaticArg() { + S1 var = MethodReferenceTestKinds::staticMethod1; + assertEquals(var.get(inst("arg")), "SM:1-MethodReferenceTestKinds(arg)"); + } + + public void testMRTopLevel() { + SN0 var = MethodReferenceTestKindsBase::new; + assertEquals(var.make().toString(), "MethodReferenceTestKindsBase(blank)"); + } + + public void testMRTopLevelArg() { + SN1 var = MethodReferenceTestKindsBase::new; + assertEquals(var.make("name").toString(), "MethodReferenceTestKindsBase(name)"); + } +/* unbound inner case not supported anymore (dropped by EG) + public void testMRUnboundInner() { + SXN0 var = MethodReferenceTestKinds.In::new; + assertEquals(var.make(inst("out")).toString(), "In(blank)"); + } + + public void testMRUnboundInnerArg() { + SXN1 var = MethodReferenceTestKinds.In::new; + assertEquals(var.make(inst("out"), "name").toString(), "In(name)"); + } +*/ + public void testMRImplicitInner() { + SN0 var = MethodReferenceTestKinds.In::new; + assertEquals(var.make().toString(), "In(blank)"); + } + + public void testMRImplicitInnerArg() { + SN1 var = MethodReferenceTestKinds.In::new; + assertEquals(var.make("name").toString(), "In(name)"); + } + +} + + +class MethodReferenceTestKindsBase { + String val = "unset"; + + public String toString() { + return getClass().getSimpleName() + "(" + val + ")"; + } + + MethodReferenceTestKindsBase(String val) { + this.val = val; + } + + MethodReferenceTestKindsBase() { + this("blank"); + } + +} + +class MethodReferenceTestKindsSup extends MethodReferenceTestKindsBase { + String instanceMethod0() { return "SIM:0-" + this; } + String instanceMethod1(MethodReferenceTestKinds x) { return "SIM:1-" + this + x; } + + MethodReferenceTestKindsSup(String val) { + super(val); + } + +} + diff --git a/jdk/test/jdk/lambda/MethodReferenceTestNew.java b/jdk/test/jdk/lambda/MethodReferenceTestNew.java new file mode 100644 index 00000000000..b556296a546 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestNew.java @@ -0,0 +1,130 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestNew { + + interface M0 { + + T m(); + } + + static class N0 { + + N0() { + } + } + + interface M1 { + + T m(Integer a); + } + + static class N1 { + + int i; + + N1(int i) { + this.i = i; + } + } + + interface M2 { + + T m(Integer n, String o); + } + + static class N2 { + + Number n; + Object o; + + N2(Number n, Object o) { + this.n = n; + this.o = o; + } + + public String toString() { + return "N2(" + n + "," + o + ")"; + } + } + + interface MV { + + NV m(Integer ai, int i); + } + + static class NV { + + int i; + + NV(int... v) { + i = 0; + for (int x : v) { + i += x; + } + } + + public String toString() { + return "NV(" + i + ")"; + } + } + + public void testConstructorReference0() { + M0 q; + + q = N0::new; + assertEquals(q.m().getClass().getSimpleName(), "N0"); + } + + public void testConstructorReference1() { + M1 q; + + q = N1::new; + assertEquals(q.m(14).getClass().getSimpleName(), "N1"); + } + + public void testConstructorReference2() { + M2 q; + + q = N2::new; + assertEquals(q.m(7, "hi").toString(), "N2(7,hi)"); + } + + public void testConstructorReferenceVarArgs() { + MV q; + + q = NV::new; + assertEquals(q.m(5, 45).toString(), "NV(50)"); + } + +} + diff --git a/jdk/test/jdk/lambda/MethodReferenceTestNewInner.java b/jdk/test/jdk/lambda/MethodReferenceTestNewInner.java new file mode 100644 index 00000000000..084eec335f3 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestNewInner.java @@ -0,0 +1,150 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestNewInner { + + String note = "NO NOTE"; + + interface M0 { + + T m(); + } + + interface MP { + + T m(MethodReferenceTestNewInner m); + } + + class N0 { + + N0() { + } + } + + interface M1 { + + T m(Integer a); + } + + class N1 { + + int i; + + N1(int i) { + this.i = i; + } + } + + interface M2 { + + T m(Integer n, String o); + } + + class N2 { + + Number n; + Object o; + + N2(Number n, Object o) { + this.n = n; + this.o = o; + } + + public String toString() { + return note + ":N2(" + n + "," + o + ")"; + } + } + + interface MV { + + NV m(Integer ai, int i); + } + + class NV { + + int i; + + NV(int... v) { + i = 0; + for (int x : v) { + i += x; + } + } + + public String toString() { + return note + ":NV(" + i + ")"; + } + } + +/* unbound constructor case not supported anymore (dropped by EG) + public static void testConstructorReferenceP() { + MP q; + + q = N0::new; + assertEquals(q.m(new MethodReferenceTestNewInner()).getClass().getSimpleName(), "N0"); + } +*/ + public void testConstructorReference0() { + M0 q; + + q = N0::new; + assertEquals(q.m().getClass().getSimpleName(), "N0"); + } + + public void testConstructorReference1() { + M1 q; + + q = N1::new; + assertEquals(q.m(14).getClass().getSimpleName(), "N1"); + } + + public void testConstructorReference2() { + M2 q; + + note = "T2"; + q = N2::new; + assertEquals(q.m(7, "hi").toString(), "T2:N2(7,hi)"); + } + + /*** + public void testConstructorReferenceVarArgs() { + MV q; + + note = "TVA"; + q = NV::new; + assertEquals(q.m(5, 45).toString(), "TNV:NV(50)"); + } + ***/ + +} + + diff --git a/jdk/test/jdk/lambda/MethodReferenceTestSueCase1.java b/jdk/test/jdk/lambda/MethodReferenceTestSueCase1.java new file mode 100644 index 00000000000..89bb988f7db --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestSueCase1.java @@ -0,0 +1,46 @@ +/* + * 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. + * + * 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. + */ + + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestSueCase1 { + + public interface Sam2 { public String get(T target, String s); } + + String instanceMethod(String s) { return "2"; } + Sam2 var = MethodReferenceTestSueCase1::instanceMethod; + + String m() { return var.get(new MethodReferenceTestSueCase1(), ""); } + + public void testSueCase1() { + assertEquals(m(), "2"); + } +} \ No newline at end of file diff --git a/jdk/test/jdk/lambda/MethodReferenceTestSueCase2.java b/jdk/test/jdk/lambda/MethodReferenceTestSueCase2.java new file mode 100644 index 00000000000..f967f9d3eeb --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestSueCase2.java @@ -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. + * + * 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. + */ + + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestSueCase2 { + + public interface Sam2 { public String get(T target, String s); } + + String instanceMethod(String s) { return "2"; } + static Sam2 var = MethodReferenceTestSueCase2::instanceMethod; + + String m() { return var.get(new MethodReferenceTestSueCase2(), ""); } + + public void testSueCase2() { + assertEquals(m(), "2"); + } + +} \ No newline at end of file diff --git a/jdk/test/jdk/lambda/MethodReferenceTestSueCase4.java b/jdk/test/jdk/lambda/MethodReferenceTestSueCase4.java new file mode 100644 index 00000000000..c14b31f82c8 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestSueCase4.java @@ -0,0 +1,52 @@ +/* + * 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. + * + * 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. + */ + + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestSueCase4 { + + public interface Sam2 { public String get(T target, String s); } + + Sam2 var = new Object().equals(new Object()) ? Target::instanceMethod : Target::instanceMethod; + + String m() { + return var.get(new Target(), ""); + } + + static class Target { + String instanceMethod(String s) { return "2"; } + } + + public void testSueCase4() { + assertEquals(m(), "2"); + } + +} \ No newline at end of file diff --git a/jdk/test/jdk/lambda/MethodReferenceTestSuper.java b/jdk/test/jdk/lambda/MethodReferenceTestSuper.java new file mode 100644 index 00000000000..1fee7e167ac --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestSuper.java @@ -0,0 +1,113 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + + + +/** + * @author Robert Field + */ + +interface SPRI { String m(String a); } + +class SPRA { + String xsA__(String s) { + return "A__xsA:" + s; + } + + String xsA_M(String s) { + return "A_MxsA:" + s; + } + + String xsAB_(String s) { + return "AB_xsA:" + s; + } + + String xsABM(String s) { + return "ABMxsA:" + s; + } + +} + +class SPRB extends SPRA { + + String xsAB_(String s) { + return "AB_xsB:" + s; + } + + String xsABM(String s) { + return "ABMxsB:" + s; + } + + String xs_B_(String s) { + return "_B_xsB:" + s; + } + + String xs_BM(String s) { + return "_BMxsB:" + s; + } + +} + +@Test +public class MethodReferenceTestSuper extends SPRB { + + String xsA_M(String s) { + return "A_MxsM:" + s; + } + + + String xsABM(String s) { + return "ABMxsM:" + s; + } + + String xs_BM(String s) { + return "_BMxsM:" + s; + } + + public void testMethodReferenceSuper() { + SPRI q; + + q = super::xsA__; + assertEquals(q.m("*"), "A__xsA:*"); + + q = super::xsA_M; + assertEquals(q.m("*"), "A_MxsA:*"); + + q = super::xsAB_; + assertEquals(q.m("*"), "AB_xsB:*"); + + q = super::xsABM; + assertEquals(q.m("*"), "ABMxsB:*"); + + q = super::xs_B_; + assertEquals(q.m("*"), "_B_xsB:*"); + + q = super::xs_BM; + assertEquals(q.m("*"), "_BMxsB:*"); + } + +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestSuperDefault.java b/jdk/test/jdk/lambda/MethodReferenceTestSuperDefault.java new file mode 100644 index 00000000000..103961e7308 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestSuperDefault.java @@ -0,0 +1,74 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + + +/** + * @author Robert Field + */ + +interface DSPRI { String m(String a); } + +interface DSPRA { + default String xsA__(String s) { + return "A__xsA:" + s; + } + + default String xsAB_(String s) { + return "AB_xsA:" + s; + } + +} + +interface DSPRB extends DSPRA { + + default String xsAB_(String s) { + return "AB_xsB:" + s; + } + + default String xs_B_(String s) { + return "_B_xsB:" + s; + } + +} + +@Test +public class MethodReferenceTestSuperDefault implements DSPRB { + + public void testMethodReferenceSuper() { + DSPRI q; + + q = DSPRB.super::xsA__; + assertEquals(q.m("*"), "A__xsA:*"); + + q = DSPRB.super::xsAB_; + assertEquals(q.m("*"), "AB_xsB:*"); + + q = DSPRB.super::xs_B_; + assertEquals(q.m("*"), "_B_xsB:*"); + } + +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestTypeConversion.java b/jdk/test/jdk/lambda/MethodReferenceTestTypeConversion.java new file mode 100644 index 00000000000..e690a9fc305 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestTypeConversion.java @@ -0,0 +1,53 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +class MethodReferenceTestTypeConversion_E { + T xI(T t) { return t; } +} + +@Test +public class MethodReferenceTestTypeConversion { + + interface ISi { int m(Short a); } + + interface ICc { char m(Character a); } + + public void testUnboxObjectToNumberWiden() { + ISi q = (new MethodReferenceTestTypeConversion_E())::xI; + assertEquals(q.m((short)77), (short)77); + } + + public void testUnboxObjectToChar() { + ICc q = (new MethodReferenceTestTypeConversion_E())::xI; + assertEquals(q.m('@'), '@'); + } + +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestVarArgs.java b/jdk/test/jdk/lambda/MethodReferenceTestVarArgs.java new file mode 100644 index 00000000000..0e58edb58c5 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestVarArgs.java @@ -0,0 +1,195 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; +import java.lang.reflect.Array; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestVarArgs { + + interface SII { + + String m(Integer a, Integer b); + } + + interface Siii { + + String m(int a, int b, int c); + } + + interface Si { + + String m(int a); + } + + interface SaO { + + String m(Object[] a); + } + + interface Sai { + + String m(int[] a); + } + + interface Svi { + + String m(int... va); + } + + // These should be processed as var args + + static String xvI(Integer... vi) { + StringBuilder sb = new StringBuilder("xvI:"); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + static String xIvI(Integer f, Integer... vi) { + StringBuilder sb = new StringBuilder("xIvI:"); + sb.append(f); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + static String xvi(int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xvi:" + sum; + } + + static String xIvi(Integer f, int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xIvi:(" + f + ")" + sum; + } + + static String xvO(Object... vi) { + StringBuilder sb = new StringBuilder("xvO:"); + for (Object i : vi) { + if (i.getClass().isArray()) { + sb.append("["); + int len = Array.getLength(i); + for (int x = 0; x < len; ++x) { + sb.append(Array.get(i, x)); + sb.append(","); + } + sb.append("]"); + + } else { + sb.append(i); + } + sb.append("*"); + } + return sb.toString(); + } + + public void testVarArgsSuperclass() { + SII q; + + q = MethodReferenceTestVarArgs::xvO; + assertEquals(q.m(55,66), "xvO:55*66*"); + } + + public void testVarArgsArray() { + Sai q; + + q = MethodReferenceTestVarArgs::xvO; + assertEquals(q.m(new int[] { 55,66 } ), "xvO:[55,66,]*"); + } + + public void testVarArgsII() { + SII q; + + q = MethodReferenceTestVarArgs::xvI; + assertEquals(q.m(33,7), "xvI:33-7-"); + + q = MethodReferenceTestVarArgs::xIvI; + assertEquals(q.m(50,40), "xIvI:5040-"); + + q = MethodReferenceTestVarArgs::xvi; + assertEquals(q.m(100,23), "xvi:123"); + + q = MethodReferenceTestVarArgs::xIvi; + assertEquals(q.m(9,21), "xIvi:(9)21"); + } + + public void testVarArgsiii() { + Siii q; + + q = MethodReferenceTestVarArgs::xvI; + assertEquals(q.m(3, 2, 1), "xvI:3-2-1-"); + + q = MethodReferenceTestVarArgs::xIvI; + assertEquals(q.m(888, 99, 2), "xIvI:88899-2-"); + + q = MethodReferenceTestVarArgs::xvi; + assertEquals(q.m(900,80,7), "xvi:987"); + + q = MethodReferenceTestVarArgs::xIvi; + assertEquals(q.m(333,27, 72), "xIvi:(333)99"); + } + + public void testVarArgsi() { + Si q; + + q = MethodReferenceTestVarArgs::xvI; + assertEquals(q.m(3), "xvI:3-"); + + q = MethodReferenceTestVarArgs::xIvI; + assertEquals(q.m(888), "xIvI:888"); + + q = MethodReferenceTestVarArgs::xvi; + assertEquals(q.m(900), "xvi:900"); + + q = MethodReferenceTestVarArgs::xIvi; + assertEquals(q.m(333), "xIvi:(333)0"); + } + + // These should NOT be processed as var args + + public void testVarArgsaO() { + SaO q; + + q = MethodReferenceTestVarArgs::xvO; + assertEquals(q.m(new String[] { "yo", "there", "dude" }), "xvO:yo*there*dude*"); + } + + +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestVarArgsExt.java b/jdk/test/jdk/lambda/MethodReferenceTestVarArgsExt.java new file mode 100644 index 00000000000..8101722760d --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestVarArgsExt.java @@ -0,0 +1,182 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; +import java.lang.reflect.Array; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +interface NXII { String m(Integer a, Integer b); } + +interface NXiii { String m(int a, int b, int c); } + +interface NXi { String m(int a); } + +interface NXaO { String m(Object[] a); } + +interface NXai { String m(int[] a); } + +interface NXvi { String m(int... va); } + +@Test +public class MethodReferenceTestVarArgsExt { + + // These should be processed as var args + + public void testVarArgsNXSuperclass() { + NXII q; + + q = (new Ext())::xvO; + assertEquals(q.m(55,66), "xvO:55*66*"); + } + + public void testVarArgsNXArray() { + NXai q; + + q = (new Ext())::xvO; + assertEquals(q.m(new int[] { 55,66 } ), "xvO:[55,66,]*"); + } + + public void testVarArgsNXII() { + NXII q; + + q = (new Ext())::xvI; + assertEquals(q.m(33,7), "xvI:33-7-"); + + q = (new Ext())::xIvI; + assertEquals(q.m(50,40), "xIvI:5040-"); + + q = (new Ext())::xvi; + assertEquals(q.m(100,23), "xvi:123"); + + q = (new Ext())::xIvi; + assertEquals(q.m(9,21), "xIvi:(9)21"); + } + + public void testVarArgsNXiii() { + NXiii q; + + q = (new Ext())::xvI; + assertEquals(q.m(3, 2, 1), "xvI:3-2-1-"); + + q = (new Ext())::xIvI; + assertEquals(q.m(888, 99, 2), "xIvI:88899-2-"); + + q = (new Ext())::xvi; + assertEquals(q.m(900,80,7), "xvi:987"); + + q = (new Ext())::xIvi; + assertEquals(q.m(333,27, 72), "xIvi:(333)99"); + } + + public void testVarArgsNXi() { + NXi q; + + q = (new Ext())::xvI; + assertEquals(q.m(3), "xvI:3-"); + + q = (new Ext())::xIvI; + assertEquals(q.m(888), "xIvI:888"); + + q = (new Ext())::xvi; + assertEquals(q.m(900), "xvi:900"); + + q = (new Ext())::xIvi; + assertEquals(q.m(333), "xIvi:(333)0"); + } + + // These should NOT be processed as var args + + public void testVarArgsNXaO() { + NXaO q; + + q = (new Ext())::xvO; + assertEquals(q.m(new String[] { "yo", "there", "dude" }), "xvO:yo*there*dude*"); + } + + +} + +class Ext { + + String xvI(Integer... vi) { + StringBuilder sb = new StringBuilder("xvI:"); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + String xIvI(Integer f, Integer... vi) { + StringBuilder sb = new StringBuilder("xIvI:"); + sb.append(f); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + String xvi(int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xvi:" + sum; + } + + String xIvi(Integer f, int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xIvi:(" + f + ")" + sum; + } + + String xvO(Object... vi) { + StringBuilder sb = new StringBuilder("xvO:"); + for (Object i : vi) { + if (i.getClass().isArray()) { + sb.append("["); + int len = Array.getLength(i); + for (int x = 0; x < len; ++x) { + sb.append(Array.get(i, x)); + sb.append(","); + } + sb.append("]"); + + } else { + sb.append(i); + } + sb.append("*"); + } + return sb.toString(); + } + + +} diff --git a/jdk/test/jdk/lambda/MethodReferenceTestVarArgsSuper.java b/jdk/test/jdk/lambda/MethodReferenceTestVarArgsSuper.java new file mode 100644 index 00000000000..2c37099be48 --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestVarArgsSuper.java @@ -0,0 +1,200 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; +import java.lang.reflect.Array; + +import static org.testng.Assert.assertEquals; + + +/** + * @author Robert Field + */ + +class MethodReferenceTestVarArgsSuper_Sub { + + String xvI(Integer... vi) { + StringBuilder sb = new StringBuilder("xvI:"); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + String xIvI(Integer f, Integer... vi) { + StringBuilder sb = new StringBuilder("xIvI:"); + sb.append(f); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + String xvi(int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xvi:" + sum; + } + + String xIvi(Integer f, int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xIvi:(" + f + ")" + sum; + } + + String xvO(Object... vi) { + StringBuilder sb = new StringBuilder("xvO:"); + for (Object i : vi) { + if (i.getClass().isArray()) { + sb.append("["); + int len = Array.getLength(i); + for (int x = 0; x < len; ++x) { + sb.append(Array.get(i, x)); + sb.append(","); + } + sb.append("]"); + + } else { + sb.append(i); + } + sb.append("*"); + } + return sb.toString(); + } +} + +@Test +public class MethodReferenceTestVarArgsSuper extends MethodReferenceTestVarArgsSuper_Sub { + + interface SPRII { String m(Integer a, Integer b); } + + interface SPRiii { String m(int a, int b, int c); } + + interface SPRi { String m(int a); } + + interface SPRaO { String m(Object[] a); } + + interface SPRai { String m(int[] a); } + + interface SPRvi { String m(int... va); } + + String xvI(Integer... vi) { + return "ERROR"; + } + + String xIvI(Integer f, Integer... vi) { + return "ERROR"; + } + + String xvi(int... vi) { + return "ERROR"; + } + + String xIvi(Integer f, int... vi) { + return "ERROR"; + } + + String xvO(Object... vi) { + return "ERROR"; + } + + // These should be processed as var args + + public void testVarArgsSPRSuperclass() { + SPRII q; + + q = super::xvO; + assertEquals(q.m(55,66), "xvO:55*66*"); + } + + public void testVarArgsSPRArray() { + SPRai q; + + q = super::xvO; + assertEquals(q.m(new int[] { 55,66 } ), "xvO:[55,66,]*"); + } + + public void testVarArgsSPRII() { + SPRII q; + + q = super::xvI; + assertEquals(q.m(33,7), "xvI:33-7-"); + + q = super::xIvI; + assertEquals(q.m(50,40), "xIvI:5040-"); + + q = super::xvi; + assertEquals(q.m(100,23), "xvi:123"); + + q = super::xIvi; + assertEquals(q.m(9,21), "xIvi:(9)21"); + } + + public void testVarArgsSPRiii() { + SPRiii q; + + q = super::xvI; + assertEquals(q.m(3, 2, 1), "xvI:3-2-1-"); + + q = super::xIvI; + assertEquals(q.m(888, 99, 2), "xIvI:88899-2-"); + + q = super::xvi; + assertEquals(q.m(900,80,7), "xvi:987"); + + q = super::xIvi; + assertEquals(q.m(333,27, 72), "xIvi:(333)99"); + } + + public void testVarArgsSPRi() { + SPRi q; + + q = super::xvI; + assertEquals(q.m(3), "xvI:3-"); + + q = super::xIvI; + assertEquals(q.m(888), "xIvI:888"); + + q = super::xvi; + assertEquals(q.m(900), "xvi:900"); + + q = super::xIvi; + assertEquals(q.m(333), "xIvi:(333)0"); + } + + // These should NOT be processed as var args + + public void testVarArgsSPRaO() { + SPRaO q; + + q = super::xvO; + assertEquals(q.m(new String[] { "yo", "there", "dude" }), "xvO:yo*there*dude*"); + } +} + diff --git a/jdk/test/jdk/lambda/MethodReferenceTestVarArgsSuperDefault.java b/jdk/test/jdk/lambda/MethodReferenceTestVarArgsSuperDefault.java new file mode 100644 index 00000000000..8f3bd87ad7f --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestVarArgsSuperDefault.java @@ -0,0 +1,181 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; +import java.lang.reflect.Array; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +interface MethodReferenceTestVarArgsSuperDefault_I { + + default String xvI(Integer... vi) { + StringBuilder sb = new StringBuilder("xvI:"); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + default String xIvI(Integer f, Integer... vi) { + StringBuilder sb = new StringBuilder("xIvI:"); + sb.append(f); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + default String xvi(int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xvi:" + sum; + } + + default String xIvi(Integer f, int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xIvi:(" + f + ")" + sum; + } + + default String xvO(Object... vi) { + StringBuilder sb = new StringBuilder("xvO:"); + for (Object i : vi) { + if (i.getClass().isArray()) { + sb.append("["); + int len = Array.getLength(i); + for (int x = 0; x < len; ++x) { + sb.append(Array.get(i, x)); + sb.append(","); + } + sb.append("]"); + + } else { + sb.append(i); + } + sb.append("*"); + } + return sb.toString(); + } +} + +@Test +public class MethodReferenceTestVarArgsSuperDefault implements MethodReferenceTestVarArgsSuperDefault_I { + + interface DSPRII { String m(Integer a, Integer b); } + + interface DSPRiii { String m(int a, int b, int c); } + + interface DSPRi { String m(int a); } + + interface DSPRaO { String m(Object[] a); } + + interface DSPRai { String m(int[] a); } + + interface DSPRvi { String m(int... va); } + + // These should be processed as var args + + public void testVarArgsSPRSuperclass() { + DSPRII q; + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xvO; + assertEquals(q.m(55,66), "xvO:55*66*"); + } + + public void testVarArgsSPRArray() { + DSPRai q; + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xvO; + assertEquals(q.m(new int[] { 55,66 } ), "xvO:[55,66,]*"); + } + + public void testVarArgsSPRII() { + DSPRII q; + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xvI; + assertEquals(q.m(33,7), "xvI:33-7-"); + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xIvI; + assertEquals(q.m(50,40), "xIvI:5040-"); + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xvi; + assertEquals(q.m(100,23), "xvi:123"); + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xIvi; + assertEquals(q.m(9,21), "xIvi:(9)21"); + } + + public void testVarArgsSPRiii() { + DSPRiii q; + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xvI; + assertEquals(q.m(3, 2, 1), "xvI:3-2-1-"); + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xIvI; + assertEquals(q.m(888, 99, 2), "xIvI:88899-2-"); + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xvi; + assertEquals(q.m(900,80,7), "xvi:987"); + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xIvi; + assertEquals(q.m(333,27, 72), "xIvi:(333)99"); + } + + public void testVarArgsSPRi() { + DSPRi q; + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xvI; + assertEquals(q.m(3), "xvI:3-"); + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xIvI; + assertEquals(q.m(888), "xIvI:888"); + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xvi; + assertEquals(q.m(900), "xvi:900"); + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xIvi; + assertEquals(q.m(333), "xIvi:(333)0"); + } + + // These should NOT be processed as var args + + public void testVarArgsSPRaO() { + DSPRaO q; + + q = MethodReferenceTestVarArgsSuperDefault_I.super::xvO; + assertEquals(q.m(new String[] { "yo", "there", "dude" }), "xvO:yo*there*dude*"); + } + + +} + diff --git a/jdk/test/jdk/lambda/MethodReferenceTestVarArgsThis.java b/jdk/test/jdk/lambda/MethodReferenceTestVarArgsThis.java new file mode 100644 index 00000000000..eb5dfca7bad --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestVarArgsThis.java @@ -0,0 +1,177 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; +import java.lang.reflect.Array; + +import static org.testng.Assert.assertEquals; + +/** + * @author Robert Field + */ + +interface NsII { String m(Integer a, Integer b); } + +interface Nsiii { String m(int a, int b, int c); } + +interface Nsi { String m(int a); } + +interface NsaO { String m(Object[] a); } + +interface Nsai { String m(int[] a); } + +interface Nsvi { String m(int... va); } + +@Test +public class MethodReferenceTestVarArgsThis { + + // These should be processed as var args + + String xvI(Integer... vi) { + StringBuilder sb = new StringBuilder("xvI:"); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + String xIvI(Integer f, Integer... vi) { + StringBuilder sb = new StringBuilder("xIvI:"); + sb.append(f); + for (Integer i : vi) { + sb.append(i); + sb.append("-"); + } + return sb.toString(); + } + + String xvi(int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xvi:" + sum; + } + + String xIvi(Integer f, int... vi) { + int sum = 0; + for (int i : vi) { + sum += i; + } + return "xIvi:(" + f + ")" + sum; + } + + String xvO(Object... vi) { + StringBuilder sb = new StringBuilder("xvO:"); + for (Object i : vi) { + if (i.getClass().isArray()) { + sb.append("["); + int len = Array.getLength(i); + for (int x = 0; x < len; ++x) { + sb.append(Array.get(i, x)); + sb.append(","); + } + sb.append("]"); + + } else { + sb.append(i); + } + sb.append("*"); + } + return sb.toString(); + } + + public void testVarArgsNsSuperclass() { + NsII q; + + q = this::xvO; + assertEquals(q.m(55,66), "xvO:55*66*"); + } + + public void testVarArgsNsArray() { + Nsai q; + + q = this::xvO; + assertEquals(q.m(new int[] { 55,66 } ), "xvO:[55,66,]*"); + } + + public void testVarArgsNsII() { + NsII q; + + q = this::xvI; + assertEquals(q.m(33,7), "xvI:33-7-"); + + q = this::xIvI; + assertEquals(q.m(50,40), "xIvI:5040-"); + + q = this::xvi; + assertEquals(q.m(100,23), "xvi:123"); + + q = this::xIvi; + assertEquals(q.m(9,21), "xIvi:(9)21"); + } + + public void testVarArgsNsiii() { + Nsiii q; + + q = this::xvI; + assertEquals(q.m(3, 2, 1), "xvI:3-2-1-"); + + q = this::xIvI; + assertEquals(q.m(888, 99, 2), "xIvI:88899-2-"); + + q = this::xvi; + assertEquals(q.m(900,80,7), "xvi:987"); + + q = this::xIvi; + assertEquals(q.m(333,27, 72), "xIvi:(333)99"); + } + + public void testVarArgsNsi() { + Nsi q; + + q = this::xvI; + assertEquals(q.m(3), "xvI:3-"); + + q = this::xIvI; + assertEquals(q.m(888), "xIvI:888"); + + q = this::xvi; + assertEquals(q.m(900), "xvi:900"); + + q = this::xIvi; + assertEquals(q.m(333), "xIvi:(333)0"); + } + + // These should NOT be processed as var args + + public void testVarArgsNsaO() { + NsaO q; + + q = this::xvO; + assertEquals(q.m(new String[] { "yo", "there", "dude" }), "xvO:yo*there*dude*"); + } + + +} diff --git a/jdk/test/jdk/lambda/TEST.properties b/jdk/test/jdk/lambda/TEST.properties new file mode 100644 index 00000000000..318077cff6b --- /dev/null +++ b/jdk/test/jdk/lambda/TEST.properties @@ -0,0 +1,5 @@ +# This file identifies root(s) of the test-ng hierarchy. + +TestNG.dirs = . + +javatest.maxOutputSize = 250000 diff --git a/jdk/test/jdk/lambda/TestInnerCtorRef.java b/jdk/test/jdk/lambda/TestInnerCtorRef.java new file mode 100644 index 00000000000..7b9ac1d7520 --- /dev/null +++ b/jdk/test/jdk/lambda/TestInnerCtorRef.java @@ -0,0 +1,63 @@ +/* + * 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. + * + * 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. + */ + +import org.testng.annotations.Test; + +import java.util.function.Supplier; + +/** + * TestInnerCtorRef + */ +// @Test +public class TestInnerCtorRef { + + public void testCtorRef() { + A a = A.make(() -> ""); + } +} + +abstract class A { + abstract T make(); + + private A() { + } + + public interface Foo { } + public static A make(Supplier factory) { + class Local implements Foo { + Supplier f = factory; + } + return new Helper(Local::new); + } + + private static class Helper extends A { + + private Helper(Supplier> factory) { + } + + @Override + T make() { + return null; + } + } +} diff --git a/jdk/test/jdk/lambda/TestPrivateCtorRef.java b/jdk/test/jdk/lambda/TestPrivateCtorRef.java new file mode 100644 index 00000000000..a358a04f068 --- /dev/null +++ b/jdk/test/jdk/lambda/TestPrivateCtorRef.java @@ -0,0 +1,60 @@ +/* + * 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. + * + * 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. + */ + +import java.util.function.Supplier; + +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** + * TestPrivateCtorRef + */ +@Test +public class TestPrivateCtorRef { + // @@@ Really, this needs to be a combo test: + // target class = nested static, nested instance, auxilliary + // class protection = PPPP + // ctor protection = PPPP + // ctor = explicit, explicit + // ref = lambda, method ref + static T makeOne(Supplier supp) { + T t = supp.get(); + assertNotNull(t != null); + return t; + } + + public void testPrivateStatic() { + makeOne(PS::new); + } + + private static class PS { + } + + public void testPrivateInstance() { + makeOne(PI::new); + } + + private class PI { + } +} + diff --git a/jdk/test/jdk/lambda/separate/AttributeInjector.java b/jdk/test/jdk/lambda/separate/AttributeInjector.java new file mode 100644 index 00000000000..6ea11154c9f --- /dev/null +++ b/jdk/test/jdk/lambda/separate/AttributeInjector.java @@ -0,0 +1,71 @@ +/* + * 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. + * + * 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 separate; + +import java.io.*; + +public class AttributeInjector implements ClassFilePreprocessor { + + private String attributeName; + private byte[] attributeData; + + public AttributeInjector(String attributeName, byte[] attributeData) { + this.attributeName = attributeName; + this.attributeData = attributeData; + } + + public byte[] preprocess(String name, byte[] cf) { + ClassFile classfile = new ClassFile(cf); + + short cpIndex = (short)classfile.constant_pool.size(); + + ClassFile.CpUtf8 entry = new ClassFile.CpUtf8(); + entry.bytes = new byte[attributeName.length()]; + for (int i = 0; i < attributeName.length(); ++i) { + entry.bytes[i] = (byte)attributeName.charAt(i); + } + + classfile.constant_pool.add(entry); + + ClassFile.Attribute attr = new ClassFile.Attribute(); + attr.attribute_name_index = cpIndex; + attr.info = attributeData; + + classfile.attributes.add(attr); + return classfile.toByteArray(); + } + +/* + public static void main(String argv[]) throws Exception { + File input = new File(argv[0]); + byte[] buffer = new byte[(int)input.length()]; + new FileInputStream(input).read(buffer); + + ClassFilePreprocessor cfp = + new AttributeInjector("RequiresBridges", new byte[0]); + byte[] cf = cfp.preprocess(argv[0], buffer); + new FileOutputStream(argv[0] + ".mod").write(cf); + } +*/ +} diff --git a/jdk/test/jdk/lambda/separate/ClassFile.java b/jdk/test/jdk/lambda/separate/ClassFile.java new file mode 100644 index 00000000000..7da140b8177 --- /dev/null +++ b/jdk/test/jdk/lambda/separate/ClassFile.java @@ -0,0 +1,452 @@ +/* + * 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. + * + * 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 separate; + +import java.io.*; +import java.util.*; + +class CfInputStream extends ByteArrayInputStream { + private int ct; + public CfInputStream(byte[] input) { + super(input); + } + + byte u1() { return (byte)read(); } + short u2() { + int b0 = read() << 8; + int b1 = read(); + return (short)(b0 | b1); + } + int u4() { + int b0 = read() << 24; + int b1 = read() << 16; + int b2 = read() << 8; + int b3 = read(); + return b0 | b1 | b2 | b3; + } + byte[] array(int count) { + byte[] ret = new byte[count]; + read(ret, 0, count); + return ret; + } +}; + +class CfOutputStream extends ByteArrayOutputStream { + void u1(byte b) { write((int)b); } + void u2(short s) { + write((s >> 8) & 0xff); + write(s & 0xff); + } + void u4(int i) { + write((i >> 24) & 0xff); + write((i >> 16) & 0xff); + write((i >> 8) & 0xff); + write(i & 0xff); + } + void array(byte[] a) { + write(a, 0, a.length); + } + + public byte[] toByteArray() { return super.toByteArray(); } +}; + +// A quick and dirty class file parser and representation +public class ClassFile { + + int magic; + short minor_version; + short major_version; + ArrayList constant_pool; + short access_flags; + short this_class; + short super_class; + ArrayList interfaces; + ArrayList fields; + ArrayList methods; + ArrayList attributes; + + ClassFile(byte[] cf) { + CfInputStream in = new CfInputStream(cf); + + magic = in.u4(); + minor_version = in.u2(); + major_version = in.u2(); + + short cpCount = in.u2(); + constant_pool = new ArrayList<>(); + constant_pool.add(new CpNull()); + for (int i = 1; i < cpCount; ++i) { + constant_pool.add(CpEntry.newCpEntry(in)); + } + + access_flags = in.u2(); + this_class = in.u2(); + super_class = in.u2(); + + short ifaceCount = in.u2(); + interfaces = new ArrayList<>(); + for (int i = 0; i < ifaceCount; ++i) { + interfaces.add(new Interface(in)); + } + + short fieldCount = in.u2(); + fields = new ArrayList<>(); + for (int i = 0; i < fieldCount; ++i) { + fields.add(new Field(in)); + } + + short methodCount = in.u2(); + methods = new ArrayList<>(); + for (int i = 0; i < methodCount; ++i) { + methods.add(new Method(in)); + } + + short attributeCount = in.u2(); + attributes = new ArrayList<>(); + for (int i = 0; i < attributeCount; ++i) { + attributes.add(new Attribute(in)); + } + } + + byte[] toByteArray() { + CfOutputStream out = new CfOutputStream(); + + out.u4(magic); + out.u2(minor_version); + out.u2(major_version); + + out.u2((short)(constant_pool.size())); + for (CpEntry cp : constant_pool) { + cp.write(out); + } + + out.u2(access_flags); + out.u2(this_class); + out.u2(super_class); + + out.u2((short)interfaces.size()); + for (Interface iface : interfaces) { + iface.write(out); + } + + out.u2((short)fields.size()); + for (Field field : fields) { + field.write(out); + } + + out.u2((short)methods.size()); + for (Method method : methods) { + method.write(out); + } + + out.u2((short)attributes.size()); + for (Attribute attribute : attributes) { + attribute.write(out); + } + + return out.toByteArray(); + } + + static abstract class CpEntry { + byte tag; + + CpEntry(byte t) { tag = t; } + void write(CfOutputStream out) { + out.u1(tag); + } + + static CpEntry newCpEntry(CfInputStream in) { + byte tag = in.u1(); + switch (tag) { + case CpUtf8.TAG: return new CpUtf8(in); + case CpInteger.TAG: return new CpInteger(in); + case CpFloat.TAG: return new CpFloat(in); + case CpLong.TAG: return new CpLong(in); + case CpDouble.TAG: return new CpDouble(in); + case CpClass.TAG: return new CpClass(in); + case CpString.TAG: return new CpString(in); + case CpFieldRef.TAG: return new CpFieldRef(in); + case CpMethodRef.TAG: return new CpMethodRef(in); + case CpInterfaceMethodRef.TAG: + return new CpInterfaceMethodRef(in); + case CpNameAndType.TAG: return new CpNameAndType(in); + case CpMethodHandle.TAG: return new CpMethodHandle(in); + case CpMethodType.TAG: return new CpMethodType(in); + case CpInvokeDynamic.TAG: return new CpInvokeDynamic(in); + default: throw new RuntimeException("Bad cp entry tag: " + tag); + } + } + } + + static class CpNull extends CpEntry { + CpNull() { super((byte)0); } + CpNull(CfInputStream in) { super((byte)0); } + void write(CfOutputStream out) {} + } + + static class CpUtf8 extends CpEntry { + static final byte TAG = 1; + byte[] bytes; + + CpUtf8() { super(TAG); } + CpUtf8(CfInputStream in) { + this(); + short length = in.u2(); + bytes = in.array(length); + } + void write(CfOutputStream out) { + super.write(out); + out.u2((short)bytes.length); + out.array(bytes); + } + } + + static class CpU4Constant extends CpEntry { + byte[] bytes; + + CpU4Constant(byte tag) { super(tag); } + CpU4Constant(byte tag, CfInputStream in) { + this(tag); + bytes = in.array(4); + } + void write(CfOutputStream out) { super.write(out); out.array(bytes); } + } + static class CpInteger extends CpU4Constant { + static final byte TAG = 3; + CpInteger() { super(TAG); } + CpInteger(CfInputStream in) { super(TAG, in); } + } + static class CpFloat extends CpU4Constant { + static final byte TAG = 4; + CpFloat() { super(TAG); } + CpFloat(CfInputStream in) { super(TAG, in); } + } + + static class CpU8Constant extends CpEntry { + byte[] bytes; + + CpU8Constant(byte tag) { super(tag); } + CpU8Constant(byte tag, CfInputStream in) { + this(tag); + bytes = in.array(8); + } + void write(CfOutputStream out) { super.write(out); out.array(bytes); } + } + static class CpLong extends CpU8Constant { + static final byte TAG = 5; + CpLong() { super(TAG); } + CpLong(CfInputStream in) { super(TAG, in); } + } + static class CpDouble extends CpU8Constant { + static final byte TAG = 6; + CpDouble() { super(TAG); } + CpDouble(CfInputStream in) { super(TAG, in); } + } + + static class CpClass extends CpEntry { + static final byte TAG = 7; + short name_index; + + CpClass() { super(TAG); } + CpClass(CfInputStream in) { super(TAG); name_index = in.u2(); } + void write(CfOutputStream out) { + super.write(out); + out.u2(name_index); + } + } + + static class CpString extends CpEntry { + static final byte TAG = 8; + short string_index; + + CpString() { super(TAG); } + CpString(CfInputStream in) { super(TAG); string_index = in.u2(); } + void write(CfOutputStream out) { + super.write(out); + out.u2(string_index); + } + } + + static class CpRef extends CpEntry { + short class_index; + short name_and_type_index; + + CpRef(byte tag) { super(tag); } + CpRef(byte tag, CfInputStream in) { + this(tag); + class_index = in.u2(); + name_and_type_index = in.u2(); + } + void write(CfOutputStream out) { + super.write(out); + out.u2(class_index); + out.u2(name_and_type_index); + } + } + static class CpFieldRef extends CpRef { + static final byte TAG = 9; + CpFieldRef() { super(TAG); } + CpFieldRef(CfInputStream in) { super(TAG, in); } + } + static class CpMethodRef extends CpRef { + static final byte TAG = 10; + CpMethodRef() { super(TAG); } + CpMethodRef(CfInputStream in) { super(TAG, in); } + } + static class CpInterfaceMethodRef extends CpRef { + static final byte TAG = 11; + CpInterfaceMethodRef() { super(TAG); } + CpInterfaceMethodRef(CfInputStream in) { super(TAG, in); } + } + + static class CpNameAndType extends CpEntry { + static final byte TAG = 12; + short name_index; + short descriptor_index; + + CpNameAndType() { super(TAG); } + CpNameAndType(CfInputStream in) { + this(); + name_index = in.u2(); + descriptor_index = in.u2(); + } + void write(CfOutputStream out) { + super.write(out); + out.u2(name_index); + out.u2(descriptor_index); + } + } + + static class CpMethodHandle extends CpEntry { + static final byte TAG = 15; + byte reference_kind; + short reference_index; + + CpMethodHandle() { super(TAG); } + CpMethodHandle(CfInputStream in) { + this(); + reference_kind = in.u1(); + reference_index = in.u2(); + } + void write(CfOutputStream out) { + super.write(out); + out.u1(reference_kind); + out.u2(reference_index); + } + } + + static class CpMethodType extends CpEntry { + static final byte TAG = 16; + short descriptor_index; + + CpMethodType() { super(TAG); } + CpMethodType(CfInputStream in) { + this(); + descriptor_index = in.u2(); + } + void write(CfOutputStream out) { + super.write(out); + out.u2(descriptor_index); + } + } + + static class CpInvokeDynamic extends CpEntry { + static final byte TAG = 18; + short bootstrap_index; + short name_and_type_index; + + CpInvokeDynamic() { super(TAG); } + CpInvokeDynamic(CfInputStream in) { + this(); + bootstrap_index = in.u2(); + name_and_type_index = in.u2(); + } + void write(CfOutputStream out) { + super.write(out); + out.u2(bootstrap_index); + out.u2(name_and_type_index); + } + } + + static class Interface { + short index; + + Interface() {} + Interface(CfInputStream in) { index = in.u2(); } + void write(CfOutputStream out) { out.u2(index); } + } + + static class FieldOrMethod { + short access_flags; + short name_index; + short descriptor_index; + ArrayList attributes; + + FieldOrMethod() { attributes = new ArrayList<>(); } + FieldOrMethod(CfInputStream in) { + access_flags = in.u2(); + name_index = in.u2(); + descriptor_index = in.u2(); + + short attrCount = in.u2(); + attributes = new ArrayList<>(); + for (int i = 0; i < attrCount; ++i) { + attributes.add(new Attribute(in)); + } + } + void write(CfOutputStream out) { + out.u2(access_flags); + out.u2(name_index); + out.u2(descriptor_index); + out.u2((short)attributes.size()); + for (Attribute attribute : attributes) { attribute.write(out); } + } + } + + static class Field extends FieldOrMethod { + Field() {} + Field(CfInputStream in) { super(in); } + } + static class Method extends FieldOrMethod { + Method() {} + Method(CfInputStream in) { super(in); } + } + + static class Attribute { + short attribute_name_index; + byte[] info; + + Attribute() { info = new byte[0]; } + Attribute(CfInputStream in) { + attribute_name_index = in.u2(); + int length = in.u4(); + info = in.array(length); + } + void write(CfOutputStream out) { + out.u2(attribute_name_index); + out.u4(info.length); + out.array(info); + } + } +} diff --git a/jdk/test/jdk/lambda/separate/ClassFilePreprocessor.java b/jdk/test/jdk/lambda/separate/ClassFilePreprocessor.java new file mode 100644 index 00000000000..e40434cc3cb --- /dev/null +++ b/jdk/test/jdk/lambda/separate/ClassFilePreprocessor.java @@ -0,0 +1,28 @@ +/* + * 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. + * + * 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 separate; + +public interface ClassFilePreprocessor { + public byte[] preprocess(String name, byte[] classfile); +}; diff --git a/jdk/test/jdk/lambda/separate/ClassToInterfaceConverter.java b/jdk/test/jdk/lambda/separate/ClassToInterfaceConverter.java new file mode 100644 index 00000000000..48c0e8dcbb3 --- /dev/null +++ b/jdk/test/jdk/lambda/separate/ClassToInterfaceConverter.java @@ -0,0 +1,92 @@ +/* + * 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. + * + * 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 separate; + +import java.io.*; +import java.util.*; + +public class ClassToInterfaceConverter implements ClassFilePreprocessor { + + private String whichClass; + + public ClassToInterfaceConverter(String className) { + this.whichClass = className; + } + + private boolean utf8Matches(ClassFile.CpEntry entry, String v) { + if (!(entry instanceof ClassFile.CpUtf8)) { + return false; + } + ClassFile.CpUtf8 utf8 = (ClassFile.CpUtf8)entry; + if (v.length() != utf8.bytes.length) { + return false; + } + for (int i = 0; i < v.length(); ++i) { + if (v.charAt(i) != utf8.bytes[i]) { + return false; + } + } + return true; + } + + private void convertToInterface(ClassFile cf) { + cf.access_flags = 0x0601; // ACC_INTERFACE | ACC_ABSTRACT | ACC_PUBLIC + ArrayList new_methods = new ArrayList<>(); + // Find method and delete it + for (int i = 0; i < cf.methods.size(); ++i) { + ClassFile.Method method = cf.methods.get(i); + ClassFile.CpEntry name = cf.constant_pool.get(method.name_index); + if (!utf8Matches(name, "")) { + new_methods.add(method); + } + } + cf.methods = new_methods; + } + + public byte[] preprocess(String classname, byte[] bytes) { + ClassFile cf = new ClassFile(bytes); + + ClassFile.CpEntry entry = cf.constant_pool.get(cf.this_class); + ClassFile.CpEntry name = cf.constant_pool.get( + ((ClassFile.CpClass)entry).name_index); + if (utf8Matches(name, whichClass)) { + convertToInterface(cf); + return cf.toByteArray(); + } else { + return bytes; // unmodified + } + } + +/* + public static void main(String argv[]) throws Exception { + File input = new File(argv[0]); + byte[] buffer = new byte[(int)input.length()]; + new FileInputStream(input).read(buffer); + + ClassFilePreprocessor cfp = new ClassToInterfaceConverter("Hello"); + byte[] cf = cfp.preprocess(argv[0], buffer); + new FileOutputStream(argv[0] + ".mod").write(cf); + } +*/ +} diff --git a/jdk/test/jdk/lambda/separate/Compiler.java b/jdk/test/jdk/lambda/separate/Compiler.java new file mode 100644 index 00000000000..9ba81d65890 --- /dev/null +++ b/jdk/test/jdk/lambda/separate/Compiler.java @@ -0,0 +1,257 @@ +/* + * 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. + * + * 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 separate; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.ConcurrentHashMap; +import java.io.*; +import java.net.URI; +import javax.tools.*; + +import com.sun.source.util.JavacTask; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; + +import static separate.SourceModel.Type; +import static separate.SourceModel.Class; +import static separate.SourceModel.Extends; +import static separate.SourceModel.SourceProcessor; + +public class Compiler { + + public enum Flags { + VERBOSE, // Prints out files as they are compiled + USECACHE // Keeps results around for reuse. Only use this is + // you're sure that each compilation name maps to the + // same source code + }; + + private static final AtomicInteger counter = new AtomicInteger(); + private static final String targetDir = + System.getProperty("lambda.separate.targetDirectory", + System.getProperty("java.io.tmpdir") + File.separator + "gen-separate"); + private static final File root = new File(targetDir); + private static ConcurrentHashMap cache = + new ConcurrentHashMap<>(); + + Set flags; + + private JavaCompiler systemJavaCompiler; + private StandardJavaFileManager fm; + private List tempDirs; + private List postprocessors; + + private static class SourceFile extends SimpleJavaFileObject { + private final String content; + + public SourceFile(String name, String content) { + super(URI.create("myfo:/" + name + ".java"), Kind.SOURCE); + this.content = content; + } + + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return toString(); + } + + public String toString() { return this.content; } + } + + public Compiler(Flags ... flags) { + setFlags(flags); + this.tempDirs = new ArrayList<>(); + this.postprocessors = new ArrayList<>(); + this.systemJavaCompiler = ToolProvider.getSystemJavaCompiler(); + this.fm = systemJavaCompiler.getStandardFileManager(null, null, null); + } + + public void setFlags(Flags ... flags) { + this.flags = new HashSet(Arrays.asList(flags)); + } + + public void addPostprocessor(ClassFilePreprocessor cfp) { + this.postprocessors.add(cfp); + } + + /** + * Compile hierarchies starting with each of the 'types' and return + * a ClassLoader that can be used to load the compiled classes. + */ + public ClassLoader compile(Type ... types) { + ClassFilePreprocessor[] cfps = this.postprocessors.toArray( + new ClassFilePreprocessor[0]); + + DirectedClassLoader dcl = new DirectedClassLoader(cfps); + + for (Type t : types) { + for (Map.Entry each : compileHierarchy(t).entrySet()) { + dcl.setLocationFor(each.getKey(), each.getValue()); + } + } + return dcl; + } + + /** + * Compiles and loads a hierarchy, starting at 'type' + */ + public java.lang.Class compileAndLoad(Type type) + throws ClassNotFoundException { + + ClassLoader loader = compile(type); + return java.lang.Class.forName(type.getName(), false, loader); + } + + /** + * Compiles a hierarchy, starting at 'type' and return a mapping of the + * name to the location where the classfile for that type resides. + */ + private Map compileHierarchy(Type type) { + HashMap outputDirs = new HashMap<>(); + + File outDir = compileOne(type); + outputDirs.put(type.getName(), outDir); + + Class superClass = type.getSuperclass(); + if (superClass != null) { + for( Map.Entry each : compileHierarchy(superClass).entrySet()) { + outputDirs.put(each.getKey(), each.getValue()); + } + } + for (Extends ext : type.getSupertypes()) { + Type iface = ext.getType(); + for( Map.Entry each : compileHierarchy(iface).entrySet()) { + outputDirs.put(each.getKey(), each.getValue()); + } + } + + return outputDirs; + } + + private File compileOne(Type type) { + if (this.flags.contains(Flags.USECACHE)) { + File dir = cache.get(type.getName()); + if (dir != null) { + return dir; + } + } + List files = new ArrayList<>(); + SourceProcessor accum = (name, src) -> files.add(new SourceFile(name, src)); + + for (Type dep : type.typeDependencies()) { + dep.generateAsDependency(accum, type.methodDependencies()); + } + + type.generate(accum); + + JavacTask ct = (JavacTask)this.systemJavaCompiler.getTask( + null, this.fm, null, null, null, files); + File destDir = null; + do { + int value = counter.incrementAndGet(); + destDir = new File(root, Integer.toString(value)); + } while (destDir.exists()); + + if (this.flags.contains(Flags.VERBOSE)) { + System.out.println("Compilation unit for " + type.getName() + + " : compiled into " + destDir); + for (JavaFileObject jfo : files) { + System.out.println(jfo.toString()); + } + } + + try { + destDir.mkdirs(); + this.fm.setLocation( + StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir)); + } catch (IOException e) { + throw new RuntimeException( + "IOException encountered during compilation"); + } + Boolean result = ct.call(); + if (result == Boolean.FALSE) { + throw new RuntimeException( + "Compilation failure in " + type.getName() + " unit"); + } + if (this.flags.contains(Flags.USECACHE)) { + File existing = cache.putIfAbsent(type.getName(), destDir); + if (existing != null) { + deleteDir(destDir); + return existing; + } + } else { + this.tempDirs.add(destDir); + } + return destDir; + } + + private static void deleteDir(File dir) { + if(!dir.exists()) { + return; + } + try { + Files.walkFileTree(dir.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.deleteIfExists(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException e) + throws IOException { + if (e == null) { + Files.deleteIfExists(dir); + return FileVisitResult.CONTINUE; + } else { + // directory iteration failed + throw e; + } + } + }); + } catch (IOException failed) { + throw new RuntimeException(failed); + } + } + + public void cleanup() { + if (!this.flags.contains(Flags.USECACHE)) { + tempDirs.forEach(dir -> { deleteDir(dir); }); + tempDirs.clear(); + } + } + + // Removes all of the elements in the cache and deletes the associated + // output directories. This may not actually empty the cache if there + // are concurrent users of it. + public static void purgeCache() { + for (Map.Entry entry : cache.entrySet()) { + cache.remove(entry.getKey()); + deleteDir(entry.getValue()); + } + } +} diff --git a/jdk/test/jdk/lambda/separate/DirectedClassLoader.java b/jdk/test/jdk/lambda/separate/DirectedClassLoader.java new file mode 100644 index 00000000000..6da38668378 --- /dev/null +++ b/jdk/test/jdk/lambda/separate/DirectedClassLoader.java @@ -0,0 +1,99 @@ +/* + * 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. + * + * 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 separate; + +import java.util.HashMap; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +class DirectedClassLoader extends ClassLoader { + + private HashMap loadLocations; + private File defaultLocation; + private ClassFilePreprocessor[] preprocessors; + + public DirectedClassLoader( + HashMap locations, File fallback, + ClassFilePreprocessor ... preprocessors) { + loadLocations = new HashMap<>(locations); + defaultLocation = fallback; + this.preprocessors = preprocessors; + } + + public DirectedClassLoader( + File fallback, ClassFilePreprocessor ... preprocessors) { + loadLocations = new HashMap<>(); + defaultLocation = fallback; + this.preprocessors = preprocessors; + } + + public DirectedClassLoader(ClassFilePreprocessor ... preprocessors) { + this((File)null, preprocessors); + } + + public void setDefaultLocation(File dir) { this.defaultLocation = dir; } + public void setLocationFor(String name, File dir) { + loadLocations.put(name, dir); + } + + @Override + protected Class findClass(String name) { + String path = name.replace(".", File.separator) + ".class"; + + File location = loadLocations.get(name); + if (location == null || !(new File(location, path)).exists()) { + File def = new File(defaultLocation, path); + if (def.exists()) { + return defineFrom(name, new File(location, path)); + } + } else { + return defineFrom(name, new File(location, path)); + } + return null; + } + + private Class defineFrom(String name, File file) { + FileInputStream fis = null; + try { + try { + fis = new FileInputStream(file); + byte[] bytes = new byte[fis.available()]; + int read = fis.read(bytes); + if (read != bytes.length) { + return null; + } + if (preprocessors != null) { + for (ClassFilePreprocessor cfp : preprocessors) { + bytes = cfp.preprocess(name, bytes); + } + } + return defineClass(name, bytes, 0, bytes.length); + } finally { + fis.close(); + } + } catch (IOException e) {} + return null; + } +} diff --git a/jdk/test/jdk/lambda/separate/SourceModel.java b/jdk/test/jdk/lambda/separate/SourceModel.java new file mode 100644 index 00000000000..6cef02fb170 --- /dev/null +++ b/jdk/test/jdk/lambda/separate/SourceModel.java @@ -0,0 +1,560 @@ +/* + * 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. + * + * 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 separate; + +import java.util.*; +import java.io.StringWriter; +import java.io.PrintWriter; + +public class SourceModel { + + public static final String stdMethodName = "m"; + + public static interface SourceProcessor { + // Called with a generated source file + void process(String name, String content); + } + + public static abstract class Element { + + protected abstract void generate(PrintWriter pw); + + public String toString() { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + generate(pw); + return sw.toString(); + } + }; + + public static class AccessFlag extends Element { + private String flag; + + public AccessFlag(String name) { flag = name; } + + protected void generate(PrintWriter pw) { + pw.print(flag); + } + + public String toString() { return flag; } + + public static final AccessFlag PUBLIC = new AccessFlag("public"); + public static final AccessFlag PRIVATE = new AccessFlag("private"); + public static final AccessFlag PROTECTED = new AccessFlag("protected"); + public static final AccessFlag STATIC = new AccessFlag("static"); + public static final AccessFlag FINAL = new AccessFlag("final"); + public static final AccessFlag SYNCHRONIZED = new AccessFlag("synchronized"); + public static final AccessFlag VOLATILE = new AccessFlag("volatile"); + public static final AccessFlag NATIVE = new AccessFlag("native"); + public static final AccessFlag ABSTRACT = new AccessFlag("abstract"); + public static final AccessFlag STRICTFP = new AccessFlag("strictfp"); + public static final AccessFlag DEFAULT = new AccessFlag("default"); + } + + public static class TypeParameter extends Element { + private String parameter; + + public TypeParameter(String str) { + this.parameter = str; + } + + protected void generate(PrintWriter pw) { + pw.print(parameter); + } + } + + public static class TypeArgument extends Element { + private String argument; + + public TypeArgument(String str) { + this.argument = str; + } + + protected void generate(PrintWriter pw) { + pw.print(argument); + } + } + + public static class MethodParameter extends Element { + private String type; + private String name; + + public MethodParameter(String type, String name) { + this.type = type; + this.name = name; + } + + protected void generate(PrintWriter pw) { + pw.printf("%s %s", this.type, this.name); + } + + public String toString() { return type + " " + name; } + } + + public static abstract class Type extends Element { + private String name; + private List accessFlags; + private List parameters; + private List supertypes; + private List methods; + + // methods from superclasses that are required for compilation + // (and thus will be present in stubs) + private Set methodDependencies; + private List typeDependencies; + + protected Type(String name, + List flags, List params, + List ifaces, List methods) { + this.name = name; + this.accessFlags = flags == null ? new ArrayList<>() : flags; + this.parameters = params == null ? new ArrayList<>() : params; + this.supertypes = ifaces == null ? new ArrayList<>() : ifaces; + this.methods = methods == null ? new ArrayList<>() : methods; + this.methodDependencies = new HashSet<>(); + this.typeDependencies = new ArrayList<>(); + } + + public String getName() { return this.name; } + public List getAccessFlags() { return this.accessFlags; } + public List getParameters() { return this.parameters; } + public List getSupertypes() { return this.supertypes; } + public List getMethods() { return this.methods; } + public Set methodDependencies() { + return this.methodDependencies; + } + + public Class getSuperclass() { return null; } + protected abstract void setSuperClass(Extends supertype); + + public void addSuperType(Extends sup) { + assert sup.getType() instanceof Interface : "Must be an interface"; + this.supertypes.add(sup); + } + public void addSuperType(Interface iface) { + this.supertypes.add(new Extends(iface)); + } + + public void addMethod(Method m) { + this.methods.add(m); + } + + public void addAccessFlag(AccessFlag f) { + this.accessFlags.add(f); + } + + // Convenience method for creation. Parameters are interpreted + // according to their type. Class (or Extends with a Class type) is + // considered a superclass (only one allowed). TypeParameters are + // generic parameter names. Interface (or Extends with an Interface + // type) is an implemented supertype. Methods are methods (duh!). + protected void addComponent(Element p) { + if (p instanceof Class) { + setSuperClass(new Extends((Class)p)); + } else if (p instanceof Extends) { + Extends ext = (Extends)p; + if (ext.supertype instanceof Class) { + setSuperClass(ext); + } else if (ext.supertype instanceof Interface) { + addSuperType(ext); + } else { + assert false : "What is this thing?"; + } + } else if (p instanceof Interface) { + addSuperType((Interface)p); + } else if (p instanceof TypeParameter) { + this.parameters.add((TypeParameter)p); + } else if (p instanceof Method) { + addMethod((Method)p); + } else if (p instanceof AccessFlag) { + addAccessFlag((AccessFlag)p); + } else { + assert false : "What is this thing?"; + } + } + + // Find and return the first method that has name 'name' + public Method findMethod(String name) { + for (Method m : methods) { + if (m.name.equals(name)) { + return m; + } + } + return null; + } + + public void addCompilationDependency(Type t) { + typeDependencies.add(t); + } + + public void addCompilationDependency(Method m) { + methodDependencies.add(m); + } + + // Convenience method for creating an Extends object using this + // class and specified type arguments. + public Extends with(String ... args) { + return new Extends(this, args); + } + + public abstract void generate(SourceProcessor sp); + public abstract void generateAsDependency( + SourceProcessor sp, Set neededMethods); + + protected void generateName(PrintWriter pw) { + pw.print(this.name); + StringJoiner joiner = new StringJoiner(",", "<", ">").setEmptyValue(""); + this.parameters.stream().map(Element::toString).forEach(joiner::add); + pw.print(joiner.toString()); + pw.print(" "); + } + + protected void generateBody(PrintWriter pw, String superSpec) { + StringJoiner joiner = new StringJoiner(",", superSpec + " ", " ") + .setEmptyValue(""); + supertypes.stream().map(Element::toString).forEach(joiner::add); + pw.print(joiner.toString()); + pw.println("{ "); + joiner = new StringJoiner("\n ", "\n ", "\n").setEmptyValue(""); + methods.stream().map(Element::toString).forEach(joiner::add); + pw.print(joiner.toString()); + pw.println("}"); + } + + protected void generateAccessFlags(PrintWriter pw) { + StringJoiner joiner = new StringJoiner(" ", "", " "); + accessFlags.stream().map(AccessFlag::toString).forEach(joiner::add); + pw.print(joiner.toString()); + } + + protected void generateBodyAsDependency( + PrintWriter pw, Set neededMethods) { + pw.println(" {"); + for (Method m : this.methods) { + if (neededMethods.contains(m)) { + pw.print(" "); + m.generate(pw); + pw.println(); + } + } + pw.println("}"); + } + + public Collection typeDependencies() { + HashMap dependencies = new HashMap<>(); + Type superclass = getSuperclass(); + if (superclass != null) { + dependencies.put(superclass.getName(), superclass); + } + for (Extends e : getSupertypes()) + dependencies.put(e.getType().getName(), e.getType()); + // Do these last so that they override + for (Type t : this.typeDependencies) + dependencies.put(t.getName(), t); + return dependencies.values(); + } + } + + public static class Class extends Type { + private Extends superClass; + + public Class(String name, List flags, + List params, Extends sprClass, + List interfaces, List methods) { + super(name, flags, params, interfaces, methods); + this.superClass = sprClass; + addAccessFlag(AccessFlag.PUBLIC); // should remove this + } + + public Class(String name, Element ... components) { + super(name, null, null, null, null); + this.superClass = null; + + for (Element p : components) { + addComponent(p); + } + addAccessFlag(AccessFlag.PUBLIC); // should remove this + } + + public boolean isAbstract() { + for (AccessFlag flag : getAccessFlags()) { + if (flag == AccessFlag.ABSTRACT) { + return true; + } + } + return false; + } + + @Override + public void setSuperClass(Extends ext) { + assert this.superClass == null : "Multiple superclasses defined"; + assert ext.getType() instanceof Class : "Must be a class"; + this.superClass = ext; + } + + public void setSuperClass(Class c) { + setSuperClass(new Extends(c)); + } + + @Override + public Class getSuperclass() { + return superClass == null ? null : (Class)superClass.supertype; + } + + public void generate(SourceProcessor processor) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + generate(pw); + processor.process(getName(), sw.toString()); + } + + public void generate(PrintWriter pw) { + generateAccessFlags(pw); + pw.print("class "); + generateName(pw); + if (superClass != null) { + pw.print("extends "); + superClass.generate(pw); + pw.print(" "); + } + generateBody(pw, "implements"); + } + + public void generateAsDependency( + SourceProcessor processor, Set neededMethods) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + generateAccessFlags(pw); + pw.print("class "); + generateName(pw); + pw.print(" "); + generateBodyAsDependency(pw, neededMethods); + + processor.process(getName(), sw.toString()); + } + } + + public static class Interface extends Type { + + public Interface(String name, + List flags, List params, + List interfaces, List methods) { + super(name, flags, params, interfaces, methods); + } + + public Interface(String name, Element ... components) { + super(name, null, null, null, null); + for (Element c : components) { + addComponent(c); + } + } + + protected void setSuperClass(Extends ext) { + assert false : "Interfaces cannot have Class supertypes"; + } + + public void generate(SourceProcessor processor) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + generate(pw); + processor.process(getName(), sw.toString()); + } + + public void generate(PrintWriter pw) { + generateAccessFlags(pw); + pw.print("interface "); + generateName(pw); + pw.print(" "); + generateBody(pw, "extends"); + } + + public void generateAsDependency( + SourceProcessor processor, Set neededMethods) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + + generateAccessFlags(pw); + pw.print("interface "); + generateName(pw); + pw.print(" "); + generateBodyAsDependency(pw, neededMethods); + + processor.process(getName(), sw.toString()); + } + } + + /** + * Represents a type extension that might contain type arguments + */ + public static class Extends extends Element { + private final Type supertype; + private final List arguments; + + public Type getType() { return supertype; } + public List getArguments() { + return arguments; + } + + public Extends(Type supertype, String ... args) { + assert supertype != null : "Null supertype"; + this.supertype = supertype; + this.arguments = new ArrayList<>(); + for (String arg : args) { + this.arguments.add(new TypeArgument(arg)); + } + } + + public void generate(PrintWriter pw) { + StringJoiner joiner = new StringJoiner(",", "<", ">").setEmptyValue(""); + getArguments().stream().map(Element::toString).forEach(joiner::add); + pw.print(supertype.getName()); + pw.print(joiner.toString()); + } + } + + public static abstract class Method extends Element { + private String name; + private String returnType; + private List accessFlags; + private List parameters; + private boolean emitSuppressWarnings; + + protected Method(String ret, String name, Element ... params) { + this.name = name; + this.returnType = ret; + this.accessFlags = new ArrayList<>(); + this.parameters = new ArrayList<>(); + this.emitSuppressWarnings = false; + + Arrays.asList(params).stream() + .filter(x -> x instanceof MethodParameter) + .map(x -> (MethodParameter)x) + .forEach(this.parameters::add); + Arrays.asList(params).stream() + .filter(x -> x instanceof AccessFlag) + .map(x -> (AccessFlag)x) + .forEach(this.accessFlags::add); + assert accessFlags.size() + parameters.size() == params.length : + "Non method parameters or access flags in constructor"; + } + + public String getName() { return this.name; } + public String getReturnType() { return this.returnType; } + public List getParameters() { + return this.parameters; + } + public List getAccessFlags() { + return this.accessFlags; + } + public Element[] getElements() { + ArrayList elements = new ArrayList<>(); + getParameters().stream().forEach(elements::add); + getAccessFlags().stream().forEach(elements::add); + return elements.toArray(new Element[elements.size()]); + } + + public void suppressWarnings() { this.emitSuppressWarnings = true; } + + public void generateWarningSuppression(PrintWriter pw) { + if (this.emitSuppressWarnings) { + pw.printf("@SuppressWarnings(\"unchecked\")\n "); + } + } + + protected void generateDecl(PrintWriter pw) { + generateWarningSuppression(pw); + StringJoiner joiner = new StringJoiner(" ", "", " "); + accessFlags.stream().map(AccessFlag::toString).forEach(joiner::add); + pw.print(joiner.toString()); + joiner = new StringJoiner(","); + pw.printf("%s %s(", returnType, name); + parameters.stream().map(MethodParameter::toString).forEach(joiner::add); + pw.print(joiner.toString()); + pw.print(")"); + } + } + + public static class AbstractMethod extends Method { + public AbstractMethod( + String ret, String name, Element ... params) { + super(ret, name, params); + this.getAccessFlags().add(AccessFlag.ABSTRACT); + } + + public void generate(PrintWriter pw) { + generateDecl(pw); + pw.print(";"); + } + + public static AbstractMethod std() { + return new AbstractMethod( + "int", SourceModel.stdMethodName, AccessFlag.PUBLIC); + } + } + + public static class ConcreteMethod extends Method { + protected String body; + + public ConcreteMethod(String ret, String name, + String body, Element ... params) { + super(ret, name, params); + this.body = body; + } + + public void generate(PrintWriter pw) { + generateDecl(pw); + pw.printf(" { %s }", this.body); + } + + public static ConcreteMethod std(String value) { + return new ConcreteMethod( + "int", SourceModel.stdMethodName, "return " + value + ";", + AccessFlag.PUBLIC); + } + } + + // When the default method flag gets moved into the traditional + // access flags location, we can remove this class completely and + // use a ConcreteMethod with an AccessFlag("default") in the constructor + public static class DefaultMethod extends Method { + protected String body; + + public DefaultMethod(String ret, String name, String body, + Element ... params) { + super(ret, name, params); + this.body = body; + this.getAccessFlags().add(AccessFlag.DEFAULT); + } + + public void generate(PrintWriter pw) { + generateDecl(pw); + pw.printf(" { %s }", this.body); + } + + public static DefaultMethod std(String value) { + return new DefaultMethod( + "int", SourceModel.stdMethodName, "return " + value + ";"); + } + } +} diff --git a/jdk/test/jdk/lambda/separate/TestHarness.java b/jdk/test/jdk/lambda/separate/TestHarness.java new file mode 100644 index 00000000000..d5ba449a3c9 --- /dev/null +++ b/jdk/test/jdk/lambda/separate/TestHarness.java @@ -0,0 +1,314 @@ +/* + * 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. + * + * 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 separate; + +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; + +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.stream.Collectors; + +import static separate.SourceModel.Class; +import static separate.SourceModel.*; +import static org.testng.Assert.*; + +public class TestHarness { + + /** + * Creates a per-thread persistent compiler object to allow as much + * sharing as possible, but still allows for parallel execution of tests. + */ + protected ThreadLocal compilerLocal = new ThreadLocal(){ + protected synchronized Compiler initialValue() { + return new Compiler(); + } + }; + + protected ThreadLocal verboseLocal = new ThreadLocal() { + protected synchronized Boolean initialValue() { + return Boolean.FALSE; + } + }; + + protected boolean verbose; + protected boolean canUseCompilerCache; + public static final String stdMethodName = SourceModel.stdMethodName; + + private TestHarness() { + } + + protected TestHarness(boolean verbose, boolean canUseCompilerCache) { + this.verbose = verbose; + this.canUseCompilerCache = canUseCompilerCache; + } + + public void setTestVerbose() { + verboseLocal.set(Boolean.TRUE); + } + + @AfterMethod + public void reset() { + if (!this.verbose) { + verboseLocal.set(Boolean.FALSE); + } + } + + public Compiler.Flags[] compilerFlags() { + HashSet flags = new HashSet<>(); + if (verboseLocal.get() == Boolean.TRUE) { + flags.add(Compiler.Flags.VERBOSE); + } + if (this.canUseCompilerCache) { + flags.add(Compiler.Flags.USECACHE); + } + return flags.toArray(new Compiler.Flags[0]); + } + + @AfterMethod + public void printError(ITestResult result) { + if (result.getStatus() == ITestResult.FAILURE) { + String clsName = result.getTestClass().getName(); + clsName = clsName.substring(clsName.lastIndexOf(".") + 1); + System.out.println("Test " + clsName + "." + + result.getName() + " FAILED"); + } + } + + private static final ConcreteMethod stdCM = ConcreteMethod.std("-1"); + private static final AbstractMethod stdAM = + new AbstractMethod("int", stdMethodName); + + /** + * Returns a class which has a static method with the same name as + * 'method', whose body creates an new instance of 'specimen' and invokes + * 'method' upon it via an invokevirtual instruction with 'args' as + * function call parameters. + * + * 'returns' is a dummy return value that need only match 'methods' + * return type (it is only used in the dummy class when compiling IV). + */ + private Class invokeVirtualHarness( + Class specimen, ConcreteMethod method, + String returns, String ... args) { + Method cm = new ConcreteMethod( + method.getReturnType(), method.getName(), + "return " + returns + ";", method.getElements()); + Class stub = new Class(specimen.getName(), cm); + + String params = + Arrays.asList(args).stream().collect(Collectors.toStringJoiner(", ")).toString(); + + ConcreteMethod sm = new ConcreteMethod( + method.getReturnType(), method.getName(), + String.format("return (new %s()).%s(%s);", + specimen.getName(), method.getName(), params), + new AccessFlag("public"), new AccessFlag("static")); + + Class iv = new Class("IV_" + specimen.getName(), sm); + + iv.addCompilationDependency(stub); + iv.addCompilationDependency(cm); + + return iv; + } + + /** + * Returns a class which has a static method with the same name as + * 'method', whose body creates an new instance of 'specimen', casts it + * to 'iface' (including the type parameters) and invokes + * 'method' upon it via an invokeinterface instruction with 'args' as + * function call parameters. + */ + private Class invokeInterfaceHarness(Class specimen, Extends iface, + AbstractMethod method, String ... args) { + Interface istub = new Interface( + iface.getType().getName(), iface.getType().getAccessFlags(), + iface.getType().getParameters(), + null, Arrays.asList((Method)method)); + Class cstub = new Class(specimen.getName()); + + String params = Arrays.asList(args).stream().collect(Collectors.toStringJoiner(", ")).toString(); + + ConcreteMethod sm = new ConcreteMethod( + "int", SourceModel.stdMethodName, + String.format("return ((%s)(new %s())).%s(%s);", iface.toString(), + specimen.getName(), method.getName(), params), + new AccessFlag("public"), new AccessFlag("static")); + sm.suppressWarnings(); + + Class ii = new Class("II_" + specimen.getName() + "_" + + iface.getType().getName(), sm); + ii.addCompilationDependency(istub); + ii.addCompilationDependency(cstub); + ii.addCompilationDependency(method); + return ii; + } + + + /** + * Uses 'loader' to load class 'clzz', and calls the static method + * 'method'. If the return value does not equal 'value' (or if an + * exception is thrown), then a test failure is indicated. + * + * If 'value' is null, then no equality check is performed -- the assertion + * fails only if an exception is thrown. + */ + protected void assertStaticCallEquals( + ClassLoader loader, Class clzz, String method, Object value) { + java.lang.Class cls = null; + try { + cls = java.lang.Class.forName(clzz.getName(), true, loader); + } catch (ClassNotFoundException e) {} + assertNotNull(cls); + + java.lang.reflect.Method m = null; + try { + m = cls.getMethod(method); + } catch (NoSuchMethodException e) {} + assertNotNull(m); + + try { + Object res = m.invoke(null); + assertNotNull(res); + if (value != null) { + assertEquals(res, value); + } + } catch (InvocationTargetException | IllegalAccessException e) { + fail("Unexpected exception thrown: " + e.getCause()); + } + } + + /** + * Creates a class which calls target::method(args) via invokevirtual, + * compiles and loads both the new class and 'target', and then invokes + * the method. If the returned value does not match 'value' then a + * test failure is indicated. + */ + public void assertInvokeVirtualEquals( + Object value, Class target, ConcreteMethod method, + String returns, String ... args) { + + Compiler compiler = compilerLocal.get(); + compiler.setFlags(compilerFlags()); + + Class iv = invokeVirtualHarness(target, method, returns, args); + ClassLoader loader = compiler.compile(iv, target); + + assertStaticCallEquals(loader, iv, method.getName(), value); + compiler.cleanup(); + } + + /** + * Convenience method for above, which assumes stdMethodName, + * a return type of 'int', and no arguments. + */ + public void assertInvokeVirtualEquals(int value, Class target) { + assertInvokeVirtualEquals( + new Integer(value), target, stdCM, "-1"); + } + + /** + * Creates a class which calls target::method(args) via invokeinterface + * through 'iface', compiles and loads both it and 'target', and + * then invokes the method. If the returned value does not match + * 'value' then a test failure is indicated. + */ + public void assertInvokeInterfaceEquals(Object value, Class target, + Extends iface, AbstractMethod method, String ... args) { + + Compiler compiler = compilerLocal.get(); + compiler.setFlags(compilerFlags()); + + Class ii = invokeInterfaceHarness(target, iface, method, args); + ClassLoader loader = compiler.compile(ii, target); + + assertStaticCallEquals(loader, ii, method.getName(), value); + compiler.cleanup(); + } + + /** + * Convenience method for above, which assumes stdMethodName, + * a return type of 'int', and no arguments. + */ + public void assertInvokeInterfaceEquals( + int value, Class target, Interface iface) { + + Compiler compiler = compilerLocal.get(); + compiler.setFlags(compilerFlags()); + + assertInvokeInterfaceEquals( + new Integer(value), target, new Extends(iface), stdAM); + + compiler.cleanup(); + } + + /** + * Creates a class which calls target::method(args) via invokevirtual, + * compiles and loads both the new class and 'target', and then invokes + * the method. If an exception of type 'exceptionType' is not thrown, + * then a test failure is indicated. + */ + public void assertThrows(java.lang.Class exceptionType, Class target, + ConcreteMethod method, String returns, String ... args) { + + Compiler compiler = compilerLocal.get(); + compiler.setFlags(compilerFlags()); + + Class iv = invokeVirtualHarness(target, method, returns, args); + ClassLoader loader = compiler.compile(iv, target); + + java.lang.Class cls = null; + try { + cls = java.lang.Class.forName(iv.getName(), true, loader); + } catch (ClassNotFoundException e) {} + assertNotNull(cls); + + java.lang.reflect.Method m = null; + try { + m = cls.getMethod(method.getName()); + } catch (NoSuchMethodException e) {} + assertNotNull(m); + + try { + m.invoke(null); + fail("Exception should have been thrown"); + } catch (InvocationTargetException | IllegalAccessException e) { + if (verboseLocal.get() == Boolean.TRUE) { + System.out.println(e.getCause()); + } + assertEquals(e.getCause().getClass(), exceptionType); + } + compiler.cleanup(); + } + + /** + * Convenience method for above, which assumes stdMethodName, + * a return type of 'int', and no arguments. + */ + public void assertThrows(java.lang.Class exceptionType, Class target) { + assertThrows(exceptionType, target, stdCM, "-1"); + } +} diff --git a/jdk/test/jdk/lambda/shapegen/ClassCase.java b/jdk/test/jdk/lambda/shapegen/ClassCase.java new file mode 100644 index 00000000000..7ad096abce9 --- /dev/null +++ b/jdk/test/jdk/lambda/shapegen/ClassCase.java @@ -0,0 +1,310 @@ +/* + * 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. + * + * 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 shapegen; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * + * @author Robert Field + */ +public class ClassCase { + + public enum Kind { + IVAC (true, "v"), + IPRESENT (true, "p"), + IDEFAULT (true, "d"), + CNONE (false, "n"), + CABSTRACT (false, "a"), + CCONCRETE (false, "c"); + + private final String prefix; + public final boolean isInterface; + + Kind(boolean isInterface, String prefix) { + this.isInterface = isInterface; + this.prefix = prefix; + } + + public String getPrefix() { return prefix; } + } + + public final Kind kind; + private final ClassCase superclass; + private final List supertypes; + + private String name; + private boolean _OK; + private boolean _HasClassMethod; + private Set _mprov; + private boolean _IsConcrete; + private boolean _HasDefault; + private ClassCase _mres; + private ClassCase _mdefend; + + private Set executed = new HashSet(); + + public ClassCase(Kind kind, ClassCase superclass, List interfaces) { + this.kind = kind; + this.superclass = superclass; + + // Set supertypes from superclass (if any) and interfaces + List lc; + if (superclass == null) { + lc = interfaces; + } else { + lc = new ArrayList<>(); + lc.add(superclass); + lc.addAll(interfaces); + } + this.supertypes = lc; + } + + public final boolean isInterface() { return kind.isInterface; } + public final boolean isClass() { return !kind.isInterface; } + + public Set get_mprov() { + exec(RuleGroup.PROVENENCE); + return _mprov; + } + + public void set_mprov(ClassCase cc) { + Set s = new HashSet<>(); + s.add(cc); + _mprov = s; + } + + public void set_mprov(Set s) { + _mprov = s; + } + + public ClassCase get_mres() { + exec(RuleGroup.RESOLUTION); + return _mres; + } + + public void set_mres(ClassCase cc) { + _mres = cc; + } + + public ClassCase get_mdefend() { + exec(RuleGroup.DEFENDER); + return _mdefend; + } + + public void set_mdefend(ClassCase cc) { + _mdefend = cc; + } + + public boolean get_HasClassMethod() { + exec(RuleGroup.PROVENENCE); + return _HasClassMethod; + } + + public void set_HasClassMethod(boolean bool) { + _HasClassMethod = bool; + } + + public boolean get_HasDefault() { + exec(RuleGroup.MARKER); + return _HasDefault; + } + + public void set_HasDefault(boolean bool) { + _HasDefault = bool; + } + + public boolean get_IsConcrete() { + exec(RuleGroup.MARKER); + return _IsConcrete; + } + + public void set_IsConcrete(boolean bool) { + _IsConcrete = bool; + } + + public boolean get_OK() { + exec(RuleGroup.CHECKING); + return _OK; + } + + public void set_OK(boolean bool) { + _OK = bool; + } + + public boolean isMethodDefined() { + for (ClassCase cc : supertypes) { + if (cc.isMethodDefined()) { + return true; + } + } + switch (kind) { + case CCONCRETE: + case CABSTRACT: + case IPRESENT: + case IDEFAULT: + return true; + default: + return false; + } + } + + public boolean isAbstract() { + return isMethodDefined() && (get_mres()==null); + } + + public boolean hasSuperclass() { + return superclass != null; + } + + public ClassCase getSuperclass() { + return superclass; + } + + public List getSupertypes() { + return supertypes; + } + + public List getInterfaces() { + if (superclass != null) { + if (supertypes.get(0) != superclass) { + throw new AssertionError("superclass missing from supertypes"); + } + return supertypes.subList(1, supertypes.size()); + } else { + return supertypes; + } + } + + public boolean isSubtypeOf(ClassCase cc) { + // S-Refl + if (cc.equals(this)) { + return true; + } + + // S-Def + for (ClassCase sp : getSupertypes()) { + if (cc.equals(sp)) { + return true; + } + } + + // _S-Trans + for (ClassCase sp : getSupertypes()) { + if (sp.isSubtypeOf(cc)) { + return true; + } + } + + return false; + } + + public void init(Map namingContext) { + if (name != null) { + return; // Already inited + } + + for (ClassCase sup : supertypes) { + sup.init(namingContext); + } + + // Build name + StringBuilder sb = new StringBuilder(); + if (!supertypes.isEmpty()) { + sb.append(isInterface() ? "I" : "C"); + for (ClassCase cc : supertypes) { + sb.append(cc.getName()); + } + sb.append(kind.isInterface ? "i" : "c"); + } + sb.append(kind.prefix); + String pname = sb.toString(); + Integer icnt = namingContext.get(pname); + int cnt = icnt == null ? 0 : icnt; + ++cnt; + namingContext.put(pname, cnt); + if (cnt > 1) { + sb.append(cnt); + } + this.name = sb.toString(); + } + + public boolean isa(Kind... kinds) { + for (Kind k : kinds) { + if (kind == k) { + return true; + } + } + return false; + } + + private void exec(RuleGroup rg ) { + if (!executed.contains(rg)) { + rg.exec(this); + executed.add(rg); + } + } + + public void collectClasses(Set seen) { + seen.add(this); + for (ClassCase cc : supertypes) { + cc.collectClasses(seen); + } + } + + public String getID() { + if (name == null) { + throw new Error("Access to uninitialized ClassCase"); + } else { + return name; + } + } + + public final String getName() { + if (name == null) { + return "ClassCase uninited@" + hashCode(); + } else { + return name; + } + } + + @Override + public boolean equals(Object obj) { + return obj instanceof ClassCase && getID().equals(((ClassCase)obj).getID()); + } + + @Override + public int hashCode() { + return getID().hashCode(); + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/jdk/test/jdk/lambda/shapegen/Hierarchy.java b/jdk/test/jdk/lambda/shapegen/Hierarchy.java new file mode 100644 index 00000000000..2315a9ea229 --- /dev/null +++ b/jdk/test/jdk/lambda/shapegen/Hierarchy.java @@ -0,0 +1,207 @@ +/* + * 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. + * + * 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 shapegen; + +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static shapegen.ClassCase.Kind.*; + +/** + * + * @author Robert Field + */ +public class Hierarchy { + + public final ClassCase root; + public final Set all; + + public Hierarchy(ClassCase root) { + this.root = root; + root.init(new HashMap()); + Set allClasses = new HashSet<>(); + root.collectClasses(allClasses); + this.all = allClasses; + } + + public boolean anyDefaults() { + for (ClassCase cc : all) { + if (cc.kind == IDEFAULT) { + return true; + } + } + return false; + } + + public boolean get_OK() { + return root.get_OK(); + } + + public String testName() { + return root + "Test"; + } + + private static void genInterfaceList(StringBuilder buf, String prefix, List interfaces) { + if (!interfaces.isEmpty()) { + buf.append(" "); + buf.append(prefix); + buf.append(" "); + buf.append(interfaces.get(0)); + for (int i = 1; i < interfaces.size(); ++i) { + buf.append(", " + interfaces.get(i)); + } + } + } + + public static void genClassDef(StringBuilder buf, ClassCase cc, String implClass, List defaultRef) { + if (cc.isInterface()) { + buf.append("interface "); + buf.append(cc.getName() + " "); + genInterfaceList(buf, "extends", cc.getInterfaces()); + buf.append(" {\n"); + + switch (cc.kind) { + case IDEFAULT: + buf.append(" default String m() { return \"\"; }\n"); + defaultRef.add(cc); + break; + case IPRESENT: + buf.append(" String m();\n"); + break; + case IVAC: + break; + default: + throw new AssertionError("Unexpected kind"); + } + buf.append("}\n\n"); + } else { + buf.append((cc.isAbstract()? "abstract " : "")); + buf.append(" class " + cc.getName()); + if (cc.getSuperclass() != null) { + buf.append(" extends " + cc.getSuperclass()); + } + + genInterfaceList(buf, "implements", cc.getInterfaces()); + buf.append(" {\n"); + + switch (cc.kind) { + case CCONCRETE: + buf.append(" public String m() { return \"\"; }\n"); + break; + case CABSTRACT: + buf.append(" public abstract String m();\n"); + break; + case CNONE: + break; + default: + throw new AssertionError("Unexpected kind"); + } + buf.append("}\n\n"); + } + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Hierarchy && root.getID().equals(((Hierarchy)obj).root.getID()); + } + + @Override + public int hashCode() { + return root.getID().hashCode(); + } + + @Override + public String toString() { + return root.getName(); + } + + private static String classNames[] = { + "C", "D", "E", "F", "G", "H", "S", "T", "U", "V" + }; + + private static String interfaceNames[] = { + "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R" + }; + + private static int CLASS_INDEX = 0; + private static int INTERFACE_INDEX = 1; + private static int NUM_INDICIES = 2; + + public List getDescription() { + Map nameMap = new HashMap<>(); + assignNames(root, new int[NUM_INDICIES], nameMap); + + ArrayList res = new ArrayList<>(); + if (root.getSupertypes().size() == 0) { + res.add(nameMap.get(root) + root.kind.getPrefix() + "()"); + } else { + genCaseDescription(root, res, new HashSet(), nameMap); + } + return res; + } + + private static void assignNames( + ClassCase cc, int indices[], Map names) { + String name = names.get(cc); + if (name == null) { + if (cc.isInterface()) { + names.put(cc, interfaceNames[indices[INTERFACE_INDEX]++]); + } else { + names.put(cc, classNames[indices[CLASS_INDEX]++]); + } + for (int i = 0; i < cc.getSupertypes().size(); ++i) { + assignNames(cc.getSupertypes().get(i), indices, names); + } + } + } + + private static void genCaseDescription( + ClassCase cc, List res, Set alreadyDone, + Map nameMap) { + if (!alreadyDone.contains(cc)) { + if (cc.getSupertypes().size() > 0) { + StringBuilder sb = new StringBuilder(); + sb.append(nameMap.get(cc)); + sb.append(cc.kind.getPrefix()); + sb.append("("); + for (int i = 0; i < cc.getSupertypes().size(); ++i) { + ClassCase supertype = cc.getSupertypes().get(i); + if (i != 0) { + sb.append(","); + } + genCaseDescription(supertype, res, alreadyDone, nameMap); + sb.append(nameMap.get(supertype)); + sb.append(supertype.kind.getPrefix()); + } + sb.append(")"); + res.add(sb.toString()); + } + } + alreadyDone.add(cc); + } +} diff --git a/jdk/test/jdk/lambda/shapegen/HierarchyGenerator.java b/jdk/test/jdk/lambda/shapegen/HierarchyGenerator.java new file mode 100644 index 00000000000..4bf5af9b8d9 --- /dev/null +++ b/jdk/test/jdk/lambda/shapegen/HierarchyGenerator.java @@ -0,0 +1,190 @@ +/* + * 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. + * + * 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 shapegen; + +import shapegen.ClassCase.Kind; + +import java.util.Collection; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; +import java.util.ArrayList; +import java.util.List; + +import static shapegen.ClassCase.Kind.*; + +import static java.lang.Math.pow; + +/** + * + * @author Robert Field + */ +public final class HierarchyGenerator { + + private int okcnt = 0; + private int errcnt = 0; + private Set uniqueOK = new HashSet<>(); + private Set uniqueErr = new HashSet<>(); + + /** + * @param args the command line arguments + */ + public HierarchyGenerator() { + organize("exhaustive interface", iExhaustive(2)); + organize("exhaustive class", cExhaustive()); + organize("shapes interface", iShapes()); + organize("shapes class/interface", ciShapes()); + + System.out.printf("\nExpect OK: %d -- unique %d", okcnt, uniqueOK.size()); + System.out.printf("\nExpect Error: %d -- unique %d\n", errcnt, uniqueErr.size()); + } + + public Collection getOK() { + return uniqueOK; + } + + public Collection getErr() { + return uniqueErr; + } + + private void organize(String tname, List totest) { + System.out.printf("\nGenerating %s....\n", tname); + int nodefault = 0; + List ok = new ArrayList<>(); + List err = new ArrayList<>(); + for (Hierarchy cc : totest) { + if (cc.anyDefaults()) { + //System.out.printf(" %s\n", cc); + if (cc.get_OK()) { + ok.add(cc); + } else { + err.add(cc); + } + } else { + ++nodefault; + } + } + + errcnt += err.size(); + okcnt += ok.size(); + uniqueErr.addAll(err); + uniqueOK.addAll(ok); + + System.out.printf(" %5d No default\n %5d Error\n %5d OK\n %5d Total\n", + nodefault, err.size(), ok.size(), totest.size()); + } + + public List iExhaustive(int idepth) { + List current = new ArrayList<>(); + for (int i = 0; i < idepth; ++i) { + current = ilayer(current); + } + return wrapInClassAndHierarchy(current); + } + + private List ilayer(List srcLayer) { + List lay = new ArrayList<>(); + for (int i = (int) pow(2, srcLayer.size()) - 1; i >= 0; --i) { + List itfs = new ArrayList<>(); + for (int b = srcLayer.size() - 1; b >= 0; --b) { + if ((i & (1< cExhaustive() { + final Kind[] iKinds = new Kind[]{IDEFAULT, IVAC, IPRESENT, null}; + final Kind[] cKinds = new Kind[]{CNONE, CABSTRACT, CCONCRETE}; + List totest = new ArrayList<>(); + for (int i1 = 0; i1 < iKinds.length; ++i1) { + for (int i2 = 0; i2 < iKinds.length; ++i2) { + for (int i3 = 0; i3 < iKinds.length; ++i3) { + for (int c1 = 0; c1 < cKinds.length; ++c1) { + for (int c2 = 0; c2 < cKinds.length; ++c2) { + for (int c3 = 0; c3 < cKinds.length; ++c3) { + totest.add( new Hierarchy( + new ClassCase(cKinds[c1], + new ClassCase(cKinds[c2], + new ClassCase(cKinds[c3], + null, + iList(iKinds[i1]) + ), + iList(iKinds[i2]) + ), + iList(iKinds[i3]) + ))); + } + } + } + } + } + } + return totest; + } + + public static final List EMPTY_LIST = new ArrayList<>(); + + private List iList(Kind kind) { + if (kind == null) { + return EMPTY_LIST; + } else { + List itfs = new ArrayList<>(); + itfs.add(new ClassCase(kind, null, EMPTY_LIST)); + return itfs; + } + } + + public List ciShapes() { + return wrapInHierarchy(TTShape.allCases(true)); + } + + public List iShapes() { + return wrapInClassAndHierarchy(TTShape.allCases(false)); + } + + public List wrapInClassAndHierarchy(List ihs) { + List totest = new ArrayList<>(); + for (ClassCase cc : ihs) { + List interfaces = new ArrayList<>(); + interfaces.add(cc); + totest.add(new Hierarchy(new ClassCase(CNONE, null, interfaces))); + } + return totest; + } + + public List wrapInHierarchy(List ihs) { + List totest = new ArrayList<>(); + for (ClassCase cc : ihs) { + totest.add(new Hierarchy(cc)); + } + return totest; + } +} diff --git a/jdk/test/jdk/lambda/shapegen/Rule.java b/jdk/test/jdk/lambda/shapegen/Rule.java new file mode 100644 index 00000000000..5995ecd7122 --- /dev/null +++ b/jdk/test/jdk/lambda/shapegen/Rule.java @@ -0,0 +1,46 @@ +/* + * 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. + * + * 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 shapegen; + +/** + * + * @author Robert Field + */ +public abstract class Rule { + + public final String name; + + public Rule(String name) { + this.name = name; + } + + abstract boolean guard(ClassCase cc); + + abstract void eval(ClassCase cc); + + @Override + public String toString() { + return name; + } +} diff --git a/jdk/test/jdk/lambda/shapegen/RuleGroup.java b/jdk/test/jdk/lambda/shapegen/RuleGroup.java new file mode 100644 index 00000000000..b67ffcd863a --- /dev/null +++ b/jdk/test/jdk/lambda/shapegen/RuleGroup.java @@ -0,0 +1,204 @@ +/* + * 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. + * + * 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 shapegen; + +import java.util.HashSet; +import java.util.Set; + +import static shapegen.ClassCase.Kind.*; + +/** + * + * @author Robert Field + */ +public class RuleGroup { + + final String name; + private final Rule[] rules; + + public RuleGroup(String name, Rule[] rules) { + this.name = name; + this.rules = rules; + } + + public boolean exec(ClassCase cc) { + boolean found = false; + for (Rule rule : rules) { + if (rule.guard(cc)) { + if (found) { + throw new RuntimeException("Bad rules -- multiple matches " + toString() + " for " + cc); + } else { + rule.eval(cc); + found = true; + } + } + } + return found; + } + + @Override + public String toString() { + return name; + } + + public static RuleGroup PROVENENCE = new RuleGroup("Provenence", new Rule[] { + new Rule("P-CDeclare") { + boolean guard(ClassCase cc) { + return cc.isa(CCONCRETE, CABSTRACT); + } + + void eval(ClassCase cc) { + cc.set_mprov(cc); + cc.set_HasClassMethod(true); + } + }, + + new Rule("P-IDeclare") { + boolean guard(ClassCase cc) { + return cc.isa(IDEFAULT, IPRESENT); + } + + void eval(ClassCase cc) { + cc.set_mprov(cc); + } + }, + + new Rule("P-IntfInh") { + boolean guard(ClassCase cc) { + return cc.isa(IVAC, CNONE) && !(cc.hasSuperclass() && cc.getSuperclass().get_HasClassMethod()); + } + + void eval(ClassCase cc) { + Set _S = new HashSet<>(); + for (ClassCase t : cc.getSupertypes()) { + _S.addAll(t.get_mprov()); + } + Set tops = new HashSet<>(); + for (ClassCase _W : _S) { + for (ClassCase _V : _S) { + if (_V.equals(_W) || !(_V.isSubtypeOf(_W))) { + tops.add(_W); + } + } + } + cc.set_mprov(tops); + } + }, + + new Rule("P-ClassInh") { + boolean guard(ClassCase cc) { + return cc.isa(CNONE) && (cc.hasSuperclass() && cc.getSuperclass().get_HasClassMethod()); + } + + void eval(ClassCase cc) { + cc.set_mprov(cc.getSuperclass()); + cc.set_HasClassMethod(true); + } + }, + + }); + + public static RuleGroup MARKER = new RuleGroup("Marker", new Rule[] { + new Rule("M-Default") { + boolean guard(ClassCase cc) { + return cc.isa(IDEFAULT); + } + + void eval(ClassCase cc) { + cc.set_HasDefault(true); + } + }, + + new Rule("M-Conc") { + boolean guard(ClassCase cc) { + return cc.isa(CCONCRETE); + } + + void eval(ClassCase cc) { + cc.set_IsConcrete(true); + } + }, + + }); + + public static RuleGroup RESOLUTION = new RuleGroup("Resolution", new Rule[] { + new Rule("R-Resolve") { + boolean guard(ClassCase cc) { + if (!(cc.isClass() && cc.get_mprov().size() == 1)) { + return false; + } + ClassCase _V = cc.get_mprov().iterator().next(); + return _V.get_IsConcrete() || _V.get_HasDefault(); + } + + void eval(ClassCase cc) { + ClassCase _V = cc.get_mprov().iterator().next(); + cc.set_mres(_V); + } + }, + + }); + + public static RuleGroup DEFENDER = new RuleGroup("Defender", new Rule[] { + new Rule("D-Defend") { + boolean guard(ClassCase cc) { + ClassCase mresSuper = cc.hasSuperclass() ? cc.getSuperclass().get_mres() : null; + boolean eq = cc.get_mres() == null ? mresSuper == null : cc.get_mres().equals(mresSuper); + return cc.isa(CNONE) && !eq; + } + + void eval(ClassCase cc) { + cc.set_mdefend(cc.get_mres()); + } + }, + + }); + + public static RuleGroup CHECKING = new RuleGroup("Checking", new Rule[] { + new Rule("C-Check") { + boolean guard(ClassCase cc) { + for (ClassCase t : cc.getSupertypes()) { + if (! t.get_OK()) { + return false; + } + } + int defenderCount = 0; + int provCount = 0; + for (ClassCase prov : cc.get_mprov()) { + if (prov.get_HasDefault()) { + defenderCount++; + } + provCount++; + } + return provCount <= 1 || defenderCount == 0; + } + + void eval(ClassCase cc) { + cc.set_OK(true); + } + }, + + }); + +} diff --git a/jdk/test/jdk/lambda/shapegen/TTNode.java b/jdk/test/jdk/lambda/shapegen/TTNode.java new file mode 100644 index 00000000000..141b052acee --- /dev/null +++ b/jdk/test/jdk/lambda/shapegen/TTNode.java @@ -0,0 +1,124 @@ +/* + * 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. + * + * 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 shapegen; + +import shapegen.ClassCase.Kind; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static shapegen.ClassCase.Kind.*; + +/** + * Type Template Node + * + * @author Robert Field + */ +public class TTNode { + + final List supertypes; + final boolean canBeClass; + + private int currentKindIndex; + private Kind[] kinds; + + public TTNode(List subtypes, boolean canBeClass) { + this.supertypes = subtypes; + this.canBeClass = canBeClass; + } + + public void start(boolean includeClasses) { + kinds = + supertypes.isEmpty()? + (new Kind[]{IDEFAULT, IPRESENT}) + : ((includeClasses && canBeClass)? + new Kind[]{CNONE, IVAC, IDEFAULT, IPRESENT} + : new Kind[]{IVAC, IDEFAULT, IPRESENT}); + currentKindIndex = 0; + + for (TTNode sub : supertypes) { + sub.start(includeClasses); + } + } + + public boolean next() { + ++currentKindIndex; + if (currentKindIndex >= kinds.length) { + currentKindIndex = 0; + return false; + } else { + return true; + } + } + + public void collectAllSubtypes(Set subs) { + subs.add(this); + for (TTNode n : supertypes) { + n.collectAllSubtypes(subs); + } + } + + private Kind getKind() { + return kinds[currentKindIndex]; + } + + boolean isInterface() { + return getKind().isInterface; + } + + boolean isClass() { + return !isInterface(); + } + + boolean hasDefault() { + return getKind() == IDEFAULT; + } + + public boolean isValid() { + for (TTNode n : supertypes) { + if (!n.isValid() || (isInterface() && n.isClass())) { + return false; + } + } + return true; + } + + public ClassCase genCase() { + ClassCase subclass; + List ttintfs; + if (isClass() && !supertypes.isEmpty() && supertypes.get(0).isClass()) { + subclass = supertypes.get(0).genCase(); + ttintfs = supertypes.subList(1, supertypes.size()); + } else { + subclass = null; + ttintfs = supertypes; + } + List intfs = new ArrayList<>(); + for (TTNode node : ttintfs) { + intfs.add(node.genCase()); + } + return new ClassCase(getKind(), subclass, intfs); + } +} diff --git a/jdk/test/jdk/lambda/shapegen/TTParser.java b/jdk/test/jdk/lambda/shapegen/TTParser.java new file mode 100644 index 00000000000..6f56ac7cd5c --- /dev/null +++ b/jdk/test/jdk/lambda/shapegen/TTParser.java @@ -0,0 +1,98 @@ +/* + * 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. + * + * 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 shapegen; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.io.IOException; +import java.io.StringReader; + +import static java.lang.Character.isLetter; +import static java.lang.Character.isUpperCase; +import static java.lang.Character.isWhitespace; + +/** + * Parse a type template definition string + * + * input :: classDef + * classDef :: letter [ ( classDef* ) ] + * + * @author Robert Field + */ +public class TTParser extends StringReader { + + private Map letterMap = new HashMap<>(); + private char ch; + + private final String def; + + public TTParser(String s) { + super(s); + this.def = s; + } + + private void advance() throws IOException { + do { + ch = (char)read(); + } while (isWhitespace(ch)); + } + + public TTNode parse() { + try { + advance(); + return classDef(); + } catch (IOException t) { + throw new RuntimeException(t); + } + } + + private TTNode classDef() throws IOException { + if (!isLetter(ch)) { + if (ch == (char)-1) { + throw new IOException("Unexpected end of type template in " + def); + } else { + throw new IOException("Unexpected character in type template: " + (Character)ch + " in " + def); + } + } + char nodeCh = ch; + TTNode node = letterMap.get(nodeCh); + boolean canBeClass = isUpperCase(nodeCh); + advance(); + if (node == null) { + List subtypes = new ArrayList<>(); + if (ch == '(') { + advance(); + while (ch != ')') { + subtypes.add(classDef()); + } + advance(); + } + node = new TTNode(subtypes, canBeClass); + letterMap.put(nodeCh, node); + } + return node; + } +} diff --git a/jdk/test/jdk/lambda/shapegen/TTShape.java b/jdk/test/jdk/lambda/shapegen/TTShape.java new file mode 100644 index 00000000000..806438787b4 --- /dev/null +++ b/jdk/test/jdk/lambda/shapegen/TTShape.java @@ -0,0 +1,102 @@ +/* + * 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. + * + * 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 shapegen; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * + * @author Robert Field + */ +public class TTShape { + + private final TTNode root; + private final TTNode[] nodes; + + TTShape(TTNode root) { + this.root = root; + Set subs = new HashSet<>(); + root.collectAllSubtypes(subs); + nodes = subs.toArray(new TTNode[subs.size()]); + } + + private List toCases(boolean includeClasses) { + List ccs = new ArrayList<>(); + root.start(includeClasses); + int i; + outer: + while (true) { + if (root.isValid()) { + ClassCase cc = root.genCase(); + //System.out.println(cc); + ccs.add(cc); + } + + i = 0; + do { + if (i >= nodes.length) { + break outer; + } + } while(!nodes[i++].next()); + } + return ccs; + } + + public static List allCases(boolean includeClasses) { + List ccs = new ArrayList<>(); + for (TTShape shape : SHAPES) { + ccs.addAll(shape.toCases(includeClasses)); + } + return ccs; + } + + public static TTShape parse(String s) { + return new TTShape(new TTParser(s).parse()); + } + + public static final TTShape[] SHAPES = new TTShape[] { + parse("a"), + parse("a(b)"), + parse("A(bb)"), + parse("A(B(d)c(d))"), + parse("A(b(c))"), + parse("A(B(cd)d)"), + parse("A(B(c)c)"), + parse("A(B(Ce)d(e))"), + parse("A(B(C)d(e))"), + parse("A(Bc(d))"), + parse("A(B(d)dc)"), + parse("A(B(dc)dc)"), + parse("A(B(c(d))d)"), + parse("A(B(C(d))d)"), + parse("A(B(C(e)d(e))e)"), + parse("A(B(c(d))c)"), + parse("A(B(dc(d))c)"), + parse("A(B(C(d))d)"), + }; + +} diff --git a/jdk/test/jdk/lambda/vm/DefaultMethodRegressionTests.java b/jdk/test/jdk/lambda/vm/DefaultMethodRegressionTests.java new file mode 100644 index 00000000000..538d26d9b5a --- /dev/null +++ b/jdk/test/jdk/lambda/vm/DefaultMethodRegressionTests.java @@ -0,0 +1,130 @@ +/* + * 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. + * + * 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 vm; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +/** + * This set of classes/interfaces (K/I/C) is specially designed to expose a + * bug in the JVM where it did not find some overloaded methods in some + * specific situations. (fixed by hotspot changeset ffb9316fd9ed) + */ +interface K { + int bbb(Long l); +} + +interface I extends K { + default void aaa() {} + default void aab() {} + default void aac() {} + + default int bbb(Integer i) { return 22; } + default int bbb(Float f) { return 33; } + default int bbb(Long l) { return 44; } + default int bbb(Double d) { return 55; } + default int bbb(String s) { return 66; } + + default void caa() {} + default void cab() {} + default void cac() {} +} + +class C implements I {} + +public class DefaultMethodRegressionTests { + + @Test(groups = "vm") + public void testLostOverloadedMethod() { + C c = new C(); + assertEquals(c.bbb(new Integer(1)), 22); + assertEquals(c.bbb(new Float(1.1)), 33); + assertEquals(c.bbb(new Long(1L)), 44); + assertEquals(c.bbb(new Double(0.01)), 55); + assertEquals(c.bbb(new String("")), 66); + } + + // Test to ensure that the inference verifier accepts older classfiles + // with classes that implement interfaces with defaults. + @Test(groups = "vm") + public void testInferenceVerifier() { + // interface I { int m() default { return 99; } } + byte I_bytes[] = { + (byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, 0x00, 0x00, 0x00, 0x34, + 0x00, 0x08, 0x07, 0x00, 0x06, 0x07, 0x00, 0x07, + 0x01, 0x00, 0x03, 0x66, 0x6f, 0x6f, 0x01, 0x00, + 0x03, 0x28, 0x29, 0x49, 0x01, 0x00, 0x04, 0x43, + 0x6f, 0x64, 0x65, 0x01, 0x00, 0x01, 0x49, 0x01, + 0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, + 0x61, 0x6e, 0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x06, 0x00, 0x00, 0x01, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, + 0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x03, 0x10, 0x63, (byte)0xac, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 + }; + // public class C implements I {} /* -target 1.5 */ + byte C_bytes[] = { + (byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x0c, 0x0a, 0x00, 0x03, 0x00, 0x08, 0x07, + 0x00, 0x09, 0x07, 0x00, 0x0a, 0x07, 0x00, 0x0b, + 0x01, 0x00, 0x06, 0x3c, 0x69, 0x6e, 0x69, 0x74, + 0x3e, 0x01, 0x00, 0x03, 0x28, 0x29, 0x56, 0x01, + 0x00, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x0c, 0x00, + 0x05, 0x00, 0x06, 0x01, 0x00, 0x01, 0x43, 0x01, + 0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, + 0x61, 0x6e, 0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x01, 0x00, 0x01, 0x49, 0x00, 0x21, + 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x05, + 0x00, 0x06, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x11, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x05, 0x2a, (byte)0xb7, 0x00, 0x01, (byte)0xb1, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + ClassLoader cl = new ClassLoader() { + protected Class findClass(String name) { + if (name.equals("I")) { + return defineClass("I", I_bytes, 0, I_bytes.length); + } else if (name.equals("C")) { + return defineClass("C", C_bytes, 0, C_bytes.length); + } else { + return null; + } + } + }; + try { + Class.forName("C", true, cl); + } catch (Exception e) { + // unmodified verifier will throw VerifyError + fail("No exception should be thrown"); + } + } +} diff --git a/jdk/test/jdk/lambda/vm/DefaultMethodsTest.java b/jdk/test/jdk/lambda/vm/DefaultMethodsTest.java new file mode 100644 index 00000000000..76ae86cd6fc --- /dev/null +++ b/jdk/test/jdk/lambda/vm/DefaultMethodsTest.java @@ -0,0 +1,810 @@ +/* + * 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. + * + * 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 vm; + +import java.lang.reflect.*; +import java.util.*; +import java.io.File; +import java.io.IOException; + +import org.testng.annotations.Test; +import separate.*; +import separate.Compiler; + +import static org.testng.Assert.*; +import static separate.SourceModel.*; +import static separate.SourceModel.Class; + +@Test(groups = "vm") +public class DefaultMethodsTest extends TestHarness { + public DefaultMethodsTest() { + super(false, false); + } + + /** + * class C { public int m() { return 22; } } + * + * TEST: C c = new C(); c.m() == 22 + */ + public void testHarnessInvokeVirtual() { + Class C = new Class("C", ConcreteMethod.std("22")); + assertInvokeVirtualEquals(22, C); + } + + /** + * interface I { int m(); } + * class C implements I { public int m() { return 33; } } + * + * TEST: I i = new C(); i.m() == 33; + */ + public void testHarnessInvokeInterface() { + Interface I = new Interface("I", AbstractMethod.std()); + Class C = new Class("C", I, ConcreteMethod.std("33")); + assertInvokeInterfaceEquals(33, C, I); + } + + /** + * class C {} + * + * TEST: C c = new C(); c.m() throws NoSuchMethod + */ + public void testHarnessThrows() { + Class C = new Class("C"); + assertThrows(NoSuchMethodError.class, C); + } + + /** + * interface I { int m() default { return 44; } } + * class C implements I {} + * + * TEST: C c = new C(); c.m() == 44; + * TEST: I i = new C(); i.m() == 44; + */ + public void testBasicDefault() { + Interface I = new Interface("I", DefaultMethod.std("44")); + Class C = new Class("C", I); + + assertInvokeVirtualEquals(44, C); + assertInvokeInterfaceEquals(44, C, I); + } + + /** + * interface I { default int m() { return 44; } } + * interface J extends I {} + * interface K extends J {} + * class C implements K {} + * + * TEST: C c = new C(); c.m() == 44; + * TEST: I i = new C(); i.m() == 44; + */ + public void testFarDefault() { + Interface I = new Interface("I", DefaultMethod.std("44")); + Interface J = new Interface("J", I); + Interface K = new Interface("K", J); + Class C = new Class("C", K); + + assertInvokeVirtualEquals(44, C); + assertInvokeInterfaceEquals(44, C, K); + } + + /** + * interface I { int m(); } + * interface J extends I { default int m() { return 44; } } + * interface K extends J {} + * class C implements K {} + * + * TEST: C c = new C(); c.m() == 44; + * TEST: K k = new C(); k.m() == 44; + */ + public void testOverrideAbstract() { + Interface I = new Interface("I", AbstractMethod.std()); + Interface J = new Interface("J", I, DefaultMethod.std("44")); + Interface K = new Interface("K", J); + Class C = new Class("C", K); + + assertInvokeVirtualEquals(44, C); + assertInvokeInterfaceEquals(44, C, K); + } + + /** + * interface I { int m() default { return 44; } } + * class C implements I { public int m() { return 55; } } + * + * TEST: C c = new C(); c.m() == 55; + * TEST: I i = new C(); i.m() == 55; + */ + public void testExisting() { + Interface I = new Interface("I", DefaultMethod.std("44")); + Class C = new Class("C", I, ConcreteMethod.std("55")); + + assertInvokeVirtualEquals(55, C); + assertInvokeInterfaceEquals(55, C, I); + } + + /** + * interface I { default int m() { return 99; } } + * class B implements I {} + * class C extends B {} + * + * TEST: C c = new C(); c.m() == 99; + * TEST: I i = new C(); i.m() == 99; + */ + public void testInherited() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Class B = new Class("B", I); + Class C = new Class("C", B); + + assertInvokeVirtualEquals(99, C); + assertInvokeInterfaceEquals(99, C, I); + } + + /** + * interface I { default int m() { return 99; } } + * class C { public int m() { return 11; } } + * class D extends C implements I {} + * + * TEST: D d = new D(); d.m() == 11; + * TEST: I i = new D(); i.m() == 11; + */ + public void testExistingInherited() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Class C = new Class("C", ConcreteMethod.std("11")); + Class D = new Class("D", C, I); + + assertInvokeVirtualEquals(11, D); + assertInvokeInterfaceEquals(11, D, I); + } + + /** + * interface I { default int m() { return 44; } } + * class C implements I { public int m() { return 11; } } + * class D extends C { public int m() { return 22; } } + * + * TEST: D d = new D(); d.m() == 22; + * TEST: I i = new D(); i.m() == 22; + */ + void testExistingInheritedOverride() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Class C = new Class("C", I, ConcreteMethod.std("11")); + Class D = new Class("D", C, ConcreteMethod.std("22")); + + assertInvokeVirtualEquals(22, D); + assertInvokeInterfaceEquals(22, D, I); + } + + /** + * interface I { default int m() { return 99; } } + * interface J { defaultint m() { return 88; } } + * class C implements I { public int m() { return 11; } } + * class D extends C { public int m() { return 22; } } + * class E extends D implements J {} + * + * TEST: E e = new E(); e.m() == 22; + * TEST: J j = new E(); j.m() == 22; + */ + public void testExistingInheritedPlusDefault() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Interface J = new Interface("J", DefaultMethod.std("88")); + Class C = new Class("C", I, ConcreteMethod.std("11")); + Class D = new Class("D", C, ConcreteMethod.std("22")); + Class E = new Class("E", D, J); + + assertInvokeVirtualEquals(22, E); + assertInvokeInterfaceEquals(22, E, J); + } + + /** + * interface I { default int m() { return 99; } } + * class B implements I {} + * class C extends B { public int m() { return 77; } } + * + * TEST: C c = new C(); c.m() == 77; + * TEST: I i = new C(); i.m() == 77; + */ + public void testInheritedWithConcrete() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Class B = new Class("B", I); + Class C = new Class("C", B, ConcreteMethod.std("77")); + + assertInvokeVirtualEquals(77, C); + assertInvokeInterfaceEquals(77, C, I); + } + + /** + * interface I { default int m() { return 99; } } + * class B implements I {} + * class C extends B implements I { public int m() { return 66; } } + * + * TEST: C c = new C(); c.m() == 66; + * TEST: I i = new C(); i.m() == 66; + */ + public void testInheritedWithConcreteAndImpl() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Class B = new Class("B", I); + Class C = new Class("C", B, I, ConcreteMethod.std("66")); + + assertInvokeVirtualEquals(66, C); + assertInvokeInterfaceEquals(66, C, I); + } + + /** + * interface I { default int m() { return 99; } } + * interface J { default int m() { return 88; } } + * class C implements I, J {} + * + * TEST: C c = new C(); c.m() throws AME + */ + public void testConflict() { + // debugTest(); + Interface I = new Interface("I", DefaultMethod.std("99")); + Interface J = new Interface("J", DefaultMethod.std("88")); + Class C = new Class("C", I, J); + + assertThrows(AbstractMethodError.class, C); + } + + /** + * interface I { int m(); } + * interface J { default int m() { return 88; } } + * class C implements I, J {} + * + * TEST: C c = new C(); c.m() throws AME + */ + public void testAmbiguousReabstract() { + Interface I = new Interface("I", AbstractMethod.std()); + Interface J = new Interface("J", DefaultMethod.std("88")); + Class C = new Class("C", I, J); + + assertThrows(AbstractMethodError.class, C); + } + + /** + * interface I { default int m() { return 99; } } + * interface J extends I { } + * interface K extends I { } + * class C implements J, K {} + * + * TEST: C c = new C(); c.m() == 99 + * TEST: J j = new C(); j.m() == 99 + * TEST: K k = new C(); k.m() == 99 + * TEST: I i = new C(); i.m() == 99 + */ + public void testDiamond() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Interface J = new Interface("J", I); + Interface K = new Interface("K", I); + Class C = new Class("C", J, K); + + assertInvokeVirtualEquals(99, C); + assertInvokeInterfaceEquals(99, C, J); + assertInvokeInterfaceEquals(99, C, K); + assertInvokeInterfaceEquals(99, C, I); + } + + /** + * interface I { default int m() { return 99; } } + * interface J extends I { } + * interface K extends I { } + * interface L extends I { } + * interface M extends I { } + * class C implements I, J, K, L, M {} + * + * TEST: C c = new C(); c.m() == 99 + * TEST: J j = new C(); j.m() == 99 + * TEST: K k = new C(); k.m() == 99 + * TEST: I i = new C(); i.m() == 99 + * TEST: L l = new C(); l.m() == 99 + * TEST: M m = new C(); m.m() == 99 + */ + public void testExpandedDiamond() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Interface J = new Interface("J", I); + Interface K = new Interface("K", I); + Interface L = new Interface("L", I); + Interface M = new Interface("M", L); + Class C = new Class("C", I, J, K, L, M); + + assertInvokeVirtualEquals(99, C); + assertInvokeInterfaceEquals(99, C, J); + assertInvokeInterfaceEquals(99, C, K); + assertInvokeInterfaceEquals(99, C, I); + assertInvokeInterfaceEquals(99, C, L); + assertInvokeInterfaceEquals(99, C, M); + } + + /** + * interface I { int m() default { return 99; } } + * interface J extends I { int m(); } + * class C implements J {} + * + * TEST: C c = new C(); c.m() throws AME + */ + public void testReabstract() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Interface J = new Interface("J", I, AbstractMethod.std()); + Class C = new Class("C", J); + + assertThrows(AbstractMethodError.class, C); + } + + /** + * interface I { default int m() { return 88; } } + * interface J extends I { default int m() { return 99; } } + * class C implements J {} + * + * TEST: C c = new C(); c.m() == 99; + * TEST: J j = new C(); j.m() == 99; + * TEST: I i = new C(); i.m() == 99; + */ + public void testShadow() { + Interface I = new Interface("I", DefaultMethod.std("88")); + Interface J = new Interface("J", I, DefaultMethod.std("99")); + Class C = new Class("C", J); + + assertInvokeVirtualEquals(99, C); + assertInvokeInterfaceEquals(99, C, J); + assertInvokeInterfaceEquals(99, C, I); + } + + /** + * interface I { default int m() { return 88; } } + * interface J extends I { default int m() { return 99; } } + * class C implements I, J {} + * + * TEST: C c = new C(); c.m() == 99; + * TEST: J j = new C(); j.m() == 99; + * TEST: I i = new C(); i.m() == 99; + */ + public void testDisqualified() { + Interface I = new Interface("I", DefaultMethod.std("88")); + Interface J = new Interface("J", I, DefaultMethod.std("99")); + Class C = new Class("C", I, J); + + assertInvokeVirtualEquals(99, C); + assertInvokeInterfaceEquals(99, C, J); + assertInvokeInterfaceEquals(99, C, I); + } + + /** + * interface I { default int m(T t) { return 99; } } + * Class C implements I { public int m() { return 88; } } + * + * TEST: C c = new C(); c.m() == 88; + * TEST: I i = new C(); i.m() == 88; + */ + public void testSelfFill() { + // This test ensures that a concrete method overrides a default method + // that matches at the language-level, but has a different method + // signature due to erasure. + + // debugTest(); + + DefaultMethod dm = new DefaultMethod( + "int", "m", "return 99;", new MethodParameter("T", "t")); + ConcreteMethod cm = new ConcreteMethod( + "int", "m", "return 88;", AccessFlag.PUBLIC, + new MethodParameter("String", "s")); + + Interface I = new Interface("I", new TypeParameter("T"), dm); + Class C = new Class("C", I.with("String"), cm); + + AbstractMethod pm = new AbstractMethod( + "int", "m", new MethodParameter("T", "t")); + + assertInvokeVirtualEquals(new Integer(88), C, cm, "-1", "\"string\""); + assertInvokeInterfaceEquals( + new Integer(88), C, I.with("String"), pm, "\"string\""); + } + + /** + * interface I { default int m() { return 99; } } + * class C implements I {} + * + * TEST: C.class.getMethod("m").invoke(new C()) == 99 + */ + public void testReflectCall() { + Interface I = new Interface("I", DefaultMethod.std("99")); + //workaround accessibility issue when loading C with DirectedClassLoader + I.addAccessFlag(AccessFlag.PUBLIC); + Class C = new Class("C", I); + + Compiler.Flags[] flags = this.verbose ? + new Compiler.Flags[] { Compiler.Flags.VERBOSE } : + new Compiler.Flags[] {}; + Compiler compiler = new Compiler(flags); + java.lang.Class cls = null; + try { + cls = compiler.compileAndLoad(C); + } catch (ClassNotFoundException e) { + fail("Could not load class"); + } + + java.lang.reflect.Method method = null; + try { + method = cls.getMethod(stdMethodName); + } catch (NoSuchMethodException e) { + fail("Could not find method in class"); + } + assertNotNull(method); + + Object c = null; + try { + c = cls.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + fail("Could not create instance of class"); + } + assertNotNull(c); + + Integer res = null; + try { + res = (Integer)method.invoke(c); + } catch (IllegalAccessException | + java.lang.reflect.InvocationTargetException e) { + fail("Could not invoke default instance method"); + } + assertNotNull(res); + + assertEquals(res.intValue(), 99); + + compiler.cleanup(); + } + + /** + * interface I { default int m(T t, V v, W w) { return 99; } } + * interface J extends I { int m(T t, V v, String w); } } + * interface K extends J { int m(T t, String v, String w); } } + * class C implements K { + * public int m(String t, String v, String w) { return 88; } + * } + * + * TEST: I i = new C(); i.m("A","B","C") == 88; + * TEST: J j = new C(); j.m("A","B","C") == 88; + * TEST: K k = new C(); k.m("A","B","C") == 88; + */ + public void testBridges() { + DefaultMethod dm = new DefaultMethod("int", stdMethodName, "return 99;", + new MethodParameter("T", "t"), new MethodParameter("V", "v"), + new MethodParameter("W", "w")); + + AbstractMethod pm0 = new AbstractMethod("int", stdMethodName, + new MethodParameter("T", "t"), new MethodParameter("V", "v"), + new MethodParameter("W", "w")); + + AbstractMethod pm1 = new AbstractMethod("int", stdMethodName, + new MethodParameter("T", "t"), new MethodParameter("V", "v"), + new MethodParameter("String", "w")); + + AbstractMethod pm2 = new AbstractMethod("int", stdMethodName, + new MethodParameter("T", "t"), new MethodParameter("String", "v"), + new MethodParameter("String", "w")); + + ConcreteMethod cm = new ConcreteMethod("int",stdMethodName,"return 88;", + AccessFlag.PUBLIC, + new MethodParameter("String", "t"), + new MethodParameter("String", "v"), + new MethodParameter("String", "w")); + + Interface I = new Interface("I", new TypeParameter("T"), + new TypeParameter("V"), new TypeParameter("W"), dm); + Interface J = new Interface("J", + new TypeParameter("T"), new TypeParameter("V"), + I.with("String", "T", "V"), pm1); + Interface K = new Interface("K", new TypeParameter("T"), + J.with("String", "T"), pm2); + Class C = new Class("C", K.with("String"), cm); + + String[] args = new String[] { "\"A\"", "\"B\"", "\"C\"" }; + assertInvokeInterfaceEquals(new Integer(88), C, + I.with("String", "String", "String"), pm0, args); + assertInvokeInterfaceEquals(new Integer(88), C, + J.with("String", "String"), pm1, args); + assertInvokeInterfaceEquals(new Integer(88), C, + K.with("String"), pm2, args); + } + + /** + * interface J { default int m() { return 88; } } + * interface I extends J { default int m() { return J.super.m(); } } + * class C implements I {} + * + * TEST: C c = new C(); c.m() == 88; + * TEST: I i = new C(); i.m() == 88; + */ + public void testSuperBasic() { + // debugTest(); + + Interface J = new Interface("J", DefaultMethod.std("88")); + Interface I = new Interface("I", J, new DefaultMethod( + "int", stdMethodName, "return J.super.m();")); + I.addCompilationDependency(J.findMethod(stdMethodName)); + Class C = new Class("C", I); + + assertInvokeVirtualEquals(88, C); + assertInvokeInterfaceEquals(88, C, I); + } + + /** + * interface K { int m() default { return 99; } } + * interface L { int m() default { return 101; } } + * interface J extends K, L {} + * interface I extends J, K { int m() default { J.super.m(); } } + * class C implements I {} + * + * TEST: C c = new C(); c.m() throws AME + * TODO: add case for K k = new C(); k.m() throws AME + */ + public void testSuperConflict() { + // debugTest(); + + Interface K = new Interface("K", DefaultMethod.std("99")); + Interface L = new Interface("L", DefaultMethod.std("101")); + Interface J = new Interface("J", K, L); + Interface I = new Interface("I", J, K, new DefaultMethod( + "int", stdMethodName, "return J.super.m();")); + Interface Jstub = new Interface("J", DefaultMethod.std("-1")); + I.addCompilationDependency(Jstub); + I.addCompilationDependency(Jstub.findMethod(stdMethodName)); + Class C = new Class("C", I); + + assertThrows(AbstractMethodError.class, C); + } + + /** + * interface I { default int m() { return 99; } } + * interface J extends I { default int m() { return 55; } } + * class C implements I, J { public int m() { return I.super.m(); } } + * + * TEST: C c = new C(); c.m() throws AME + * TODO: add case for J j = new C(); j.m() throws AME + */ + public void testSuperDisqual() { + Interface I = new Interface("I", DefaultMethod.std("99")); + Interface J = new Interface("J", I, DefaultMethod.std("55")); + Class C = new Class("C", I, J, + new ConcreteMethod("int", stdMethodName, "return I.super.m();", + AccessFlag.PUBLIC)); + C.addCompilationDependency(I.findMethod(stdMethodName)); + + assertThrows(AbstractMethodError.class, C); + } + + /** + * interface J { int m(); } + * interface I extends J { default int m() { return J.super.m(); } } + * class C implements I {} + * + * TEST: C c = new C(); c.m() throws AME + * TODO: add case for I i = new C(); i.m() throws AME + */ + public void testSuperNull() { + Interface J = new Interface("J", AbstractMethod.std()); + Interface I = new Interface("I", J, new DefaultMethod( + "int", stdMethodName, "return J.super.m();")); + Interface Jstub = new Interface("J", DefaultMethod.std("99")); + I.addCompilationDependency(Jstub); + I.addCompilationDependency(Jstub.findMethod(stdMethodName)); + Class C = new Class("C", I); + + assertThrows(AbstractMethodError.class, C); + } + + /** + * interface J { default int m(T t) { return 88; } } + * interface I extends J { + * int m(String s) default { return J.super.m(); } + * } + * class C implements I {} + * + * TEST: I i = new C(); i.m("") == 88; + */ + public void testSuperGeneric() { + Interface J = new Interface("J", new TypeParameter("T"), + new DefaultMethod("int", stdMethodName, "return 88;", + new MethodParameter("T", "t"))); + Interface I = new Interface("I", J.with("String"), + new DefaultMethod("int", stdMethodName, "return J.super.m(s);", + new MethodParameter("String", "s"))); + I.addCompilationDependency(J.findMethod(stdMethodName)); + Class C = new Class("C", I); + + AbstractMethod pm = new AbstractMethod("int", stdMethodName, + new MethodParameter("String", "s")); + + assertInvokeInterfaceEquals( + new Integer(88), C, new Extends(I), pm, "\"\""); + } + + /** + * interface I { int m(T t) default { return 44; } } + * interface J extends I { int m(String s) default { return 55; } } + * class C implements I, J { + * public int m(String s) { return I.super.m(s); } + * } + * + * TEST: C c = new C(); c.m("string") throws AME + */ + public void testSuperGenericDisqual() { + MethodParameter t = new MethodParameter("T", "t"); + MethodParameter s = new MethodParameter("String", "s"); + + Interface I = new Interface("I", new TypeParameter("T"), + new DefaultMethod("int", stdMethodName, "return 44;", t)); + Interface J = new Interface("J", I.with("String"), + new DefaultMethod("int", stdMethodName, "return 55;", s)); + Class C = new Class("C", I.with("String"), J, + new ConcreteMethod("int", stdMethodName, + "return I.super.m(s);", AccessFlag.PUBLIC, s)); + C.addCompilationDependency(I.findMethod(stdMethodName)); + + assertThrows(AbstractMethodError.class, C, + new ConcreteMethod( + "int", stdMethodName, "return -1;", AccessFlag.PUBLIC, s), + "-1", "\"string\""); + } + + /** + * interface I { default Integer m() { return new Integer(88); } } + * class C { Number m() { return new Integer(99); } } + * class D extends C implements I {} + * class S { Object foo() { return (new D()).m(); } // link sig: ()LInteger; + * TEST: S s = new S(); s.foo() == new Integer(99) + */ + public void testCovarBridge() { + Interface I = new Interface("I", new DefaultMethod( + "Integer", "m", "return new Integer(88);")); + Class C = new Class("C", new ConcreteMethod( + "Number", "m", "return new Integer(99);", AccessFlag.PUBLIC)); + Class D = new Class("D", I, C); + + ConcreteMethod DstubMethod = new ConcreteMethod( + "Integer", "m", "return null;", AccessFlag.PUBLIC); + Class Dstub = new Class("D", DstubMethod); + + ConcreteMethod toCall = new ConcreteMethod( + "Object", "foo", "return (new D()).m();", AccessFlag.PUBLIC); + Class S = new Class("S", D, toCall); + S.addCompilationDependency(Dstub); + S.addCompilationDependency(DstubMethod); + + assertInvokeVirtualEquals(new Integer(99), S, toCall, "null"); + } + + /** + * interface I { default Integer m() { return new Integer(88); } } + * class C { int m() { return 99; } } + * class D extends C implements I {} + * class S { Object foo() { return (new D()).m(); } // link sig: ()LInteger; + * TEST: S s = new S(); s.foo() == new Integer(88) + */ + public void testNoCovarNoBridge() { + Interface I = new Interface("I", new DefaultMethod( + "Integer", "m", "return new Integer(88);")); + Class C = new Class("C", new ConcreteMethod( + "int", "m", "return 99;", AccessFlag.PUBLIC)); + Class D = new Class("D", I, C); + + ConcreteMethod DstubMethod = new ConcreteMethod( + "Integer", "m", "return null;", AccessFlag.PUBLIC); + Class Dstub = new Class("D", DstubMethod); + + ConcreteMethod toCall = new ConcreteMethod( + "Object", "foo", "return (new D()).m();", AccessFlag.PUBLIC); + Class S = new Class("S", D, toCall); + S.addCompilationDependency(Dstub); + S.addCompilationDependency(DstubMethod); + + assertInvokeVirtualEquals(new Integer(88), S, toCall, "null"); + } + + /** + * interface J { int m(); } + * interface I extends J { default int m() { return 99; } } + * class B implements J {} + * class C extends B implements I {} + * TEST: C c = new C(); c.m() == 99 + * + * The point of this test is that B does not get default method analysis, + * and C does not generate any new miranda methods in the vtable. + * It verifies that default method analysis occurs when mirandas have been + * inherited and the supertypes don't have any overpass methods. + */ + public void testNoNewMiranda() { + Interface J = new Interface("J", AbstractMethod.std()); + Interface I = new Interface("I", J, DefaultMethod.std("99")); + Class B = new Class("B", J); + Class C = new Class("C", B, I); + assertInvokeVirtualEquals(99, C); + } + + /** + * interface I { int m(T t, V v, W w); } + * interface J implements I { int m(T t, V v, String w); } + * interface K implements J { + * int m(T t, String v, String w); { return 99; } } + * class C implements K { + * public int m(Object t, Object v, String w) { return 77; } + * } + * TEST C = new C(); ((I)c).m(Object,Object,Object) == 99 + * TEST C = new C(); ((J)c).m(Object,Object,String) == 77 + * TEST C = new C(); ((K)c).m(Object,String,String) == 99 + * + * Test that a erased-signature-matching method does not implement + * non-language-level matching methods + */ + public void testNonConcreteFill() { + AbstractMethod ipm = new AbstractMethod("int", "m", + new MethodParameter("T", "t"), + new MethodParameter("V", "s"), + new MethodParameter("W", "w")); + Interface I = new Interface("I", + new TypeParameter("T"), + new TypeParameter("V"), + new TypeParameter("W"), ipm); + + AbstractMethod jpm = new AbstractMethod("int", "m", + new MethodParameter("T", "t"), + new MethodParameter("V", "s"), + new MethodParameter("String", "w")); + Interface J = new Interface("J", + new TypeParameter("T"), + new TypeParameter("V"), + I.with("T", "V", "String"), jpm); + + AbstractMethod kpm = new AbstractMethod("int", "m", + new MethodParameter("T", "t"), + new MethodParameter("String", "s"), + new MethodParameter("String", "w")); + Interface K = new Interface("K", + new TypeParameter("T"), + J.with("T", "String"), + new DefaultMethod("int", "m", "return 99;", + new MethodParameter("T", "t"), + new MethodParameter("String", "v"), + new MethodParameter("String", "w"))); + + Class C = new Class("C", + K.with("String"), + new ConcreteMethod("int", "m", "return 77;", + AccessFlag.PUBLIC, + new MethodParameter("Object", "t"), + new MethodParameter("Object", "v"), + new MethodParameter("String", "w"))); + + String a = "\"\""; + assertInvokeInterfaceEquals(99, C, + K.with("String"), kpm, a, a, a); + assertInvokeInterfaceEquals(77, C, + J.with("String", "String"), jpm, a, a, a); + assertInvokeInterfaceEquals(99, C, + I.with("String", "String", "String"), ipm, a, a, a); + } + + public void testStrictfpDefault() { + try { + java.lang.Class.forName("vm.StrictfpDefault"); + } catch (Exception e) { + fail("Could not load class", e); + } + } +} diff --git a/jdk/test/jdk/lambda/vm/InterfaceAccessFlagsTest.java b/jdk/test/jdk/lambda/vm/InterfaceAccessFlagsTest.java new file mode 100644 index 00000000000..b08e67c7a09 --- /dev/null +++ b/jdk/test/jdk/lambda/vm/InterfaceAccessFlagsTest.java @@ -0,0 +1,90 @@ +/* + * 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. + * + * 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 vm; + +import java.io.*; + +import org.testng.annotations.Test; +import separate.*; +import separate.Compiler; + +import static org.testng.Assert.*; +import static separate.SourceModel.*; +import static separate.SourceModel.Class; + +public class InterfaceAccessFlagsTest extends TestHarness { + public InterfaceAccessFlagsTest() { + super(false, false); + } + + public void testMethodCallWithFlag(AccessFlag ... flags) { + Class I = new Class("I", + new ConcreteMethod("int", "m", "return priv();", AccessFlag.PUBLIC), + new ConcreteMethod("int", "priv", "return 99;", flags)); + Interface Istub = new Interface("I", + new DefaultMethod("int", "m", "return 0;")); + Class C = new Class("C", Istub, + new ConcreteMethod("int", "foo", "return (new C()).m();", + AccessFlag.PUBLIC, AccessFlag.STATIC)); + C.addCompilationDependency(Istub.findMethod("m")); + + Compiler compiler = new Compiler(/*Compiler.Flags.VERBOSE*/); + compiler.addPostprocessor(new ClassToInterfaceConverter("I")); + // Turns I from a class into an interface when loading + + ClassLoader cl = compiler.compile(C, I); + try { + java.lang.Class C_class = + java.lang.Class.forName("C", true, cl); + assertNotNull(C_class); + java.lang.reflect.Method m = C_class.getMethod("foo"); + assertNotNull(m); + Integer res = (Integer)m.invoke(null); + assertEquals(res.intValue(), 99); + } catch (java.lang.reflect.InvocationTargetException e) { + fail("Unexpected exception: " + e.getCause()); + } catch (Throwable e) { + fail("Unexpected exception: " + e); + } finally { + compiler.cleanup(); + } + } + + @Test(groups = "vm_prototype") + public void testPrivateMethodCall() { + testMethodCallWithFlag(AccessFlag.PRIVATE); + } + + @Test(groups = "vm_prototype") + public void testStaticMethodCall() { + testMethodCallWithFlag(AccessFlag.PUBLIC, AccessFlag.STATIC); + } + + @Test(groups = "vm_prototype") + public void testPrivateStaticMethodCall() { + testMethodCallWithFlag(AccessFlag.PRIVATE, AccessFlag.STATIC); + } + + // Test other combos? Protected? +} diff --git a/jdk/test/jdk/lambda/vm/StrictfpDefault.java b/jdk/test/jdk/lambda/vm/StrictfpDefault.java new file mode 100644 index 00000000000..9b7e1680e1b --- /dev/null +++ b/jdk/test/jdk/lambda/vm/StrictfpDefault.java @@ -0,0 +1,32 @@ +/* + * 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. + * + * 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 vm; + +/* +* @test +* @ignore +*/ +interface StrictfpDefault { + default strictfp void m() {} +}