harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jessewil...@apache.org
Subject svn commit: r835972 - in /harmony/enhanced/classlib/trunk: modules/luni/make/ modules/luni/src/main/java/java/io/ modules/luni/src/main/java/org/apache/harmony/luni/util/ modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/ support/s...
Date Fri, 13 Nov 2009 20:08:09 GMT
Author: jessewilson
Date: Fri Nov 13 20:08:08 2009
New Revision: 835972

URL: http://svn.apache.org/viewvc?rev=835972&view=rev
Log:
Fixing the bugs demonstrated by WriterTesterTest. Only ObjectOutputStream failures are outstanding;
these are suppressed in the test case.

This commit adds SneakyThrow, which is a dangerous class that you should not use! It is used
to give Harmony the best behaviour when dealing with failures during stream flush and close.
Read the Javadoc for full detalis.

This commit makes behaviour changes to BufferedWriter, FilterOutputStream, and BufferedOutputStream.
These streams now throw as required after they are closed, and throw the correct exception
when closing fails.

Added:
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/SneakyThrow.java
  (with props)
Modified:
    harmony/enhanced/classlib/trunk/modules/luni/make/exclude.common
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedOutputStream.java
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedWriter.java
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/FilterOutputStream.java
    harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedOutputStreamTest.java
    harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java
    harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/WriterTesterTest.java
    harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharSinkTester.java
    harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharWrapperTester.java
    harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java
    harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java

Modified: harmony/enhanced/classlib/trunk/modules/luni/make/exclude.common
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/make/exclude.common?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/make/exclude.common (original)
+++ harmony/enhanced/classlib/trunk/modules/luni/make/exclude.common Fri Nov 13 20:08:08 2009
@@ -1,3 +1 @@
 org/apache/harmony/luni/tests/java/net/ExcludedProxyTest.java
-org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java
-org/apache/harmony/luni/tests/java/io/WriterTesterTest.java

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedOutputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedOutputStream.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedOutputStream.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedOutputStream.java
Fri Nov 13 20:08:08 2009
@@ -88,6 +88,10 @@
      */
     @Override
     public synchronized void flush() throws IOException {
+        if (buf == null) {
+            throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+        }
+
         flushInternal();
         out.flush();
     }
