1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.io.output;
18
19 import static org.apache.commons.io.output.ThresholdingOutputStreamTest.assertThresholdingInitialState;
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import static org.junit.jupiter.api.Assertions.assertNull;
25 import static org.junit.jupiter.api.Assertions.assertThrows;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27
28 import java.io.File;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.nio.file.Files;
32 import java.nio.file.Path;
33 import java.util.stream.IntStream;
34
35 import org.apache.commons.io.IOUtils;
36 import org.apache.commons.io.file.AbstractTempDirTest;
37 import org.junit.jupiter.api.Test;
38 import org.junit.jupiter.api.io.TempDir;
39 import org.junit.jupiter.params.ParameterizedTest;
40 import org.junit.jupiter.params.provider.MethodSource;
41
42
43
44
45
46
47 class DeferredFileOutputStreamTest extends AbstractTempDirTest {
48
49 private static void assertDeferredInitialState(final DeferredFileOutputStream out) {
50 assertTrue(out.isInMemory());
51 }
52
53 public static IntStream data() {
54 return IntStream.of(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096);
55 }
56
57
58
59
60 private final String testString = "0123456789";
61
62
63
64
65 private final byte[] testBytes = testString.getBytes();
66
67
68
69
70
71
72
73
74 @ParameterizedTest(name = "initialBufferSize = {0}")
75 @MethodSource("data")
76 void testAboveThreshold(final int initialBufferSize) throws IOException {
77 final File testFile = Files.createTempFile(tempDirPath, "testAboveThreshold", "dat").toFile();
78 final int threshold = testBytes.length - 5;
79 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
80 .setThreshold(threshold)
81 .setBufferSize(initialBufferSize)
82 .setOutputFile(testFile)
83 .get()) {
84 assertThresholdingInitialState(out, threshold, 0);
85 assertDeferredInitialState(out);
86 out.write(testBytes, 0, testBytes.length);
87 out.close();
88 assertFalse(out.isInMemory());
89 assertNull(out.getData());
90 assertEquals(testFile.length(), out.getByteCount());
91 verifyResultFile(testFile);
92 }
93 }
94
95
96
97
98
99
100 @ParameterizedTest(name = "initialBufferSize = {0}")
101 @MethodSource("data")
102 void testAboveThresholdGetInputStream(final int initialBufferSize, final @TempDir Path tempDir) throws IOException {
103 final File testFile = Files.createTempFile(tempDirPath, "testAboveThreshold", "dat").toFile();
104 final int threshold = testBytes.length - 5;
105 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
106 .setThreshold(threshold)
107 .setBufferSize(initialBufferSize)
108 .setOutputFile(testFile)
109 .get()) {
110 assertThresholdingInitialState(out, threshold, 0);
111 assertDeferredInitialState(out);
112 out.write(testBytes, 0, testBytes.length);
113 out.close();
114 assertFalse(out.isInMemory());
115 assertEquals(testFile.length(), out.getByteCount());
116 try (InputStream is = out.toInputStream()) {
117 assertArrayEquals(testBytes, IOUtils.toByteArray(is));
118 }
119 verifyResultFile(testFile);
120 }
121 }
122
123
124
125
126
127 @ParameterizedTest(name = "initialBufferSize = {0}")
128 @MethodSource("data")
129 void testAtThreshold(final int initialBufferSize) throws IOException {
130 final int threshold = testBytes.length;
131 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
132
133 .setThreshold(threshold)
134 .setBufferSize(initialBufferSize)
135 .get()) {
136
137 assertThresholdingInitialState(out, threshold, 0);
138 assertDeferredInitialState(out);
139 out.write(testBytes, 0, testBytes.length);
140 out.close();
141 assertTrue(out.isInMemory());
142 assertEquals(testBytes.length, out.getByteCount());
143 final byte[] resultBytes = out.getData();
144 assertEquals(testBytes.length, resultBytes.length);
145 assertArrayEquals(resultBytes, testBytes);
146 }
147 }
148
149
150
151
152
153 @ParameterizedTest(name = "initialBufferSize = {0}")
154 @MethodSource("data")
155 void testBelowThreshold(final int initialBufferSize) throws IOException {
156 final int threshold = testBytes.length + 42;
157 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
158
159 .setThreshold(threshold)
160 .setBufferSize(initialBufferSize)
161 .get()) {
162
163 assertThresholdingInitialState(out, threshold, 0);
164 assertDeferredInitialState(out);
165 out.write(testBytes, 0, testBytes.length);
166 out.close();
167 assertTrue(out.isInMemory());
168 assertEquals(testBytes.length, out.getByteCount());
169 final byte[] resultBytes = out.getData();
170 assertEquals(testBytes.length, resultBytes.length);
171 assertArrayEquals(resultBytes, testBytes);
172 }
173 }
174
175
176
177
178
179 @ParameterizedTest(name = "initialBufferSize = {0}")
180 @MethodSource("data")
181 void testBelowThresholdGetInputStream(final int initialBufferSize) throws IOException {
182
183 final int threshold = testBytes.length + 42;
184 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
185 .setThreshold(threshold)
186 .setBufferSize(initialBufferSize)
187 .get()) {
188
189 assertThresholdingInitialState(out, threshold, 0);
190 assertDeferredInitialState(out);
191 out.write(testBytes, 0, testBytes.length);
192 out.close();
193 assertTrue(out.isInMemory());
194 assertEquals(testBytes.length, out.getByteCount());
195 try (InputStream is = out.toInputStream()) {
196 assertArrayEquals(testBytes, IOUtils.toByteArray(is));
197 }
198 }
199 }
200
201
202
203
204 @ParameterizedTest(name = "initialBufferSize = {0}")
205 @MethodSource("data")
206 void testTempFileAboveThreshold(final int initialBufferSize) throws IOException {
207 final String prefix = "commons-io-test";
208 final String suffix = ".out";
209
210 final int threshold = testBytes.length - 5;
211 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
212 .setThreshold(threshold)
213 .setBufferSize(initialBufferSize)
214 .setPrefix(prefix)
215 .setSuffix(suffix)
216 .setDirectory(tempDirFile)
217 .setDirectory(tempDirPath.toFile())
218 .get()) {
219
220 assertThresholdingInitialState(out, threshold, 0);
221 assertDeferredInitialState(out);
222 assertNull(out.getFile(), "Check File is null-A");
223 assertNull(out.getPath(), "Check Path is null-A");
224 out.write(testBytes, 0, testBytes.length);
225 out.close();
226 assertFalse(out.isInMemory());
227 assertEquals(testBytes.length, out.getByteCount());
228 assertNull(out.getData());
229 assertNotNull(out.getFile(), "Check file not null");
230 assertTrue(out.getFile().exists(), "Check file exists");
231 assertTrue(out.getFile().getName().startsWith(prefix), "Check prefix");
232 assertTrue(out.getFile().getName().endsWith(suffix), "Check suffix");
233 assertEquals(tempDirPath, out.getPath().getParent(), "Check dir");
234 verifyResultFile(out.getFile());
235 }
236 }
237
238
239
240
241
242 @ParameterizedTest(name = "initialBufferSize = {0}")
243 @MethodSource("data")
244 void testTempFileAboveThresholdPrefixOnly(final int initialBufferSize) throws IOException {
245 final String prefix = "commons-io-test";
246 final String suffix = null;
247 final int threshold = testBytes.length - 5;
248 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
249
250 .setThreshold(threshold)
251 .setBufferSize(initialBufferSize)
252 .setPrefix(prefix)
253 .setSuffix(suffix)
254 .setDirectory((Path) null)
255 .get()) {
256
257 try {
258 assertThresholdingInitialState(out, threshold, 0);
259 assertDeferredInitialState(out);
260 assertNull(out.getFile(), "Check File is null-A");
261 assertNull(out.getPath(), "Check Path is null-A");
262 out.write(testBytes, 0, testBytes.length);
263 out.close();
264 assertFalse(out.isInMemory());
265 assertNull(out.getData());
266 assertEquals(testBytes.length, out.getByteCount());
267 assertNotNull(out.getFile(), "Check file not null");
268 assertTrue(out.getFile().exists(), "Check file exists");
269 assertTrue(out.getFile().getName().startsWith(prefix), "Check prefix");
270 assertTrue(out.getFile().getName().endsWith(".tmp"), "Check suffix");
271 verifyResultFile(out.getFile());
272 } finally {
273
274 out.getFile().delete();
275 }
276 }
277 }
278
279
280
281
282
283 @ParameterizedTest(name = "initialBufferSize = {0}")
284 @MethodSource("data")
285 void testTempFileBelowThreshold(final int initialBufferSize) throws IOException {
286 final String prefix = "commons-io-test";
287 final String suffix = ".out";
288 final int threshold = testBytes.length + 42;
289 try (DeferredFileOutputStream out = new DeferredFileOutputStream(threshold, initialBufferSize, prefix, suffix, tempDirFile)) {
290 assertThresholdingInitialState(out, threshold, 0);
291 assertDeferredInitialState(out);
292 assertNull(out.getFile(), "Check File is null-A");
293 assertNull(out.getPath(), "Check Path is null-A");
294 out.write(testBytes, 0, testBytes.length);
295 out.close();
296 assertTrue(out.isInMemory());
297 assertEquals(testBytes.length, out.getByteCount());
298 assertNull(out.getFile(), "Check file is null-B");
299 }
300 }
301
302
303
304
305
306
307 @Test
308 void testTempFileError() throws Exception {
309 final String prefix = null;
310 final String suffix = ".out";
311 assertThrows(NullPointerException.class, () -> new DeferredFileOutputStream(testBytes.length - 5, prefix, suffix, tempDirFile));
312 }
313
314
315
316
317
318 @ParameterizedTest(name = "initialBufferSize = {0}")
319 @MethodSource("data")
320 void testThresholdNegative(final int initialBufferSize) throws IOException {
321 final File testFile = Files.createTempFile(tempDirPath, "testThresholdNegative", "dat").toFile();
322 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
323 .setThreshold(-1)
324 .setBufferSize(initialBufferSize)
325 .setOutputFile(testFile)
326 .get()) {
327 assertThresholdingInitialState(out, 0, 0);
328 assertDeferredInitialState(out);
329 out.write(testBytes, 0, testBytes.length);
330 out.close();
331 assertFalse(out.isInMemory());
332 assertNull(out.getData());
333 assertEquals(testFile.length(), out.getByteCount());
334 verifyResultFile(testFile);
335 }
336 }
337
338
339
340
341
342
343 @ParameterizedTest(name = "initialBufferSize = {0}")
344 @MethodSource("data")
345 void testThresholdReached(final int initialBufferSize) throws IOException {
346 final File testFile = Files.createTempFile(tempDirPath, "testThresholdReached", "dat").toFile();
347 final int threshold = testBytes.length / 2;
348 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
349
350 .setThreshold(threshold)
351 .setBufferSize(initialBufferSize)
352 .setOutputFile(testFile)
353 .get()) {
354
355 assertThresholdingInitialState(out, threshold, 0);
356 assertDeferredInitialState(out);
357 final int chunkSize = testBytes.length / 3;
358 out.write(testBytes, 0, chunkSize);
359 out.write(testBytes, chunkSize, chunkSize);
360 out.write(testBytes, chunkSize * 2, testBytes.length - chunkSize * 2);
361 out.close();
362 assertFalse(out.isInMemory());
363 assertNull(out.getData());
364 assertEquals(testBytes.length, out.getByteCount());
365 verifyResultFile(testFile);
366 }
367 }
368
369
370
371
372 @ParameterizedTest(name = "initialBufferSize = {0}")
373 @MethodSource("data")
374 void testWriteToLarge(final int initialBufferSize) throws IOException {
375 final File testFile = Files.createTempFile(tempDirPath, "testWriteToFile", "dat").toFile();
376 final int threshold = testBytes.length / 2;
377 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize);
378 DeferredFileOutputStream dfos = DeferredFileOutputStream.builder().setThreshold(threshold).setOutputFile(testFile).get()) {
379 assertThresholdingInitialState(dfos, threshold, 0);
380 assertDeferredInitialState(dfos);
381 dfos.write(testBytes);
382 assertTrue(testFile.exists());
383 assertFalse(dfos.isInMemory());
384 assertEquals(testBytes.length, dfos.getByteCount());
385 assertThrows(IOException.class, () -> dfos.writeTo(baos));
386 dfos.close();
387 dfos.writeTo(baos);
388 final byte[] copiedBytes = baos.toByteArray();
389 assertArrayEquals(testBytes, copiedBytes);
390 verifyResultFile(testFile);
391 }
392 }
393
394
395
396
397 @ParameterizedTest(name = "initialBufferSize = {0}")
398 @MethodSource("data")
399 void testWriteToLargeCtor(final int initialBufferSize) throws IOException {
400 final File testFile = Files.createTempFile(tempDirPath, "testWriteToFile", "dat").toFile();
401 final int threshold = testBytes.length / 2;
402 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize);
403 DeferredFileOutputStream dfos = new DeferredFileOutputStream(threshold, testFile)) {
404 assertThresholdingInitialState(dfos, threshold, 0);
405 assertDeferredInitialState(dfos);
406 dfos.write(testBytes);
407 assertTrue(testFile.exists());
408 assertFalse(dfos.isInMemory());
409 assertThrows(IOException.class, () -> dfos.writeTo(baos));
410 assertEquals(testBytes.length, dfos.getByteCount());
411 dfos.close();
412 dfos.writeTo(baos);
413 final byte[] copiedBytes = baos.toByteArray();
414 assertArrayEquals(testBytes, copiedBytes);
415 verifyResultFile(testFile);
416 }
417 }
418
419
420
421
422
423 @ParameterizedTest(name = "initialBufferSize = {0}")
424 @MethodSource("data")
425 void testWriteToSmall(final int initialBufferSize) throws IOException {
426 final File testFile = Files.createTempFile(tempDirPath, "testWriteToMem", "dat").toFile();
427 final int threshold = testBytes.length * 2;
428 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize);
429 DeferredFileOutputStream dfos = new DeferredFileOutputStream(threshold, initialBufferSize, testFile)) {
430 assertThresholdingInitialState(dfos, threshold, 0);
431 assertDeferredInitialState(dfos);
432 dfos.write(testBytes);
433 assertTrue(dfos.isInMemory());
434 assertThrows(IOException.class, () -> dfos.writeTo(baos));
435 assertEquals(testBytes.length, dfos.getByteCount());
436 dfos.close();
437 dfos.writeTo(baos);
438 final byte[] copiedBytes = baos.toByteArray();
439 assertArrayEquals(testBytes, copiedBytes);
440 }
441 }
442
443
444
445
446
447
448 private void verifyResultFile(final File testFile) throws IOException {
449 try (InputStream fis = Files.newInputStream(testFile.toPath())) {
450 assertEquals(testBytes.length, fis.available());
451
452 final byte[] resultBytes = new byte[testBytes.length];
453 assertEquals(testBytes.length, fis.read(resultBytes));
454
455 assertArrayEquals(resultBytes, testBytes);
456 assertEquals(-1, fis.read(resultBytes));
457 }
458 }
459 }