1 /* 2 * Copyright (c) 2011, 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 import java.io.*; 25 26 /** 27 * @test 28 * @bug 7015589 8054565 29 * @summary Test that buffering streams are considered closed even when the 30 * close or flush from the underlying stream fails. 31 */ 32 33 public class FailingFlushAndClose { 34 35 static int failed; 36 fail(String msg)37 static void fail(String msg) { 38 System.err.println("FAIL: " + msg); 39 failed++; 40 } 41 failWithIOE(String msg)42 static void failWithIOE(String msg) throws IOException { 43 fail(msg); 44 throw new IOException(msg); 45 } 46 47 static class FailingCloseInputStream extends InputStream { 48 boolean closed; 49 @Override read()50 public int read()throws IOException { 51 if (closed) 52 failWithIOE("input stream is closed"); 53 return 1; 54 } 55 @Override close()56 public void close() throws IOException { 57 if (!closed) { 58 closed = true; 59 throw new IOException("close failed"); 60 } 61 } 62 } 63 64 static class FailingCloseOutputStream extends OutputStream { 65 boolean closed; 66 @Override write(int b)67 public void write(int b) throws IOException { 68 if (closed) 69 failWithIOE("output stream is closed"); 70 } 71 @Override flush()72 public void flush() throws IOException { 73 if (closed) 74 failWithIOE("output stream is closed"); 75 } 76 @Override close()77 public void close() throws IOException { 78 if (!closed) { 79 closed = true; 80 throw new IOException("close failed"); 81 } 82 } 83 } 84 85 static class FailingFlushOutputStream extends OutputStream { 86 boolean closed; 87 @Override write(int b)88 public void write(int b) throws IOException { 89 if (closed) 90 failWithIOE("output stream is closed"); 91 } 92 @Override flush()93 public void flush() throws IOException { 94 if (closed) { 95 failWithIOE("output stream is closed"); 96 } else { 97 throw new IOException("flush failed"); 98 } 99 } 100 @Override close()101 public void close() throws IOException { 102 closed = true; 103 } 104 } 105 106 static class FailingCloseReader extends Reader { 107 boolean closed; 108 @Override read(char[] cbuf, int off, int len)109 public int read(char[] cbuf, int off, int len) throws IOException { 110 if (closed) 111 failWithIOE("reader is closed"); 112 return 1; 113 } 114 @Override close()115 public void close() throws IOException { 116 if (!closed) { 117 closed = true; 118 throw new IOException("close failed"); 119 } 120 } 121 } 122 123 static class FailingCloseWriter extends Writer { 124 boolean closed; 125 @Override write(char[] cbuf, int off, int len)126 public void write(char[] cbuf, int off, int len) throws IOException { 127 if (closed) 128 failWithIOE("writer is closed"); 129 } 130 @Override flush()131 public void flush() throws IOException { 132 if (closed) 133 failWithIOE("writer is closed"); 134 } 135 @Override close()136 public void close() throws IOException { 137 if (!closed) { 138 closed = true; 139 throw new IOException("close failed"); 140 } 141 } 142 } 143 144 static class FailingFlushWriter extends Writer { 145 boolean closed; 146 @Override write(char[] cbuf, int off, int len)147 public void write(char[] cbuf, int off, int len) throws IOException { 148 if (closed) 149 failWithIOE("writer is closed"); 150 } 151 @Override flush()152 public void flush() throws IOException { 153 if (closed) { 154 failWithIOE("writer is closed"); 155 } else { 156 throw new IOException("flush failed"); 157 } 158 } 159 @Override close()160 public void close() throws IOException { 161 if (!closed) { 162 closed = true; 163 throw new IOException("close failed"); 164 } 165 } 166 } 167 testFailingClose(InputStream in)168 static InputStream testFailingClose(InputStream in) throws IOException { 169 System.out.println(in.getClass()); 170 in.read(new byte[100]); 171 try { 172 in.close(); 173 fail("close did not fail"); 174 } catch (IOException expected) { } 175 try { 176 in.read(new byte[100]); 177 fail("read did not fail"); 178 } catch (IOException expected) { } 179 return in; 180 } 181 testFailingClose(OutputStream out)182 static OutputStream testFailingClose(OutputStream out) throws IOException { 183 System.out.println(out.getClass()); 184 out.write(1); 185 try { 186 out.close(); 187 fail("close did not fail"); 188 } catch (IOException expected) { } 189 try { 190 out.write(1); 191 if (!(out instanceof BufferedOutputStream)) 192 fail("write did not fail"); 193 } catch (IOException expected) { } 194 return out; 195 } 196 testFailingFlush(OutputStream out)197 static OutputStream testFailingFlush(OutputStream out) throws IOException { 198 System.out.println(out.getClass()); 199 out.write(1); 200 try { 201 out.flush(); 202 fail("flush did not fail"); 203 } catch (IOException expected) { } 204 if (out instanceof BufferedOutputStream) { 205 out.write(1); 206 try { 207 out.close(); 208 fail("close did not fail"); 209 } catch (IOException expected) { } 210 } 211 return out; 212 } 213 closeAgain(InputStream in)214 static void closeAgain(InputStream in) throws IOException { 215 // assert the given stream should already be closed. 216 try { 217 in.close(); 218 } catch (IOException expected) { 219 fail("unexpected IOException from subsequent close"); 220 } 221 } closeAgain(OutputStream out)222 static void closeAgain(OutputStream out) throws IOException { 223 // assert the given stream should already be closed. 224 try { 225 out.close(); 226 } catch (IOException expected) { 227 fail("unexpected IOException from subsequent close"); 228 } 229 } 230 testFailingClose(Reader r)231 static Reader testFailingClose(Reader r) throws IOException { 232 System.out.println(r.getClass()); 233 r.read(new char[100]); 234 try { 235 r.close(); 236 fail("close did not fail"); 237 } catch (IOException expected) { } 238 try { 239 r.read(new char[100]); 240 fail("read did not fail"); 241 } catch (IOException expected) { } 242 return r; 243 } 244 testFailingClose(Writer w)245 static Writer testFailingClose(Writer w) throws IOException { 246 System.out.println(w.getClass()); 247 w.write("message"); 248 try { 249 w.close(); 250 fail("close did not fail"); 251 } catch (IOException expected) { } 252 try { 253 w.write("another message"); 254 fail("write did not fail"); 255 } catch (IOException expected) { } 256 return w; 257 } 258 testFailingFlush(Writer w)259 static Writer testFailingFlush(Writer w) throws IOException { 260 System.out.println(w.getClass()); 261 w.write("message"); 262 try { 263 w.flush(); 264 fail("flush did not fail"); 265 } catch (IOException expected) { } 266 if (w instanceof BufferedWriter) { 267 // assume this message will be buffered 268 w.write("another message"); 269 try { 270 w.close(); 271 fail("close did not fail"); 272 } catch (IOException expected) { } 273 } 274 return w; 275 } 276 closeAgain(Reader r)277 static Reader closeAgain(Reader r) throws IOException { 278 // assert the given stream should already be closed. 279 try { 280 r.close(); 281 } catch (IOException expected) { 282 fail("unexpected IOException from subsequent close"); 283 } 284 return r; 285 } closeAgain(Writer w)286 static Writer closeAgain(Writer w) throws IOException { 287 // assert the given stream should already be closed. 288 try { 289 w.close(); 290 } catch (IOException expected) { 291 fail("unexpected IOException from subsequent close"); 292 } 293 return w; 294 } 295 main(String[] args)296 public static void main(String[] args) throws IOException { 297 298 closeAgain(testFailingClose(new BufferedInputStream(new FailingCloseInputStream()))); 299 closeAgain(testFailingClose(new BufferedOutputStream(new FailingCloseOutputStream()))); 300 301 closeAgain(testFailingClose(new BufferedReader(new FailingCloseReader()))); 302 closeAgain(testFailingClose(new BufferedWriter(new FailingCloseWriter()))); 303 304 closeAgain(testFailingFlush(new BufferedOutputStream(new FailingFlushOutputStream()))); 305 closeAgain(testFailingFlush(new BufferedWriter(new FailingFlushWriter()))); 306 307 if (failed > 0) 308 throw new RuntimeException(failed + " test(s) failed - see log for details"); 309 } 310 } 311