ConcatClosingInputStream extends InputStream { @Override public void close() throws IOException { if (closed) return; IOException ioException = tryClose(current); while (streams.hasNext()) { IOException exception = tryClose(streams.next()); ioException = asSuppressedOf(ioException, exception); } closed = true; if (ioException != null) throw ioException; } ConcatClosingInputStream(Iterator<InputStream> streams); @Override int read(); @Override void close();  }
@Test public void testCloseDoesNotThrowForEmptyIterator() throws Exception { ImmutableList<InputStream> inputStreams = ImmutableList.of(); ConcatClosingInputStream concatClosingInputStream = new ConcatClosingInputStream(inputStreams.iterator()); concatClosingInputStream.close(); }
@Test public void testCloseClosesUnderlyingStreamForASingle() throws Exception { InputStream a = mock(InputStream.class); ImmutableList<InputStream> inputStreams = ImmutableList.of(a); ConcatClosingInputStream concatClosingInputStream = new ConcatClosingInputStream(inputStreams.iterator()); concatClosingInputStream.close(); verify(a).close(); }
@Test public void testCloseClosesUnderlyingStreams() throws Exception { InputStream a = mock(InputStream.class); InputStream b = mock(InputStream.class); InputStream c = mock(InputStream.class); ImmutableList<InputStream> inputStreams = ImmutableList.of(a, b, c); ConcatClosingInputStream concatClosingInputStream = new ConcatClosingInputStream(inputStreams.iterator()); concatClosingInputStream.close(); verify(a).close(); verify(b).close(); verify(c).close(); }
@Test public void testReportingFirstExceptionAndSuppressingLaterOnClose() throws Exception { IOException closingException = new IOException("stream close exception"); IOException closingException2 = new IOException("stream close exception for stream c"); IOException closingException3 = new IOException("stream close exception for stream d"); InputStream a = mock(InputStream.class); InputStream b = mock(InputStream.class); doThrow(closingException).when(b).close(); InputStream c = mock(InputStream.class); doThrow(closingException2).when(c).close(); InputStream d = mock(InputStream.class); doThrow(closingException3).when(d).close(); ImmutableList<InputStream> inputStreams = ImmutableList.of(a, b, c, d); ConcatClosingInputStream concatClosingInputStream = new ConcatClosingInputStream(inputStreams.iterator()); try { concatClosingInputStream.close(); } catch (IOException e) { assertSame(closingException, e); assertThat(e.getSuppressed(), is(arrayContaining((Throwable) closingException2, closingException3))); } verify(a).close(); verify(b).close(); verify(c).close(); verify(d).close(); verifyNoMoreInteractions(a, b, c, d); }