1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @summary close handlers and closing streams 27 * @bug 8044047 28 */ 29 30 package org.openjdk.tests.java.util.stream; 31 32 import java.util.Arrays; 33 import java.util.stream.OpTestCase; 34 import java.util.stream.Stream; 35 36 import org.testng.annotations.Test; 37 38 import static java.util.stream.LambdaTestHelpers.countTo; 39 import static java.util.stream.ThowableHelper.checkNPE; 40 import static java.util.stream.ThowableHelper.checkISE; 41 42 @Test(groups = { "serialization-hostile" }) 43 public class StreamCloseTest extends OpTestCase { 44 public void testNullCloseHandler() { 45 checkNPE(() -> Stream.of(1).onClose(null)); 46 } 47 48 public void testEmptyCloseHandler() { 49 try (Stream<Integer> ints = countTo(100).stream()) { 50 ints.forEach(i -> {}); 51 } 52 } 53 54 public void testOneCloseHandler() { 55 final boolean[] holder = new boolean[1]; 56 Runnable closer = () -> { holder[0] = true; }; 57 58 try (Stream<Integer> ints = countTo(100).stream()) { 59 ints.onClose(closer); 60 ints.forEach(i -> {}); 61 } 62 assertTrue(holder[0]); 63 64 Arrays.fill(holder, false); 65 try (Stream<Integer> ints = countTo(100).stream().onClose(closer)) { 66 ints.forEach(i -> {}); 67 } 68 assertTrue(holder[0]); 69 70 Arrays.fill(holder, false); 71 try (Stream<Integer> ints = countTo(100).stream().filter(e -> true).onClose(closer)) { 72 ints.forEach(i -> {}); 73 } 74 assertTrue(holder[0]); 75 76 Arrays.fill(holder, false); 77 try (Stream<Integer> ints = countTo(100).stream().filter(e -> true).onClose(closer).filter(e -> true)) { 78 ints.forEach(i -> {}); 79 } 80 assertTrue(holder[0]); 81 } 82 83 public void testTwoCloseHandlers() { 84 final boolean[] holder = new boolean[2]; 85 Runnable close1 = () -> { holder[0] = true; }; 86 Runnable close2 = () -> { holder[1] = true; }; 87 88 try (Stream<Integer> ints = countTo(100).stream()) { 89 ints.onClose(close1).onClose(close2); 90 ints.forEach(i -> {}); 91 } 92 assertTrue(holder[0] && holder[1]); 93 94 Arrays.fill(holder, false); 95 try (Stream<Integer> ints = countTo(100).stream().onClose(close1).onClose(close2)) { 96 ints.forEach(i -> {}); 97 } 98 assertTrue(holder[0] && holder[1]); 99 100 Arrays.fill(holder, false); 101 try (Stream<Integer> ints = countTo(100).stream().filter(e -> true).onClose(close1).onClose(close2)) { 102 ints.forEach(i -> {}); 103 } 104 assertTrue(holder[0] && holder[1]); 105 106 Arrays.fill(holder, false); 107 try (Stream<Integer> ints = countTo(100).stream().filter(e -> true).onClose(close1).onClose(close2).filter(e -> true)) { 108 ints.forEach(i -> {}); 109 } 110 assertTrue(holder[0] && holder[1]); 111 } 112 113 public void testCascadedExceptions() { 114 final boolean[] holder = new boolean[3]; 115 boolean caught = false; 116 Runnable close1 = () -> { holder[0] = true; throw new RuntimeException("1"); }; 117 Runnable close2 = () -> { holder[1] = true; throw new RuntimeException("2"); }; 118 Runnable close3 = () -> { holder[2] = true; throw new RuntimeException("3"); }; 119 120 try (Stream<Integer> ints = countTo(100).stream()) { 121 ints.onClose(close1).onClose(close2).onClose(close3); 122 ints.forEach(i -> {}); 123 } 124 catch (RuntimeException e) { 125 assertCascaded(e, 3); 126 assertTrue(holder[0] && holder[1] && holder[2]); 127 caught = true; 128 } 129 assertTrue(caught); 130 131 Arrays.fill(holder, false); 132 caught = false; 133 try (Stream<Integer> ints = countTo(100).stream().onClose(close1).onClose(close2).onClose(close3)) { 134 ints.forEach(i -> {}); 135 } 136 catch (RuntimeException e) { 137 assertCascaded(e, 3); 138 assertTrue(holder[0] && holder[1] && holder[2]); 139 caught = true; 140 } 141 assertTrue(caught); 142 143 caught = false; 144 Arrays.fill(holder, false); 145 try (Stream<Integer> ints = countTo(100).stream().filter(e -> true).onClose(close1).onClose(close2).onClose(close3)) { 146 ints.forEach(i -> {}); 147 } 148 catch (RuntimeException e) { 149 assertCascaded(e, 3); 150 assertTrue(holder[0] && holder[1] && holder[2]); 151 caught = true; 152 } 153 assertTrue(caught); 154 155 caught = false; 156 Arrays.fill(holder, false); 157 try (Stream<Integer> ints = countTo(100).stream().filter(e -> true).onClose(close1).onClose(close2).filter(e -> true).onClose(close3)) { 158 ints.forEach(i -> {}); 159 } 160 catch (RuntimeException e) { 161 assertCascaded(e, 3); 162 assertTrue(holder[0] && holder[1] && holder[2]); 163 caught = true; 164 } 165 assertTrue(caught); 166 } 167 168 private void assertCascaded(RuntimeException e, int n) { 169 assertTrue(e.getMessage().equals("1")); 170 assertTrue(e.getSuppressed().length == n - 1); 171 for (int i=0; i<n-1; i++) 172 assertTrue(e.getSuppressed()[i].getMessage().equals(String.valueOf(i + 2))); 173 } 174 175 public void testConsumed() { 176 try(Stream<Integer> s = countTo(100).stream()) { 177 s.forEach(i -> {}); 178 // Adding onClose handler when stream is consumed is illegal 179 // handler must not be registered 180 checkISE(() -> s.onClose(() -> fail("1"))); 181 } 182 183 // close() must be idempotent: 184 // second close() invoked at the end of try-with-resources must have no effect 185 try(Stream<Integer> s = countTo(100).stream()) { 186 s.close(); 187 // Adding onClose handler when stream is closed is also illegal 188 checkISE(() -> s.onClose(() -> fail("3"))); 189 } 190 } 191 }