This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-io.git


The following commit(s) were added to refs/heads/master by this push:
     new 87da775  [IO-651] Add DeferredFileOutputStream.toInputStream() #206.
87da775 is described below

commit 87da775d2f0aa9d3382ac30b9dd7e793c3c6f9e5
Author: Gary Gregory <gardgreg...@gmail.com>
AuthorDate: Mon Feb 22 14:58:24 2021 -0500

    [IO-651] Add DeferredFileOutputStream.toInputStream() #206.
    
    - Update @since tag.
    - Sort members.
---
 src/changes/changes.xml                            |   7 +-
 .../io/output/DeferredFileOutputStream.java        | 190 ++++++------
 .../io/output/DeferredFileOutputStreamTest.java    | 340 ++++++++++-----------
 3 files changed, 270 insertions(+), 267 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3cfaf6a..69dc2a2 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -68,7 +68,7 @@ The <action> type attribute can be add,update,fix,remove.
       </action>
       <action issue="IO-597" dev="ggregory" type="fix" due-to="Gary Gregory, 
Arvind, Rob Spoor">
         FileUtils.iterateFiles runs out of memory when executed for a 
directory with large number of files.
-        Re-implement FileUtils' iterateFiles(), iterateFilesAndDirs(), 
listFiles(), listFilesAndDirs() to use NIO 
+        Re-implement FileUtils' iterateFiles(), iterateFilesAndDirs(), 
listFiles(), listFilesAndDirs() to use NIO
         file tree walking instead of IO file listings to avoid memory 
consumption issues on large file trees.
       </action>
       <action dev="ggregory" type="fix" due-to="Gary Gregory">
@@ -193,6 +193,9 @@ The <action> type attribute can be add,update,fix,remove.
       <action dev="ggregory" type="add" due-to="Gary Gregory">
         Add copy(URL, OutputStream).
       </action>
+      <action  issue="IO-651" dev="ggregory" type="add" due-to="jmark109, Gary 
Gregory">
+        Add DeferredFileOutputStream.toInputStream() #206.
+      </action>
       <!-- UPDATES -->
       <action dev="ggregory" type="update" due-to="Dependabot">
         Update junit-jupiter from 5.6.2 to 5.7.0 #153.
@@ -385,7 +388,7 @@ The <action> type attribute can be add,update,fix,remove.
       </action>
       <action type="update" dev="ggregory" due-to="Gary Gregory">
         Update com.github.siom79.japicmp:japicmp-maven-plugin 0.14.3 -> 0.14.4.
-      </action>      
+      </action>
     </release>
     <!-- The release date is the date RC is cut -->
     <release version="2.7" date="2020-05-24" description="Java 8 required.">
