diff --git a/guava-tests/test/com/google/common/io/BaseEncodingTest.java b/guava-tests/test/com/google/common/io/BaseEncodingTest.java index 82c1b4e1994c..15cf4e11e1ad 100644 --- a/guava-tests/test/com/google/common/io/BaseEncodingTest.java +++ b/guava-tests/test/com/google/common/io/BaseEncodingTest.java @@ -572,6 +572,34 @@ private static void testStreamingDecodes(BaseEncoding encoding, String encoded, } } + @GwtIncompatible // Writer,OutputStream + public void testEncodingStreamCloseIsIdempotent() throws IOException { + StringWriter writer = new StringWriter(); + OutputStream encodingStream = base64().encodingStream(writer); + encodingStream.write(0); + encodingStream.close(); + assertThat(writer.toString()).isEqualTo("AA=="); + // Closing again should have no effect. + encodingStream.close(); + assertThat(writer.toString()).isEqualTo("AA=="); + } + + @GwtIncompatible // Writer,OutputStream + public void testEncodingStreamWriteAfterClose() throws IOException { + StringWriter writer = new StringWriter(); + OutputStream encodingStream = base64().encodingStream(writer); + encodingStream.close(); + assertThrows(IOException.class, () -> encodingStream.write(0)); + } + + @GwtIncompatible // Writer,OutputStream + public void testEncodingStreamFlushAfterClose() throws IOException { + StringWriter writer = new StringWriter(); + OutputStream encodingStream = base64().encodingStream(writer); + encodingStream.close(); + assertThrows(IOException.class, () -> encodingStream.flush()); + } + public void testToString() { assertThat(base64().toString()).isEqualTo("BaseEncoding.base64().withPadChar('=')"); assertThat(base32Hex().omitPadding().toString()) diff --git a/guava-tests/test/com/google/common/io/ReflectionFreeAssertThrows.java b/guava-tests/test/com/google/common/io/ReflectionFreeAssertThrows.java index 957bfb4902a1..fc391c54f8e7 100644 --- a/guava-tests/test/com/google/common/io/ReflectionFreeAssertThrows.java +++ b/guava-tests/test/com/google/common/io/ReflectionFreeAssertThrows.java @@ -23,6 +23,7 @@ import com.google.common.base.VerifyException; import com.google.common.collect.ImmutableMap; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.charset.UnsupportedCharsetException; import java.util.ConcurrentModificationException; @@ -136,6 +137,7 @@ ImmutableMap, Predicate> exceptions() { .put(ExecutionException.class, e -> e instanceof ExecutionException) .put(IllegalArgumentException.class, e -> e instanceof IllegalArgumentException) .put(IllegalStateException.class, e -> e instanceof IllegalStateException) + .put(IOException.class, e -> e instanceof IOException) .put(IndexOutOfBoundsException.class, e -> e instanceof IndexOutOfBoundsException) .put(NoSuchElementException.class, e -> e instanceof NoSuchElementException) .put(NullPointerException.class, e -> e instanceof NullPointerException) diff --git a/guava/src/com/google/common/io/BaseEncoding.java b/guava/src/com/google/common/io/BaseEncoding.java index a12d7519f55f..6b3f80aef4e5 100644 --- a/guava/src/com/google/common/io/BaseEncoding.java +++ b/guava/src/com/google/common/io/BaseEncoding.java @@ -645,9 +645,13 @@ public OutputStream encodingStream(Writer out) { int bitBuffer = 0; int bitBufferLength = 0; int writtenChars = 0; + boolean closed = false; @Override - public void write(int b) throws IOException { + public synchronized void write(int b) throws IOException { + if (closed) { + throw new IOException("Stream is closed"); + } bitBuffer <<= 8; bitBuffer |= b & 0xFF; bitBufferLength += 8; @@ -660,12 +664,19 @@ public void write(int b) throws IOException { } @Override - public void flush() throws IOException { + public synchronized void flush() throws IOException { + if (closed) { + throw new IOException("Stream is closed"); + } out.flush(); } @Override - public void close() throws IOException { + public synchronized void close() throws IOException { + if (closed) { + return; + } + closed = true; if (bitBufferLength > 0) { int charIndex = (bitBuffer << (alphabet.bitsPerChar - bitBufferLength)) & alphabet.mask; out.write(alphabet.encode(charIndex));