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 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 37 static void fail(String msg) { 38 System.err.println("FAIL: " + msg); 39 failed++; 40 } 41 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 50 public int read()throws IOException { 51 if (closed) 52 failWithIOE("input stream is closed"); 53 return 1; 54 } 55 @Override 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 67 public void write(int b) throws IOException { 68 if (closed) 69 failWithIOE("output stream is closed"); 70 } 71 @Override 72 public void flush() throws IOException { 73 if (closed) 74 failWithIOE("output stream is closed"); 75 } 76 @Override 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 88 public void write(int b) throws IOException { 89 if (closed) 90 failWithIOE("output stream is closed"); 91 } 92 @Override 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 101 public void close() throws IOException { 102 closed = true; 103 } 104 } 105 106 static class FailingCloseReader extends Reader { 107 boolean closed; 108 @Override 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 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 126 public void write(char[] cbuf, int off, int len) throws IOException { 127 if (closed) 128 failWithIOE("writer is closed"); 129 } 130 @Override 131 public void flush() throws IOException { 132 if (closed) 133 failWithIOE("writer is closed"); 134 } 135 @Override 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 147 public void write(char[] cbuf, int off, int len) throws IOException { 148 if (closed) 149 failWithIOE("writer is closed"); 150 } 151 @Override 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 160 public void close() throws IOException { 161 if (!closed) { 162 closed = true; 163 throw new IOException("close failed"); 164 } 165 } 166 } 167 168 static void 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 } 180 181 static void testFailingClose(OutputStream out) throws IOException { 182 System.out.println(out.getClass()); 183 out.write(1); 184 try { 185 out.close(); 186 fail("close did not fail"); 187 } catch (IOException expected) { } 188 try { 189 out.write(1); 190 if (!(out instanceof BufferedOutputStream)) 191 fail("write did not fail"); 192 } catch (IOException expected) { } 193 } 194 195 static void testFailingFlush(OutputStream out) throws IOException { 196 System.out.println(out.getClass()); 197 out.write(1); 198 try { 199 out.flush(); 200 fail("flush did not fail"); 201 } catch (IOException expected) { } 202 if (out instanceof BufferedOutputStream) { 203 out.write(1); 204 try { 205 out.close(); 206 fail("close did not fail"); 207 } catch (IOException expected) { } 208 } 209 } 210 211 static void testFailingClose(Reader r) throws IOException { 212 System.out.println(r.getClass()); 213 r.read(new char[100]); 214 try { 215 r.close(); 216 fail("close did not fail"); 217 } catch (IOException expected) { } 218 try { 219 r.read(new char[100]); 220 fail("read did not fail"); 221 } catch (IOException expected) { } 222 } 223 224 static void testFailingClose(Writer w) throws IOException { 225 System.out.println(w.getClass()); 226 w.write("message"); 227 try { 228 w.close(); 229 fail("close did not fail"); 230 } catch (IOException expected) { } 231 try { 232 w.write("another message"); 233 fail("write did not fail"); 234 } catch (IOException expected) { } 235 } 236 237 static void testFailingFlush(Writer w) throws IOException { 238 System.out.println(w.getClass()); 239 w.write("message"); 240 try { 241 w.flush(); 242 fail("flush did not fail"); 243 } catch (IOException expected) { } 244 if (w instanceof BufferedWriter) { 245 // assume this message will be buffered 246 w.write("another message"); 247 try { 248 w.close(); 249 fail("close did not fail"); 250 } catch (IOException expected) { } 251 } 252 } 253 254 public static void main(String[] args) throws IOException { 255 256 testFailingClose(new BufferedInputStream(new FailingCloseInputStream())); 257 testFailingClose(new BufferedOutputStream(new FailingCloseOutputStream())); 258 259 testFailingClose(new BufferedReader(new FailingCloseReader())); 260 testFailingClose(new BufferedWriter(new FailingCloseWriter())); 261 262 testFailingFlush(new BufferedOutputStream(new FailingFlushOutputStream())); 263 testFailingFlush(new BufferedWriter(new FailingFlushWriter())); 264 265 if (failed > 0) 266 throw new RuntimeException(failed + " test(s) failed - see log for details"); 267 } 268 }