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 <[email protected]>
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");
+ }
}
}