diff --git a/src/share/classes/java/util/stream/Streams.java b/src/share/classes/java/util/stream/Streams.java index 7bf3123af65e668cf152af8d9092bb07584193e5..fe83b9708df5a4b06634762deebb295ce73dfd23 100644 --- a/src/share/classes/java/util/stream/Streams.java +++ b/src/share/classes/java/util/stream/Streams.java @@ -681,11 +681,9 @@ final class Streams { this.aSpliterator = aSpliterator; this.bSpliterator = bSpliterator; beforeSplit = true; - // The spliterator is unsized before splitting if a and b are - // sized and the sum of the estimates overflows - unsized = aSpliterator.hasCharacteristics(SIZED) - && aSpliterator.hasCharacteristics(SIZED) - && aSpliterator.estimateSize() + bSpliterator.estimateSize() < 0; + // The spliterator is known to be unsized before splitting if the + // sum of the estimates overflows. + unsized = aSpliterator.estimateSize() + bSpliterator.estimateSize() < 0; } @Override diff --git a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java index 1b3c4b65bf243ef7b431d982836ee0e2556f521f..43c513449508d948c178804dd6f892cfcbe983c3 100644 --- a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java +++ b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java @@ -22,6 +22,8 @@ */ package org.openjdk.tests.java.util.stream; +import java.util.Spliterator; +import java.util.stream.BaseStream; import java.util.stream.OpTestCase; import java.util.stream.StreamTestDataProvider; @@ -34,16 +36,107 @@ import java.util.stream.DoubleStream; import java.util.stream.TestData; import static java.util.stream.LambdaTestHelpers.*; +import static org.testng.Assert.assertEquals; +/** + * @test + * @bug 8021863 + */ public class ConcatOpTest extends OpTestCase { // Sanity to make sure all type of stream source works @Test(dataProvider = "StreamTestData", dataProviderClass = StreamTestDataProvider.class) - public void testOpsSequential(String name, TestData.OfRef data) { + public void testOps(String name, TestData.OfRef data) { exerciseOpsInt(data, s -> Stream.concat(s, data.stream()), s -> IntStream.concat(s, data.stream().mapToInt(Integer::intValue)), s -> LongStream.concat(s, data.stream().mapToLong(Integer::longValue)), s -> DoubleStream.concat(s, data.stream().mapToDouble(Integer::doubleValue))); } + + public void testSize() { + assertSized(Stream.concat( + LongStream.range(0, Long.MAX_VALUE / 2).boxed(), + LongStream.range(0, Long.MAX_VALUE / 2).boxed())); + + assertUnsized(Stream.concat( + LongStream.range(0, Long.MAX_VALUE).boxed(), + LongStream.range(0, Long.MAX_VALUE).boxed())); + + assertUnsized(Stream.concat( + LongStream.range(0, Long.MAX_VALUE).boxed(), + Stream.iterate(0, i -> i + 1))); + + assertUnsized(Stream.concat( + Stream.iterate(0, i -> i + 1), + LongStream.range(0, Long.MAX_VALUE).boxed())); + } + + public void testLongSize() { + assertSized(LongStream.concat( + LongStream.range(0, Long.MAX_VALUE / 2), + LongStream.range(0, Long.MAX_VALUE / 2))); + + assertUnsized(LongStream.concat( + LongStream.range(0, Long.MAX_VALUE), + LongStream.range(0, Long.MAX_VALUE))); + + assertUnsized(LongStream.concat( + LongStream.range(0, Long.MAX_VALUE), + LongStream.iterate(0, i -> i + 1))); + + assertUnsized(LongStream.concat( + LongStream.iterate(0, i -> i + 1), + LongStream.range(0, Long.MAX_VALUE))); + } + + public void testIntSize() { + assertSized(IntStream.concat( + IntStream.range(0, Integer.MAX_VALUE), + IntStream.range(0, Integer.MAX_VALUE))); + + assertUnsized(IntStream.concat( + LongStream.range(0, Long.MAX_VALUE).mapToInt(i -> (int) i), + LongStream.range(0, Long.MAX_VALUE).mapToInt(i -> (int) i))); + + assertUnsized(IntStream.concat( + LongStream.range(0, Long.MAX_VALUE).mapToInt(i -> (int) i), + IntStream.iterate(0, i -> i + 1))); + + assertUnsized(IntStream.concat( + IntStream.iterate(0, i -> i + 1), + LongStream.range(0, Long.MAX_VALUE).mapToInt(i -> (int) i))); + } + + public void testDoubleSize() { + assertSized(DoubleStream.concat( + IntStream.range(0, Integer.MAX_VALUE).mapToDouble(i -> i), + IntStream.range(0, Integer.MAX_VALUE).mapToDouble(i -> i))); + + assertUnsized(DoubleStream.concat( + LongStream.range(0, Long.MAX_VALUE).mapToDouble(i -> i), + LongStream.range(0, Long.MAX_VALUE).mapToDouble(i -> i))); + + assertUnsized(DoubleStream.concat( + LongStream.range(0, Long.MAX_VALUE).mapToDouble(i -> i), + DoubleStream.iterate(0, i -> i + 1))); + + assertUnsized(DoubleStream.concat( + DoubleStream.iterate(0, i -> i + 1), + LongStream.range(0, Long.MAX_VALUE).mapToDouble(i -> i))); + } + + void assertUnsized(BaseStream s) { + Spliterator sp = s.spliterator(); + + assertFalse(sp.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)); + assertEquals(sp.estimateSize(), Long.MAX_VALUE); + } + + void assertSized(BaseStream s) { + Spliterator sp = s.spliterator(); + + assertTrue(sp.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)); + assertTrue(sp.estimateSize() < Long.MAX_VALUE); + } }