1 /*
   2  * Copyright (c) 2015, 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 import java.io.BufferedOutputStream;
  24 import java.io.IOException;
  25 import java.io.OutputStream;
  26 
  27 /*
  28  * @test
  29  * @bug 8042377
  30  * @summary Ensure suppressed exceptions are properly handled in close()
  31  */
  32 public class SuppressedException {
  33     private static final String CLOSE_MESSAGE = "Close exception";
  34     private static final String FLUSH_MESSAGE = "Flush exception";
  35     private static final String SAME_MESSAGE = "Same exception";
  36 
  37     public static void main(String[] args) throws java.io.IOException {
  38         SuppressedException test = new SuppressedException();
  39         test.test();
  40     }
  41 
  42     private void test() {
  43         int failures = 0;
  44         BufferedOutputStream buf;
  45 
  46         try {
  47             buf = new BufferedOutputStream(new OutputStreamFailsWithException());
  48             buf.close();
  49             System.err.println("\nNo IOException thrown for same exception");
  50             failures++;
  51         } catch (IOException expected) {
  52             if (!expected.getMessage().equals(SAME_MESSAGE)) {
  53                 System.err.println("\nIOException with unexpected message thrown");
  54                 expected.printStackTrace();
  55                 failures++;
  56             }
  57         } catch (IllegalArgumentException unexpected) {
  58             System.err.println("\nUnexpected IllegalArgumentException thrown");
  59             unexpected.printStackTrace();
  60             failures++;
  61         }
  62 
  63         try {
  64             buf = new BufferedOutputStream(
  65                 new OutputStreamFailsWithException(false, false));
  66             buf.close();
  67         } catch (IOException e) {
  68             System.err.println("\nUnexpected IOException thrown");
  69             e.printStackTrace();
  70             failures++;
  71         }
  72 
  73         try {
  74             buf = new BufferedOutputStream(
  75                 new OutputStreamFailsWithException(true, false));
  76             buf.close();
  77         } catch (IOException e) {
  78             if (!e.getMessage().equals(CLOSE_MESSAGE)) {
  79                 System.err.println("\nIOException with unexpected message thrown");
  80                 e.printStackTrace();
  81                 failures++;
  82             }
  83         }
  84 
  85         try {
  86             buf = new BufferedOutputStream(
  87                 new OutputStreamFailsWithException(false, true));
  88             buf.close();
  89         } catch (IOException e) {
  90             if (!e.getMessage().equals(FLUSH_MESSAGE)) {
  91                 System.err.println("\nIOException with unexpected message thrown");
  92                 e.printStackTrace();
  93                 failures++;
  94             }
  95         }
  96 
  97         try {
  98             buf = new BufferedOutputStream(
  99                 new OutputStreamFailsWithException(true, true));
 100             buf.close();
 101         } catch (IOException e) {
 102             if (!e.getMessage().equals(CLOSE_MESSAGE)) {
 103                 System.err.println("\nIOException with unexpected message thrown");
 104                 e.printStackTrace();
 105                 failures++;
 106             }
 107 
 108             Throwable[] suppressed = e.getSuppressed();
 109             if (suppressed == null) {
 110                 System.err.println("\nExpected suppressed exception not present");
 111                 e.printStackTrace();
 112                 failures++;
 113             } else if (suppressed.length != 1) {
 114                 System.err.println("\nUnexpected number of suppressed exceptions");
 115                 e.printStackTrace();
 116                 failures++;
 117             } else if (!(suppressed[0] instanceof IOException)) {
 118                 System.err.println("\nSuppressed exception is not an IOException");
 119                 e.printStackTrace();
 120                 failures++;
 121             } else if (!suppressed[0].getMessage().equals(FLUSH_MESSAGE)) {
 122                 System.err.println("\nIOException with unexpected message thrown");
 123                 e.printStackTrace();
 124                 failures++;
 125             }
 126         }
 127 
 128         if (failures > 0) {
 129             throw new RuntimeException("Test failed with " + failures + " errors");
 130         } else {
 131             System.out.println("Test succeeded.");
 132         }
 133     }
 134 
 135     class OutputStreamFailsWithException extends OutputStream {
 136         private final IOException sameException = new IOException(SAME_MESSAGE);
 137 
 138         private final Boolean throwSeparateCloseException;
 139         private final Boolean throwSeparateFlushException;
 140 
 141         OutputStreamFailsWithException() {
 142             throwSeparateCloseException = null;
 143             throwSeparateFlushException = null;
 144         }
 145 
 146         OutputStreamFailsWithException(boolean throwCloseException,
 147                 boolean throwFlushException) {
 148             throwSeparateCloseException = throwCloseException;
 149             throwSeparateFlushException = throwFlushException;
 150         }
 151 
 152         @Override
 153         public void write(int i) throws IOException {
 154             throw new UnsupportedOperationException("");
 155         }
 156 
 157         @Override
 158         public void flush() throws IOException {
 159             System.out.println("flush()");
 160             if (throwSeparateFlushException == null) {
 161                 throw sameException;
 162             } else if (throwSeparateFlushException) {
 163                 throw new IOException(FLUSH_MESSAGE);
 164             }
 165         }
 166 
 167         @Override
 168         public void close() throws IOException {
 169             System.out.println("close()");
 170             if (throwSeparateCloseException == null) {
 171                 throw sameException;
 172             } else if (throwSeparateCloseException) {
 173                 throw new IOException(CLOSE_MESSAGE);
 174             }
 175         }
 176     }
 177 }