8193856: takeWhile produces incorrect result with elements produced by flatMap
authorpsandoz
Wed, 20 Dec 2017 11:40:45 -0800
changeset 48410 8aab0cea56bf
parent 48409 5ab69533994b
child 48411 4ff5c5206427
8193856: takeWhile produces incorrect result with elements produced by flatMap Reviewed-by: smarks
src/java.base/share/classes/java/util/stream/WhileOps.java
test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/WhileOpTest.java
--- a/src/java.base/share/classes/java/util/stream/WhileOps.java	Thu Dec 21 09:29:24 2017 -0800
+++ b/src/java.base/share/classes/java/util/stream/WhileOps.java	Wed Dec 20 11:40:45 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -95,7 +95,7 @@
 
                     @Override
                     public void accept(T t) {
-                        if (take = predicate.test(t)) {
+                        if (take && (take = predicate.test(t))) {
                             downstream.accept(t);
                         }
                     }
@@ -152,7 +152,7 @@
 
                     @Override
                     public void accept(int t) {
-                        if (take = predicate.test(t)) {
+                        if (take && (take = predicate.test(t))) {
                             downstream.accept(t);
                         }
                     }
@@ -209,7 +209,7 @@
 
                     @Override
                     public void accept(long t) {
-                        if (take = predicate.test(t)) {
+                        if (take && (take = predicate.test(t))) {
                             downstream.accept(t);
                         }
                     }
@@ -266,7 +266,7 @@
 
                     @Override
                     public void accept(double t) {
-                        if (take = predicate.test(t)) {
+                        if (take && (take = predicate.test(t))) {
                             downstream.accept(t);
                         }
                     }
--- a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/WhileOpTest.java	Thu Dec 21 09:29:24 2017 -0800
+++ b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/WhileOpTest.java	Wed Dec 20 11:40:45 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, 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
@@ -46,7 +46,7 @@
 
 /*
  * @test
- * @bug 8071597
+ * @bug 8071597 8193856
  */
 @Test
 public class WhileOpTest extends OpTestCase {
@@ -361,4 +361,33 @@
         }
         assertTrue(isClosed.get());
     }
+
+    @Test(groups = { "serialization-hostile" })
+    public void testFlatMapThenTake() {
+        TestData.OfRef<Integer> range = TestData.Factory.ofSupplier(
+                "range", () -> IntStream.range(0, 100).boxed());
+
+        exerciseOpsMulti(range,
+                         // Reference result
+                         s -> s.takeWhile(e -> e != 50),
+                         // For other results collect into array,
+                         // stream the single array (not the elements),
+                         // then flat map to stream the array elements
+                         s -> Stream.<Integer[]>of(s.toArray(Integer[]::new)).
+                                 flatMap(Stream::of).
+                                 takeWhile(e -> e != 50),
+                         s -> Stream.of(s.mapToInt(e -> e).toArray()).
+                                 flatMapToInt(IntStream::of).
+                                 takeWhile(e -> e != 50).
+                                 mapToObj(e -> e),
+                         s -> Stream.of(s.mapToLong(e -> e).toArray()).
+                                 flatMapToLong(LongStream::of).
+                                 takeWhile(e -> e != 50L).
+                                 mapToObj(e -> (int) e),
+                         s -> Stream.of(s.mapToDouble(e -> e).toArray()).
+                                 flatMapToDouble(DoubleStream::of).
+                                 takeWhile(e -> e != 50.0).
+                                 mapToObj(e -> (int) e)
+                         );
+    }
 }