diff --git 
a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java 
b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
index d6dac39..a99c01a 100644
--- a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
@@ -87,6 +87,29 @@ public class DeferredFileOutputStream extends 
ThresholdingOutputStream {
     }
 
     /**
+     * Constructs an instance of this class which will trigger an event at the 
specified threshold, and save data either
+     * to a file beyond that point.
+     *
+     * @param threshold The number of bytes at which to trigger an event.
+     * @param outputFile The file to which data is saved beyond the threshold.
+     * @param prefix Prefix to use for the temporary file.
+     * @param suffix Suffix to use for the temporary file.
+     * @param directory Temporary file directory.
+     * @param initialBufferSize The initial size of the in memory buffer.
+     */
+    private DeferredFileOutputStream(final int threshold, final File 
outputFile, final String prefix,
+        final String suffix, final File directory, final int 
initialBufferSize) {
+        super(threshold);
+        this.outputFile = outputFile;
+        this.prefix = prefix;
+        this.suffix = suffix;
+        this.directory = directory;
+
+        memoryOutputStream = new ByteArrayOutputStream(initialBufferSize);
+        currentOutputStream = memoryOutputStream;
+    }
+
+    /**
      * Constructs an instance of this class which will trigger an event at the 
specified threshold, and save data to a
      * file beyond that point.
      *
@@ -105,26 +128,6 @@ public class DeferredFileOutputStream extends 
ThresholdingOutputStream {
 
     /**
      * Constructs an instance of this class which will trigger an event at the 
specified threshold, and save data to a
-     * temporary file beyond that point. The initial buffer size will default 
to 32 bytes which is
-     * ByteArrayOutputStream's default buffer size.
-     *
-     * @param threshold The number of bytes at which to trigger an event.
-     * @param prefix Prefix to use for the temporary file.
-     * @param suffix Suffix to use for the temporary file.
-     * @param directory Temporary file directory.
-     *
-     * @since 1.4
-     */
-    public DeferredFileOutputStream(final int threshold, final String prefix, 
final String suffix,
-        final File directory) {
-        this(threshold, null, prefix, suffix, directory, 
AbstractByteArrayOutputStream.DEFAULT_SIZE);
-        if (prefix == null) {
-            throw new IllegalArgumentException("Temporary file prefix is 
missing");
-        }
-    }
-
-    /**
-     * Constructs an instance of this class which will trigger an event at the 
specified threshold, and save data to a
      * temporary file beyond that point.
      *
      * @param threshold The number of bytes at which to trigger an event.
@@ -147,72 +150,34 @@ public class DeferredFileOutputStream extends 
ThresholdingOutputStream {
     }
 
     /**
-     * Constructs an instance of this class which will trigger an event at the 
specified threshold, and save data either
-     * to a file beyond that point.
+     * Constructs an instance of this class which will trigger an event at the 
specified threshold, and save data to a
+     * temporary file beyond that point. The initial buffer size will default 
to 32 bytes which is
+     * ByteArrayOutputStream's default buffer size.
      *
      * @param threshold The number of bytes at which to trigger an event.
-     * @param outputFile The file to which data is saved beyond the threshold.
      * @param prefix Prefix to use for the temporary file.
      * @param suffix Suffix to use for the temporary file.
      * @param directory Temporary file directory.
-     * @param initialBufferSize The initial size of the in memory buffer.
-     */
-    private DeferredFileOutputStream(final int threshold, final File 
outputFile, final String prefix,
-        final String suffix, final File directory, final int 
initialBufferSize) {
-        super(threshold);
-        this.outputFile = outputFile;
-        this.prefix = prefix;
-        this.suffix = suffix;
-        this.directory = directory;
-
-        memoryOutputStream = new ByteArrayOutputStream(initialBufferSize);
-        currentOutputStream = memoryOutputStream;
-    }
-
-    /**
-     * Returns the current output stream. This may be memory based or disk 
based, depending on the current state with
-     * respect to the threshold.
-     *
-     * @return The underlying output stream.
      *
-     * @throws IOException if an error occurs.
+     * @since 1.4
      */
-    @Override
-    protected OutputStream getStream() throws IOException {
-        return currentOutputStream;
+    public DeferredFileOutputStream(final int threshold, final String prefix, 
final String suffix,
+        final File directory) {
+        this(threshold, null, prefix, suffix, directory, 
AbstractByteArrayOutputStream.DEFAULT_SIZE);
+        if (prefix == null) {
+            throw new IllegalArgumentException("Temporary file prefix is 
missing");
+        }
     }
 
     /**
-     * Switches the underlying output stream from a memory based stream to one 
that is backed by disk. This is the point
-     * at which we realize that too much data is being written to keep in 
memory, so we elect to switch to disk-based
-     * storage.
+     * Closes underlying output stream, and mark this as closed
      *
      * @throws IOException if an error occurs.
      */
     @Override
-    protected void thresholdReached() throws IOException {
-        if (prefix != null) {
-            outputFile = File.createTempFile(prefix, suffix, directory);
-        }
-        FileUtils.forceMkdirParent(outputFile);
-        final FileOutputStream fos = new FileOutputStream(outputFile);
-        try {
-            memoryOutputStream.writeTo(fos);
-        } catch (final IOException e) {
-            fos.close();
-            throw e;
-        }
-        currentOutputStream = fos;
-        memoryOutputStream = null;
-    }
-
-    /**
-     * Determines whether or not the data for this output stream has been 
retained in memory.
-     *
-     * @return {@code true} if the data is available in memory; {@code false} 
otherwise.
-     */
-    public boolean isInMemory() {
-        return !isThresholdExceeded();
+    public void close() throws IOException {
+        super.close();
+        closed = true;
     }
 
     /**
@@ -241,38 +206,49 @@ public class DeferredFileOutputStream extends 
ThresholdingOutputStream {
     }
 
     /**
-     * Closes underlying output stream, and mark this as closed
+     * Returns the current output stream. This may be memory based or disk 
based, depending on the current state with
+     * respect to the threshold.
+     *
+     * @return The underlying output stream.
      *
      * @throws IOException if an error occurs.
      */
     @Override
-    public void close() throws IOException {
-        super.close();
-        closed = true;
+    protected OutputStream getStream() throws IOException {
+        return currentOutputStream;
     }
 
     /**
-     * Writes the data from this output stream to the specified output stream, 
after it has been closed.
+     * Determines whether or not the data for this output stream has been 
retained in memory.
      *
-     * @param outputStream output stream to write to.
-     * @throws NullPointerException if the OutputStream is {@code null}.
-     * @throws IOException if this stream is not yet closed or an error occurs.
+     * @return {@code true} if the data is available in memory; {@code false} 
otherwise.
      */
-    public void writeTo(final OutputStream outputStream) throws IOException {
-        // we may only need to check if this is closed if we are working with 
a file
-        // but we should force the habit of closing whether we are working with
-        // a file or memory.
-        if (!closed) {
-            throw new IOException("Stream not closed");
-        }
+    public boolean isInMemory() {
+        return !isThresholdExceeded();
+    }
 
-        if (isInMemory()) {
-            memoryOutputStream.writeTo(outputStream);
-        } else {
-            try (FileInputStream fis = new FileInputStream(outputFile)) {
-                IOUtils.copy(fis, outputStream);
-            }
+    /**
+     * Switches the underlying output stream from a memory based stream to one 
that is backed by disk. This is the point
+     * at which we realize that too much data is being written to keep in 
memory, so we elect to switch to disk-based
+     * storage.
+     *
+     * @throws IOException if an error occurs.
+     */
+    @Override
+    protected void thresholdReached() throws IOException {
+        if (prefix != null) {
+            outputFile = File.createTempFile(prefix, suffix, directory);
         }
+        FileUtils.forceMkdirParent(outputFile);
+        final FileOutputStream fos = new FileOutputStream(outputFile);
+        try {
+            memoryOutputStream.writeTo(fos);
+        } catch (final IOException e) {
+            fos.close();
+            throw e;
+        }
+        currentOutputStream = fos;
+        memoryOutputStream = null;
     }
 
     /**
@@ -286,8 +262,8 @@ public class DeferredFileOutputStream extends 
ThresholdingOutputStream {
      * @return the current contents of this output stream.
      * @throws IOException if this stream is not yet closed or an error occurs.
      * @see org.apache.commons.io.output.ByteArrayOutputStream#toInputStream()
-     * 
-     * @since 2.9
+     *
+     * @since 2.9.0
      */
     public InputStream toInputStream() throws IOException {
         // we may only need to check if this is closed if we are working with 
a file
@@ -303,4 +279,28 @@ public class DeferredFileOutputStream extends 
ThresholdingOutputStream {
             return Files.newInputStream(outputFile.toPath());
         }
     }
+
+    /**
+     * Writes the data from this output stream to the specified output stream, 
after it has been closed.
+     *
+     * @param outputStream output stream to write to.
+     * @throws NullPointerException if the OutputStream is {@code null}.
+     * @throws IOException if this stream is not yet closed or an error occurs.
+     */
+    public void writeTo(final OutputStream outputStream) throws IOException {
+        // we may only need to check if this is closed if we are working with 
a file
+        // but we should force the habit of closing whether we are working with
+        // a file or memory.
+        if (!closed) {
+            throw new IOException("Stream not closed");
+        }
+
+        if (isInMemory()) {
+            memoryOutputStream.writeTo(outputStream);
+        } else {
+            try (FileInputStream fis = new FileInputStream(outputFile)) {
+                IOUtils.copy(fis, outputStream);
+            }
+        }
+    }
 }
diff --git 
a/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java 
b/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java
index 23a1c35..8f0d509 100644
--- 
a/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java
+++ 
b/src/test/java/org/apache/commons/io/output/DeferredFileOutputStreamTest.java
@@ -60,48 +60,6 @@ public class DeferredFileOutputStreamTest {
     private final byte[] testBytes = testString.getBytes();
 
     /**
-     * Tests the case where the amount of data falls below the threshold, and 
is therefore confined to memory.
-     */
-    @ParameterizedTest(name = "initialBufferSize = {0}")
-    @MethodSource("data")
-    public void testBelowThreshold(final int initialBufferSize) {
-        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length + 42, initialBufferSize,
-            null);
-        try {
-            dfos.write(testBytes, 0, testBytes.length);
-            dfos.close();
-        } catch (final IOException e) {
-            fail("Unexpected IOException");
-        }
-        assertTrue(dfos.isInMemory());
-
-        final byte[] resultBytes = dfos.getData();
-        assertEquals(testBytes.length, resultBytes.length);
-        assertTrue(Arrays.equals(resultBytes, testBytes));
-    }
-
-    /**
-     * Tests the case where the amount of data is exactly the same as the 
threshold. The behavior should be the same as
-     * that for the amount of data being below (i.e. not exceeding) the 
threshold.
-     */
-    @ParameterizedTest(name = "initialBufferSize = {0}")
-    @MethodSource("data")
-    public void testAtThreshold(final int initialBufferSize) {
-        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length, initialBufferSize, null);
-        try {
-            dfos.write(testBytes, 0, testBytes.length);
-            dfos.close();
-        } catch (final IOException e) {
-            fail("Unexpected IOException");
-        }
-        assertTrue(dfos.isInMemory());
-
-        final byte[] resultBytes = dfos.getData();
-        assertEquals(testBytes.length, resultBytes.length);
-        assertTrue(Arrays.equals(resultBytes, testBytes));
-    }
-
-    /**
      * Tests the case where the amount of data exceeds the threshold, and is 
therefore written to disk. The actual data
      * written to disk is verified, as is the file itself.
      */
@@ -131,132 +89,86 @@ public class DeferredFileOutputStreamTest {
     }
 
     /**
-     * Tests the case where there are multiple writes beyond the threshold, to 
ensure that the
-     * {@code thresholdReached()} method is only called once, as the threshold 
is crossed for the first time.
+     * Tests the case where the amount of data exceeds the threshold, and is 
therefore written to disk. The actual data
+     * written to disk is verified, as is the file itself.
+     * Testing the getInputStream() method.
      */
     @ParameterizedTest(name = "initialBufferSize = {0}")
     @MethodSource("data")
-    public void testThresholdReached(final int initialBufferSize) {
-        final File testFile = new File("testThresholdReached.dat");
-
-        // Ensure that the test starts from a clean base.
-        testFile.delete();
+    public void testAboveThresholdGetInputStream(final int initialBufferSize, 
final @TempDir Path tempDir) throws IOException {
+        final File testFile = 
tempDir.resolve("testAboveThreshold.dat").toFile();
 
-        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length / 2, initialBufferSize,
+        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length - 5, initialBufferSize,
             testFile);
-        final int chunkSize = testBytes.length / 3;
+        dfos.write(testBytes, 0, testBytes.length);
+        dfos.close();
+        assertFalse(dfos.isInMemory());
 
-        try {
-            dfos.write(testBytes, 0, chunkSize);
-            dfos.write(testBytes, chunkSize, chunkSize);
-            dfos.write(testBytes, chunkSize * 2, testBytes.length - chunkSize 
* 2);
-            dfos.close();
-        } catch (final IOException e) {
-            fail("Unexpected IOException");
+        try (InputStream is = dfos.toInputStream()) {
+            assertArrayEquals(testBytes, IOUtils.toByteArray(is));
         }
-        assertFalse(dfos.isInMemory());
-        assertNull(dfos.getData());
 
         verifyResultFile(testFile);
-
-        // Ensure that the test starts from a clean base.
-        testFile.delete();
     }
 
     /**
-     * Test whether writeTo() properly writes small content.
+     * Tests the case where the amount of data is exactly the same as the 
threshold. The behavior should be the same as
+     * that for the amount of data being below (i.e. not exceeding) the 
threshold.
      */
     @ParameterizedTest(name = "initialBufferSize = {0}")
     @MethodSource("data")
-    public void testWriteToSmall(final int initialBufferSize) {
-        final File testFile = new File("testWriteToMem.dat");
-        final ByteArrayOutputStream baos = new 
ByteArrayOutputStream(initialBufferSize);
-        // Ensure that the test starts from a clean base.
-        testFile.delete();
-
-        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length * 2, initialBufferSize,
-            testFile);
+    public void testAtThreshold(final int initialBufferSize) {
+        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length, initialBufferSize, null);
         try {
-            dfos.write(testBytes);
-
-            assertFalse(testFile.exists());
-            assertTrue(dfos.isInMemory());
-
-            try {
-                dfos.writeTo(baos);
-                fail("Should not have been able to write before closing");
-            } catch (final IOException ioe) {
-                // ok, as expected
-            }
-
+            dfos.write(testBytes, 0, testBytes.length);
             dfos.close();
-            dfos.writeTo(baos);
-        } catch (final IOException ioe) {
+        } catch (final IOException e) {
             fail("Unexpected IOException");
         }
-        final byte[] copiedBytes = baos.toByteArray();
-        assertTrue(Arrays.equals(testBytes, copiedBytes));
+        assertTrue(dfos.isInMemory());
 
-        testFile.delete();
+        final byte[] resultBytes = dfos.getData();
+        assertEquals(testBytes.length, resultBytes.length);
+        assertTrue(Arrays.equals(resultBytes, testBytes));
     }
 
     /**
-     * Test whether writeTo() properly writes large content.
+     * Tests the case where the amount of data falls below the threshold, and 
is therefore confined to memory.
      */
     @ParameterizedTest(name = "initialBufferSize = {0}")
     @MethodSource("data")
-    public void testWriteToLarge(final int initialBufferSize) {
-        final File testFile = new File("testWriteToFile.dat");
-        final ByteArrayOutputStream baos = new 
ByteArrayOutputStream(initialBufferSize);
-        // Ensure that the test starts from a clean base.
-        testFile.delete();
-
-        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length / 2, testFile);
+    public void testBelowThreshold(final int initialBufferSize) {
+        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length + 42, initialBufferSize,
+            null);
         try {
-            dfos.write(testBytes);
-
-            assertTrue(testFile.exists());
-            assertFalse(dfos.isInMemory());
-
-            try {
-                dfos.writeTo(baos);
-                fail("Should not have been able to write before closing");
-            } catch (final IOException ioe) {
-                // ok, as expected
-            }
-
+            dfos.write(testBytes, 0, testBytes.length);
             dfos.close();
-            dfos.writeTo(baos);
-        } catch (final IOException ioe) {
+        } catch (final IOException e) {
             fail("Unexpected IOException");
         }
-        final byte[] copiedBytes = baos.toByteArray();
-        assertTrue(Arrays.equals(testBytes, copiedBytes));
-        verifyResultFile(testFile);
-        testFile.delete();
+        assertTrue(dfos.isInMemory());
+
+        final byte[] resultBytes = dfos.getData();
+        assertEquals(testBytes.length, resultBytes.length);
+        assertTrue(Arrays.equals(resultBytes, testBytes));
     }
 
     /**
-     * Test specifying a temporary file and the threshold not reached.
+     * Tests the case where the amount of data falls below the threshold, and 
is therefore confined to memory.
+     * Testing the getInputStream() method.
      */
     @ParameterizedTest(name = "initialBufferSize = {0}")
     @MethodSource("data")
-    public void testTempFileBelowThreshold(final int initialBufferSize) {
-
-        final String prefix = "commons-io-test";
-        final String suffix = ".out";
-        final File tempDir = new File(".");
+    public void testBelowThresholdGetInputStream(final int initialBufferSize) 
throws IOException {
         final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length + 42, initialBufferSize,
-            prefix, suffix, tempDir);
-        assertNull(dfos.getFile(), "Check file is null-A");
-        try {
-            dfos.write(testBytes, 0, testBytes.length);
-            dfos.close();
-        } catch (final IOException e) {
-            fail("Unexpected IOException");
-        }
+            null);
+        dfos.write(testBytes, 0, testBytes.length);
+        dfos.close();
         assertTrue(dfos.isInMemory());
-        assertNull(dfos.getFile(), "Check file is null-B");
+
+        try (InputStream is = dfos.toInputStream()) {
+            assertArrayEquals(testBytes, IOUtils.toByteArray(is));
+        }
     }
 
     /**
@@ -325,6 +237,29 @@ public class DeferredFileOutputStreamTest {
     }
 
     /**
+     * Test specifying a temporary file and the threshold not reached.
+     */
+    @ParameterizedTest(name = "initialBufferSize = {0}")
+    @MethodSource("data")
+    public void testTempFileBelowThreshold(final int initialBufferSize) {
+
+        final String prefix = "commons-io-test";
+        final String suffix = ".out";
+        final File tempDir = new File(".");
+        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length + 42, initialBufferSize,
+            prefix, suffix, tempDir);
+        assertNull(dfos.getFile(), "Check file is null-A");
+        try {
+            dfos.write(testBytes, 0, testBytes.length);
+            dfos.close();
+        } catch (final IOException e) {
+            fail("Unexpected IOException");
+        }
+        assertTrue(dfos.isInMemory());
+        assertNull(dfos.getFile(), "Check file is null-B");
+    }
+
+    /**
      * Test specifying a temporary file and the threshold is reached.
      *
      * @throws Exception
@@ -344,71 +279,136 @@ public class DeferredFileOutputStreamTest {
     }
 
     /**
-     * Verifies that the specified file contains the same data as the original 
test data.
-     *
-     * @param testFile The file containing the test output.
+     * Tests the case where there are multiple writes beyond the threshold, to 
ensure that the
+     * {@code thresholdReached()} method is only called once, as the threshold 
is crossed for the first time.
      */
-    private void verifyResultFile(final File testFile) {
-        try {
-            final FileInputStream fis = new FileInputStream(testFile);
-            assertEquals(testBytes.length, fis.available());
+    @ParameterizedTest(name = "initialBufferSize = {0}")
+    @MethodSource("data")
+    public void testThresholdReached(final int initialBufferSize) {
+        final File testFile = new File("testThresholdReached.dat");
 
-            final byte[] resultBytes = new byte[testBytes.length];
-            assertEquals(testBytes.length, fis.read(resultBytes));
+        // Ensure that the test starts from a clean base.
+        testFile.delete();
 
-            assertTrue(Arrays.equals(resultBytes, testBytes));
-            assertEquals(-1, fis.read(resultBytes));
+        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length / 2, initialBufferSize,
+            testFile);
+        final int chunkSize = testBytes.length / 3;
 
-            try {
-                fis.close();
-            } catch (final IOException e) {
-                // Ignore an exception on close
-            }
-        } catch (final FileNotFoundException e) {
-            fail("Unexpected FileNotFoundException");
+        try {
+            dfos.write(testBytes, 0, chunkSize);
+            dfos.write(testBytes, chunkSize, chunkSize);
+            dfos.write(testBytes, chunkSize * 2, testBytes.length - chunkSize 
* 2);
+            dfos.close();
         } catch (final IOException e) {
             fail("Unexpected IOException");
         }
+        assertFalse(dfos.isInMemory());
+        assertNull(dfos.getData());
+
+        verifyResultFile(testFile);
+
+        // Ensure that the test starts from a clean base.
+        testFile.delete();
     }
 
     /**
-     * Tests the case where the amount of data falls below the threshold, and 
is therefore confined to memory.
-     * Testing the getInputStream() method.
+     * Test whether writeTo() properly writes large content.
      */
     @ParameterizedTest(name = "initialBufferSize = {0}")
     @MethodSource("data")
-    public void testBelowThresholdGetInputStream(final int initialBufferSize) 
throws IOException {
-        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length + 42, initialBufferSize,
-            null);
-        dfos.write(testBytes, 0, testBytes.length);
-        dfos.close();
-        assertTrue(dfos.isInMemory());
+    public void testWriteToLarge(final int initialBufferSize) {
+        final File testFile = new File("testWriteToFile.dat");
+        final ByteArrayOutputStream baos = new 
ByteArrayOutputStream(initialBufferSize);
+        // Ensure that the test starts from a clean base.
+        testFile.delete();
 
-        try (InputStream is = dfos.toInputStream()) {
-            assertArrayEquals(testBytes, IOUtils.toByteArray(is));
+        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length / 2, testFile);
+        try {
+            dfos.write(testBytes);
+
+            assertTrue(testFile.exists());
+            assertFalse(dfos.isInMemory());
+
+            try {
+                dfos.writeTo(baos);
+                fail("Should not have been able to write before closing");
+            } catch (final IOException ioe) {
+                // ok, as expected
+            }
+
+            dfos.close();
+            dfos.writeTo(baos);
+        } catch (final IOException ioe) {
+            fail("Unexpected IOException");
         }
+        final byte[] copiedBytes = baos.toByteArray();
+        assertTrue(Arrays.equals(testBytes, copiedBytes));
+        verifyResultFile(testFile);
+        testFile.delete();
     }
 
     /**
-     * Tests the case where the amount of data exceeds the threshold, and is 
therefore written to disk. The actual data
-     * written to disk is verified, as is the file itself.
-     * Testing the getInputStream() method.
+     * Test whether writeTo() properly writes small content.
      */
     @ParameterizedTest(name = "initialBufferSize = {0}")
     @MethodSource("data")
-    public void testAboveThresholdGetInputStream(final int initialBufferSize, 
final @TempDir Path tempDir) throws IOException {
-        final File testFile = 
tempDir.resolve("testAboveThreshold.dat").toFile();
+    public void testWriteToSmall(final int initialBufferSize) {
+        final File testFile = new File("testWriteToMem.dat");
+        final ByteArrayOutputStream baos = new 
ByteArrayOutputStream(initialBufferSize);
+        // Ensure that the test starts from a clean base.
+        testFile.delete();
 
-        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length - 5, initialBufferSize,
+        final DeferredFileOutputStream dfos = new 
DeferredFileOutputStream(testBytes.length * 2, initialBufferSize,
             testFile);
-        dfos.write(testBytes, 0, testBytes.length);
-        dfos.close();
-        assertFalse(dfos.isInMemory());
+        try {
+            dfos.write(testBytes);
 
-        try (InputStream is = dfos.toInputStream()) {
-            assertArrayEquals(testBytes, IOUtils.toByteArray(is));
+            assertFalse(testFile.exists());
+            assertTrue(dfos.isInMemory());
+
+            try {
+                dfos.writeTo(baos);
+                fail("Should not have been able to write before closing");
+            } catch (final IOException ioe) {
+                // ok, as expected
+            }
+
+            dfos.close();
+            dfos.writeTo(baos);
+        } catch (final IOException ioe) {
+            fail("Unexpected IOException");
         }
+        final byte[] copiedBytes = baos.toByteArray();
+        assertTrue(Arrays.equals(testBytes, copiedBytes));
 
-        verifyResultFile(testFile);
+        testFile.delete();
+    }
+
+    /**
+     * Verifies that the specified file contains the same data as the original 
test data.
+     *
+     * @param testFile The file containing the test output.
+     */
+    private void verifyResultFile(final File testFile) {
+        try {
+            final FileInputStream fis = new FileInputStream(testFile);
+            assertEquals(testBytes.length, fis.available());
+
+            final byte[] resultBytes = new byte[testBytes.length];
+            assertEquals(testBytes.length, fis.read(resultBytes));
+
+            assertTrue(Arrays.equals(resultBytes, testBytes));
+            assertEquals(-1, fis.read(resultBytes));
+
+            try {
+                fis.close();
+            } catch (final IOException e) {
+                // Ignore an exception on close
+            }
+        } catch (final FileNotFoundException e) {
+            fail("Unexpected FileNotFoundException");
+        } catch (final IOException e) {
+            fail("Unexpected IOException");
+        }
     }
 }

Reply via email to