# HG changeset patch # User psandoz # Date 1375180346 -3600 # Node ID 8f176099ec00eeb3ab9b7a4ebae0c0fafd9be78d # Parent bc096b85d91dd62062975e1973e40cb7257857a9 8021863: Stream.concat incorrectly calculates unsized state Reviewed-by: chegar diff -r bc096b85d91d -r 8f176099ec00 jdk/src/share/classes/java/util/stream/Streams.java --- a/jdk/src/share/classes/java/util/stream/Streams.java Tue Jul 30 15:47:35 2013 -0700 +++ b/jdk/src/share/classes/java/util/stream/Streams.java Tue Jul 30 11:32:26 2013 +0100 @@ -681,11 +681,9 @@ 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 -r bc096b85d91d -r 8f176099ec00 jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java Tue Jul 30 15:47:35 2013 -0700 +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java Tue Jul 30 11:32:26 2013 +0100 @@ -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.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); + } }