@@ -120,12 +124,17 @@
     @Override
     public synchronized void write(byte[] buffer, int offset, int length)
             throws IOException {
+        byte[] internalBuffer = buf;
+        if (internalBuffer == null) {
+            throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+        }
+
         if (buffer == null) {
             // K0047=buffer is null
             throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
         }
         
-        if (length >= buf.length) {
+        if (length >= internalBuffer.length) {
             flushInternal();
             out.write(buffer, offset, length);
             return;
@@ -142,15 +151,27 @@
         }
 
         // flush the internal buffer first if we have not enough space left
-        if (length >= (buf.length - count)) {
+        if (length >= (internalBuffer.length - count)) {
             flushInternal();
         }
 
-        // the length is always less than (buf.length - count) here so arraycopy is safe
-        System.arraycopy(buffer, offset, buf, count, length);
+        // the length is always less than (internalBuffer.length - count) here so arraycopy
is safe
+        System.arraycopy(buffer, offset, internalBuffer, count, length);
         count += length;
     }
 
+    @Override public synchronized void close() throws IOException {
+        if (buf == null) {
+            return;
+        }
+        
+        try {
+            super.close();
+        } finally {
+            buf = null;
+        }
+    }
+
     /**
      * Writes one byte to this stream. Only the low order byte of the integer
      * {@code oneByte} is written. If there is room in the buffer, the byte is
@@ -165,11 +186,16 @@
      */
     @Override
     public synchronized void write(int oneByte) throws IOException {
-        if (count == buf.length) {
-            out.write(buf, 0, count);
+        byte[] internalBuffer = buf;
+        if (internalBuffer == null) {
+            throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+        }
+
+        if (count == internalBuffer.length) {
+            out.write(internalBuffer, 0, count);
             count = 0;
         }
-        buf[count++] = (byte) oneByte;
+        internalBuffer[count++] = (byte) oneByte;
     }
 
     /**
@@ -178,7 +204,7 @@
     private void flushInternal() throws IOException {
         if (count > 0) {
             out.write(buf, 0, count);
+            count = 0;
         }
-        count = 0;
     }
 }

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedWriter.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedWriter.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedWriter.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/BufferedWriter.java
Fri Nov 13 20:08:08 2009
@@ -21,6 +21,7 @@
 
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
+import org.apache.harmony.luni.util.SneakyThrow;
 
 /**
  * Wraps an existing {@link Writer} and <em>buffers</em> the output. Expensive
@@ -95,11 +96,29 @@
     @Override
     public void close() throws IOException {
         synchronized (lock) {
-            if (!isClosed()) {
+            if (isClosed()) {
+                return;
+            }
+
+            Throwable thrown = null;
+            try {
                 flushInternal();
+            } catch (Throwable e) {
+                thrown = e;
+            }
+            buf = null;
+
+            try {
                 out.close();
-                buf = null;
-                out = null;
+            } catch (Throwable e) {
+                if (thrown == null) {
+                    thrown = e;
+                }
+            }
+            out = null;
+
+            if (thrown != null) {
+                SneakyThrow.sneakyThrow(thrown);
             }
         }
     }

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/FilterOutputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/FilterOutputStream.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/FilterOutputStream.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/FilterOutputStream.java
Fri Nov 13 20:08:08 2009
@@ -18,6 +18,7 @@
 package java.io;
 
 import org.apache.harmony.luni.util.Msg;
+import org.apache.harmony.luni.util.SneakyThrow;
 
 /**
  * Wraps an existing {@link OutputStream} and performs some transformation on
@@ -55,27 +56,23 @@
      */
     @Override
     public void close() throws IOException {
-        Exception thrown = null;
+        Throwable thrown = null;
         try {
             flush();
-        } catch (Exception e) {
+        } catch (Throwable e) {
             thrown = e;
         }
 
         try {
             out.close();
-        } catch (Exception e) {
-            if (thrown != null) {
+        } catch (Throwable e) {
+            if (thrown == null) {
                 thrown = e;
             }
         }
 
         if (thrown != null) {
-            if (thrown instanceof IOException) {
-                throw (IOException) thrown;
-            } else {
-                throw (RuntimeException) thrown;
-            }
+            SneakyThrow.sneakyThrow(thrown);
         }
     }
 

Added: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/SneakyThrow.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/SneakyThrow.java?rev=835972&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/SneakyThrow.java
(added)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/SneakyThrow.java
Fri Nov 13 20:08:08 2009
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.luni.util;
+
+/**
+ * Exploits a weakness in the runtime to throw an arbitrary throwable without
+ * the traditional declaration. <strong>This is a dangerous API that should be
+ * used with great caution.</strong> Typically this is useful when rethrowing
+ * throwables that are of a known range of types.
+ *
+ * <p>The following code must enumerate several types to rethrow:
+ * <pre>
+ * public void close() throws IOException {
+ *     Throwable thrown = null;
+ *     ...
+ *
+ *     if (thrown != null) {
+ *         if (thrown instanceof IOException) {
+ *             throw (IOException) thrown;
+ *         } else if (thrown instanceof RuntimeException) {
+ *             throw (RuntimeException) thrown;
+ *         } else if (thrown instanceof Error) {
+ *             throw (Error) thrown;
+ *         } else {
+ *             throw new AssertionError();
+ *         }
+ *     }
+ * }</pre>
+ * With SneakyThrow, rethrowing is easier:
+ * <pre>
+ * public void close() throws IOException {
+ *     Throwable thrown = null;
+ *     ...
+ *
+ *     if (thrown != null) {
+ *         SneakyThrow.sneakyThrow(thrown);
+ *     }
+ * }</pre>
+ */
+public final class SneakyThrow {
+    private SneakyThrow() {}
+
+    public static void sneakyThrow(Throwable t) {
+        SneakyThrow.<Error>sneakyThrow2(t);
+    }
+
+    /**
+     * Exploits unsafety to throw an exception that the compiler wouldn't permit
+     * but that the runtime doesn't check. See Java Puzzlers #43.
+     */
+    @SuppressWarnings("unchecked")
+    private static <T extends Throwable> void sneakyThrow2(Throwable t) throws T {
+        throw (T) t;
+    }
+}

Propchange: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/org/apache/harmony/luni/util/SneakyThrow.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedOutputStreamTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedOutputStreamTest.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedOutputStreamTest.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/BufferedOutputStreamTest.java
Fri Nov 13 20:08:08 2009
@@ -328,9 +328,9 @@
 
         try {
             bos.write(byteArray, -1, -1);
-            fail("should throw ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException e) {
-            // expected
+            fail();
+        } catch (Exception e) {
+            // expected IOException. RI throws IndexOutOfBoundsException
         }
     }
 
@@ -663,11 +663,6 @@
         buffos.flush();
 
         buffos.close();
-
-        buffos.write(Integer.MIN_VALUE);
-        buffos.write(Integer.MAX_VALUE);
-        buffos.write(buffer, 0, 10);
-        buffos.flush();
     }
 
     public void test_write_Scenario1() throws IOException {
@@ -751,8 +746,6 @@
             assertEquals(buffer2[i], byteArrayis.read());
         }
 
-        buffos.close();
-
         byte[] buffer3 = new byte[] { 'e', 'f', 'g', 'h', 'i' };
         buffos.write(buffer3, 0, 5);
         byteArrayis = new ByteArrayInputStream(byteArrayos.toByteArray());
@@ -778,6 +771,8 @@
         byteArrayis = new ByteArrayInputStream(byteArrayos.toByteArray());
         assertEquals("Bytes not written after flush", 21, byteArrayis
                 .available());
+
+        buffos.close();
     }
 
     public void test_write_Scenario3() throws IOException {

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/OutputStreamTesterTest.java
Fri Nov 13 20:08:08 2009
@@ -54,8 +54,8 @@
         // sink tests
         suite.addTest(new FileOutputStreamSinkTester(true).createTests());
         suite.addTest(new FileOutputStreamSinkTester(false).createTests());
-        suite.addTest(new ByteArrayOutputStreamSinkTester(0).createTests());
-        suite.addTest(new ByteArrayOutputStreamSinkTester(4).createTests());
+        suite.addTest(new ByteArrayOutputStreamSinkTester(0).setThrowsExceptions(false).createTests());
+        suite.addTest(new ByteArrayOutputStreamSinkTester(4).setThrowsExceptions(false).createTests());
         suite.addTest(new PipedOutputStreamSinkTester().createTests());
 
         // wrapper tests
@@ -64,7 +64,8 @@
         suite.addTest(new BufferedOutputStreamTester(1024).createTests());
         suite.addTest(new FilterOutputStreamTester().createTests());
         suite.addTest(new DataOutputStreamTester().createTests());
-        suite.addTest(new ObjectOutputStreamTester().createTests());
+        // fails wrapperTestFlushThrowsViaClose() and sinkTestWriteAfterClose():
+        // suite.addTest(new ObjectOutputStreamTester().createTests());
         suite.addTest(new PrintStreamTester().setThrowsExceptions(false).createTests());
 
         return suite;

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/WriterTesterTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/WriterTesterTest.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/WriterTesterTest.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/io/WriterTesterTest.java
Fri Nov 13 20:08:08 2009
@@ -52,8 +52,8 @@
         // sink tests
         suite.addTest(new FileWriterCharSinkTester(true).createTests());
         suite.addTest(new FileWriterCharSinkTester(false).createTests());
-        suite.addTest(new CharArrayWriterCharSinkTester().createTests());
-        suite.addTest(new StringWriterCharSinkTester().createTests());
+        suite.addTest(new CharArrayWriterCharSinkTester().setThrowsExceptions(false).createTests());
+        suite.addTest(new StringWriterCharSinkTester().setThrowsExceptions(false).createTests());
         suite.addTest(new PipedWriterCharSinkTester().createTests());
 
         // wrapper tests

Modified: harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharSinkTester.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharSinkTester.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharSinkTester.java
(original)
+++ harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharSinkTester.java
Fri Nov 13 20:08:08 2009
@@ -67,6 +67,8 @@
 
         if (throwsExceptions) {
             result.addTest(new SinkTestCase("sinkTestWriteAfterClose"));
+        } else {
+            result.addTest(new SinkTestCase("sinkTestWriteAfterCloseSuppressed"));
         }
 
         return result;
@@ -184,6 +186,13 @@
             Assert.assertArrayEquals(expectedChars, getChars());
         }
 
+        public void sinkTestWriteAfterCloseSuppressed() throws Exception {
+            Writer out = create();
+            out.write("EF".toCharArray());
+            out.close();
+            out.write("GCDE".toCharArray()); // no exception expected!
+        }
+
         // adding a new test? Don't forget to update createTests().
 
         @Override public String getName() {

Modified: harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharWrapperTester.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharWrapperTester.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharWrapperTester.java
(original)
+++ harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/CharWrapperTester.java
Fri Nov 13 20:08:08 2009
@@ -21,7 +21,6 @@
 import junit.framework.TestSuite;
 
 import java.io.IOException;
-import java.io.StringWriter;
 import java.io.Writer;
 
 /**
@@ -63,9 +62,11 @@
         if (throwsExceptions) {
             result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaFlush"));
             result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaClose"));
+            result.addTest(new WrapperTestCase("wrapperTestCloseThrows"));
         } else {
             result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaFlushSuppressed"));
             result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaCloseSuppressed"));
+            result.addTest(new WrapperTestCase("wrapperTestCloseThrowsSuppressed"));
         }
 
         return result;
@@ -76,15 +77,15 @@
     }
 
     private class WrapperSinkTester extends CharSinkTester {
-        private StringWriter delegate;
+        private ClosableStringWriter delegate;
 
         @Override public Writer create() throws Exception {
-            delegate = new StringWriter();
+            delegate = new ClosableStringWriter();
             return CharWrapperTester.this.create(delegate);
         }
 
         @Override public char[] getChars() throws Exception {
-            return CharWrapperTester.this.decode(delegate.toString().toCharArray());
+            return decode(delegate.buffer.toString().toCharArray());
         }
 
         @Override public String toString() {
@@ -98,6 +99,10 @@
             super(name);
         }
 
+        @Override public String getName() {
+            return CharWrapperTester.this.toString() + ":" + super.getName();
+        }
+
         public void wrapperTestFlushThrowsViaFlushSuppressed() throws Exception {
             FailOnFlushWriter delegate = new FailOnFlushWriter();
             Writer o = create(delegate);
@@ -154,27 +159,83 @@
             }
         }
 
+        public void wrapperTestCloseThrows() throws Exception {
+            FailOnCloseWriter delegate = new FailOnCloseWriter();
+            Writer o = create(delegate);
+            try {
+                o.close();
+                assertTrue(delegate.closed);
+                fail("close exception ignored");
+            } catch (IOException expected) {
+                assertEquals("Close failed" , expected.getMessage());
+            }
+        }
+
+        public void wrapperTestCloseThrowsSuppressed() throws Exception {
+            FailOnCloseWriter delegate = new FailOnCloseWriter();
+            Writer o = create(delegate);
+            o.close();
+            assertTrue(delegate.closed);
+        }
+
         // adding a new test? Don't forget to update createTests().
+    }
 
-        @Override public String getName() {
-            return CharWrapperTester.this.toString() + ":" + super.getName();
+    /**
+     * A custom Writer that respects the closed state. The built-in StringWriter
+     * doesn't respect close(), which makes testing wrapped streams difficult.
+     */
+    private static class ClosableStringWriter extends Writer {
+        private final StringBuilder buffer = new StringBuilder();
+        private boolean closed = false;
+
+        @Override public void close() throws IOException {
+            closed = true;
         }
 
-        private class FailOnFlushWriter extends Writer {
-            boolean flushed = false;
+        @Override public void flush() throws IOException {}
 
-            @Override public void write(char[] buf, int offset, int count) throws IOException
{}
+        @Override public void write(char[] buf, int offset, int count) throws IOException
{
+            if (closed) {
+                throw new IOException();
+            }
+            buffer.append(buf, offset, count);
+        }
+    }
 
-            @Override public void close() throws IOException {
-                flush();
+    private static class FailOnFlushWriter extends Writer {
+        boolean flushed = false;
+        boolean closed = false;
+
+        @Override public void write(char[] buf, int offset, int count) throws IOException
{
+            if (closed) {
+                throw new IOException("Already closed");
             }
+        }
 
-            @Override public void flush() throws IOException {
-                if (!flushed) {
-                    flushed = true;
-                    throw new IOException("Flush failed");
-                }
+        @Override public void close() throws IOException {
+            closed = true;
+            flush();
+        }
+
+        @Override public void flush() throws IOException {
+            if (!flushed) {
+                flushed = true;
+                throw new IOException("Flush failed");
             }
         }
     }
+
+    private static class FailOnCloseWriter extends Writer {
+        boolean closed = false;
+
+        @Override public void flush() throws IOException {}
+
+        @Override public void write(char[] buf, int offset, int count) throws IOException
{}
+
+        @Override public void close() throws IOException {
+            closed = true;
+            throw new IOException("Close failed");
+        }
+    }
 }
\ No newline at end of file

Modified: harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java
(original)
+++ harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/SinkTester.java
Fri Nov 13 20:08:08 2009
@@ -68,6 +68,8 @@
 
         if (throwsExceptions) {
             result.addTest(new SinkTestCase("sinkTestWriteAfterClose"));
+        } else {
+            result.addTest(new SinkTestCase("sinkTestWriteAfterCloseSuppressed"));
         }
 
         return result;
@@ -196,6 +198,13 @@
             Assert.assertArrayEquals(expectedBytes, getBytes());
         }
 
+        public void sinkTestWriteAfterCloseSuppressed() throws Exception {
+            OutputStream out = create();
+            out.write(new byte[] { 5, 6 });
+            out.close();
+            out.write(new byte[] { 7, 3, 4, 5 }); // no exception expected!
+        }
+
         // adding a new test? Don't forget to update createTests().
 
         @Override public String getName() {

Modified: harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java?rev=835972&r1=835971&r2=835972&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java
(original)
+++ harmony/enhanced/classlib/trunk/support/src/test/java/org/apache/harmony/testframework/WrapperTester.java
Fri Nov 13 20:08:08 2009
@@ -63,9 +63,11 @@
         if (throwsExceptions) {
             result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaFlush"));
             result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaClose"));
+            result.addTest(new WrapperTestCase("wrapperTestCloseThrows"));
         } else {
             result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaFlushSuppressed"));
             result.addTest(new WrapperTestCase("wrapperTestFlushThrowsViaCloseSuppressed"));
+            result.addTest(new WrapperTestCase("wrapperTestCloseThrowsSuppressed"));
         }
 
         return result;
@@ -76,15 +78,15 @@
     }
 
     private class WrapperSinkTester extends SinkTester {
-        private ByteArrayOutputStream delegate;
+        private ClosableByteArrayOutputStream delegate;
 
         @Override public OutputStream create() throws Exception {
-            delegate = new ByteArrayOutputStream();
+            delegate = new ClosableByteArrayOutputStream();
             return WrapperTester.this.create(delegate);
         }
 
         @Override public byte[] getBytes() throws Exception {
-            return WrapperTester.this.decode(delegate.toByteArray());
+            return WrapperTester.this.decode(delegate.bytesOut.toByteArray());
         }
 
         @Override public String toString() {
@@ -98,6 +100,10 @@
             super(name);
         }
 
+        @Override public String getName() {
+            return WrapperTester.this.toString() + ":" + super.getName();
+        }
+
         public void wrapperTestFlushThrowsViaFlushSuppressed() throws Exception {
             FailOnFlushOutputStream delegate = new FailOnFlushOutputStream();
             OutputStream o = create(delegate);
@@ -154,27 +160,73 @@
             }
         }
 
+        public void wrapperTestCloseThrows() throws Exception {
+            FailOnCloseOutputStream delegate = new FailOnCloseOutputStream();
+            OutputStream o = create(delegate);
+            try {
+                o.close();
+                assertTrue(delegate.closed);
+                fail("close exception ignored");
+            } catch (IOException expected) {
+                assertEquals("Close failed" , expected.getMessage());
+            }
+        }
+
+        public void wrapperTestCloseThrowsSuppressed() throws Exception {
+            FailOnCloseOutputStream delegate = new FailOnCloseOutputStream();
+            OutputStream o = create(delegate);
+            o.close();
+            assertTrue(delegate.closed);
+        }
+
         // adding a new test? Don't forget to update createTests().
+    }
 
-        @Override public String getName() {
-            return WrapperTester.this.toString() + ":" + super.getName();
+    private static class ClosableByteArrayOutputStream extends OutputStream {
+        private final ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+        private boolean closed = false;
+
+        @Override public void close() throws IOException {
+            closed = true;
         }
 
-        private class FailOnFlushOutputStream extends ByteArrayOutputStream {
-            boolean flushed = false;
+        @Override public void write(int oneByte) throws IOException {
+            if (closed) {
+                throw new IOException();
+            }
+            bytesOut.write(oneByte);
+        }
+    }
 
-            @Override public void close() throws IOException {
-                flush();
-                super.close();
+    private static class FailOnFlushOutputStream extends OutputStream {
+        boolean flushed = false;
+        boolean closed = false;
+
+        @Override public void write(int oneByte) throws IOException {
+            if (closed) {
+                throw new IOException("Already closed");
             }
+        }
+
+        @Override public void close() throws IOException {
+            closed = true;
+            flush();
+        }
 
-            @Override public void flush() throws IOException {
-                if (!flushed) {
-                    flushed = true;
-                    throw new IOException("Flush failed");
-                }
-                super.flush();
+        @Override public void flush() throws IOException {
+            if (!flushed) {
+                flushed = true;
+                throw new IOException("Flush failed");
             }
         }
     }
+
+    private static class FailOnCloseOutputStream extends ByteArrayOutputStream {
+        boolean closed = false;
+
+        @Override public void close() throws IOException {
+            closed = true;
+            throw new IOException("Close failed");
+        }
+    }
 }



Mime
View raw message