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
154 @ParameterizedTest(name = "initialBufferSize = {0}")
155 @MethodSource("data")
156 void testBelowThreshold(final int initialBufferSize) throws IOException {
157 final int threshold = testBytes.length + 42;
158 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
159
160 .setThreshold(threshold)
161 .setBufferSize(initialBufferSize)
162 .get()) {
163
164 assertThresholdingInitialState(out, threshold, 0);
165 assertDeferredInitialState(out);
166 out.write(testBytes, 0, testBytes.length);
167 out.close();
168 assertTrue(out.isInMemory());
169 assertEquals(testBytes.length, out.getByteCount());
170 final byte[] resultBytes = out.getData();
171 assertEquals(testBytes.length, resultBytes.length);
172 assertArrayEquals(resultBytes, testBytes);
173 }
174 }
175
176
177
178
179
180 @ParameterizedTest(name = "initialBufferSize = {0}")
181 @MethodSource("data")
182 void testBelowThresholdGetInputStream(final int initialBufferSize) throws IOException {
183
184 final int threshold = testBytes.length + 42;
185 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
186 .setThreshold(threshold)
187 .setBufferSize(initialBufferSize)
188 .get()) {
189
190 assertThresholdingInitialState(out, threshold, 0);
191 assertDeferredInitialState(out);
192 out.write(testBytes, 0, testBytes.length);
193 out.close();
194 assertTrue(out.isInMemory());
195 assertEquals(testBytes.length, out.getByteCount());
196 try (InputStream is = out.toInputStream()) {
197 assertArrayEquals(testBytes, IOUtils.toByteArray(is));
198 }
199 }
200 }
201
202
203
204
205 @ParameterizedTest(name = "initialBufferSize = {0}")
206 @MethodSource("data")
207 void testTempFileAboveThreshold(final int initialBufferSize) throws IOException {
208 final String prefix = "commons-io-test";
209 final String suffix = ".out";
210
211 final int threshold = testBytes.length - 5;
212 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
213 .setThreshold(threshold)
214 .setBufferSize(initialBufferSize)
215 .setPrefix(prefix)
216 .setSuffix(suffix)
217 .setDirectory(tempDirFile)
218 .setDirectory(tempDirPath.toFile())
219 .get()) {
220
221 assertThresholdingInitialState(out, threshold, 0);
222 assertDeferredInitialState(out);
223 assertNull(out.getFile(), "Check File is null-A");
224 assertNull(out.getPath(), "Check Path is null-A");
225 out.write(testBytes, 0, testBytes.length);
226 out.close();
227 assertFalse(out.isInMemory());
228 assertEquals(testBytes.length, out.getByteCount());
229 assertNull(out.getData());
230 assertNotNull(out.getFile(), "Check file not null");
231 assertTrue(out.getFile().exists(), "Check file exists");
232 assertTrue(out.getFile().getName().startsWith(prefix), "Check prefix");
233 assertTrue(out.getFile().getName().endsWith(suffix), "Check suffix");
234 assertEquals(tempDirPath, out.getPath().getParent(), "Check dir");
235 verifyResultFile(out.getFile());
236 }
237 }
238
239
240
241
242
243
244 @ParameterizedTest(name = "initialBufferSize = {0}")
245 @MethodSource("data")
246 void testTempFileAboveThresholdPrefixOnly(final int initialBufferSize) throws IOException {
247 final String prefix = "commons-io-test";
248 final String suffix = null;
249 final int threshold = testBytes.length - 5;
250 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
251
252 .setThreshold(threshold)
253 .setBufferSize(initialBufferSize)
254 .setPrefix(prefix)
255 .setSuffix(suffix)
256 .setDirectory((Path) null)
257 .get()) {
258
259 try {
260 assertThresholdingInitialState(out, threshold, 0);
261 assertDeferredInitialState(out);
262 assertNull(out.getFile(), "Check File is null-A");
263 assertNull(out.getPath(), "Check Path is null-A");
264 out.write(testBytes, 0, testBytes.length);
265 out.close();
266 assertFalse(out.isInMemory());
267 assertNull(out.getData());
268 assertEquals(testBytes.length, out.getByteCount());
269 assertNotNull(out.getFile(), "Check file not null");
270 assertTrue(out.getFile().exists(), "Check file exists");
271 assertTrue(out.getFile().getName().startsWith(prefix), "Check prefix");
272 assertTrue(out.getFile().getName().endsWith(".tmp"), "Check suffix");
273 verifyResultFile(out.getFile());
274 } finally {
275
276 out.getFile().delete();
277 }
278 }
279 }
280
281
282
283
284
285
286 @ParameterizedTest(name = "initialBufferSize = {0}")
287 @MethodSource("data")
288 void testTempFileBelowThreshold(final int initialBufferSize) throws IOException {
289 final String prefix = "commons-io-test";
290 final String suffix = ".out";
291 final int threshold = testBytes.length + 42;
292 try (DeferredFileOutputStream out = new DeferredFileOutputStream(threshold, initialBufferSize, prefix, suffix, tempDirFile)) {
293 assertThresholdingInitialState(out, threshold, 0);
294 assertDeferredInitialState(out);
295 assertNull(out.getFile(), "Check File is null-A");
296 assertNull(out.getPath(), "Check Path is null-A");
297 out.write(testBytes, 0, testBytes.length);
298 out.close();
299 assertTrue(out.isInMemory());
300 assertEquals(testBytes.length, out.getByteCount());
301 assertNull(out.getFile(), "Check file is null-B");
302 }
303 }
304
305
306
307
308
309
310 @Test
311 void testTempFileError() throws Exception {
312 final String prefix = null;
313 final String suffix = ".out";
314 assertThrows(NullPointerException.class, () -> new DeferredFileOutputStream(testBytes.length - 5, prefix, suffix, tempDirFile));
315 }
316
317
318
319
320
321 @ParameterizedTest(name = "initialBufferSize = {0}")
322 @MethodSource("data")
323 void testThresholdNegative(final int initialBufferSize) throws IOException {
324 final File testFile = Files.createTempFile(tempDirPath, "testThresholdNegative", "dat").toFile();
325 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
326 .setThreshold(-1)
327 .setBufferSize(initialBufferSize)
328 .setOutputFile(testFile)
329 .get()) {
330 assertThresholdingInitialState(out, 0, 0);
331 assertDeferredInitialState(out);
332 out.write(testBytes, 0, testBytes.length);
333 out.close();
334 assertFalse(out.isInMemory());
335 assertNull(out.getData());
336 assertEquals(testFile.length(), out.getByteCount());
337 verifyResultFile(testFile);
338 }
339 }
340
341
342
343
344
345
346
347 @ParameterizedTest(name = "initialBufferSize = {0}")
348 @MethodSource("data")
349 void testThresholdReached(final int initialBufferSize) throws IOException {
350 final File testFile = Files.createTempFile(tempDirPath, "testThresholdReached", "dat").toFile();
351 final int threshold = testBytes.length / 2;
352 try (DeferredFileOutputStream out = DeferredFileOutputStream.builder()
353
354 .setThreshold(threshold)
355 .setBufferSize(initialBufferSize)
356 .setOutputFile(testFile)
357 .get()) {
358
359 assertThresholdingInitialState(out, threshold, 0);
360 assertDeferredInitialState(out);
361 final int chunkSize = testBytes.length / 3;
362 out.write(testBytes, 0, chunkSize);
363 out.write(testBytes, chunkSize, chunkSize);
364 out.write(testBytes, chunkSize * 2, testBytes.length - chunkSize * 2);
365 out.close();
366 assertFalse(out.isInMemory());
367 assertNull(out.getData());
368 assertEquals(testBytes.length, out.getByteCount());
369 verifyResultFile(testFile);
370 }
371 }
372
373
374
375
376 @ParameterizedTest(name = "initialBufferSize = {0}")
377 @MethodSource("data")
378 void testWriteToLarge(final int initialBufferSize) throws IOException {
379 final File testFile = Files.createTempFile(tempDirPath, "testWriteToFile", "dat").toFile();
380 final int threshold = testBytes.length / 2;
381 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize);
382 DeferredFileOutputStream dfos = DeferredFileOutputStream.builder().setThreshold(threshold).setOutputFile(testFile).get()) {
383 assertThresholdingInitialState(dfos, threshold, 0);
384 assertDeferredInitialState(dfos);
385 dfos.write(testBytes);
386 assertTrue(testFile.exists());
387 assertFalse(dfos.isInMemory());
388 assertEquals(testBytes.length, dfos.getByteCount());
389 assertThrows(IOException.class, () -> dfos.writeTo(baos));
390 dfos.close();
391 dfos.writeTo(baos);
392 final byte[] copiedBytes = baos.toByteArray();
393 assertArrayEquals(testBytes, copiedBytes);
394 verifyResultFile(testFile);
395 }
396 }
397
398
399
400
401 @ParameterizedTest(name = "initialBufferSize = {0}")
402 @MethodSource("data")
403 void testWriteToLargeCtor(final int initialBufferSize) throws IOException {
404 final File testFile = Files.createTempFile(tempDirPath, "testWriteToFile", "dat").toFile();
405 final int threshold = testBytes.length / 2;
406 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize);
407 DeferredFileOutputStream dfos = new DeferredFileOutputStream(threshold, testFile)) {
408 assertThresholdingInitialState(dfos, threshold, 0);
409 assertDeferredInitialState(dfos);
410 dfos.write(testBytes);
411 assertTrue(testFile.exists());
412 assertFalse(dfos.isInMemory());
413 assertThrows(IOException.class, () -> dfos.writeTo(baos));
414 assertEquals(testBytes.length, dfos.getByteCount());
415 dfos.close();
416 dfos.writeTo(baos);
417 final byte[] copiedBytes = baos.toByteArray();
418 assertArrayEquals(testBytes, copiedBytes);
419 verifyResultFile(testFile);
420 }
421 }
422
423
424
425
426
427
428 @ParameterizedTest(name = "initialBufferSize = {0}")
429 @MethodSource("data")
430 void testWriteToSmall(final int initialBufferSize) throws IOException {
431 final File testFile = Files.createTempFile(tempDirPath, "testWriteToMem", "dat").toFile();
432 final int threshold = testBytes.length * 2;
433 try (ByteArrayOutputStream baos = new ByteArrayOutputStream(initialBufferSize);
434 DeferredFileOutputStream dfos = new DeferredFileOutputStream(threshold, initialBufferSize, testFile)) {
435 assertThresholdingInitialState(dfos, threshold, 0);
436 assertDeferredInitialState(dfos);
437 dfos.write(testBytes);
438 assertTrue(dfos.isInMemory());
439 assertThrows(IOException.class, () -> dfos.writeTo(baos));
440 assertEquals(testBytes.length, dfos.getByteCount());
441 dfos.close();
442 dfos.writeTo(baos);
443 final byte[] copiedBytes = baos.toByteArray();
444 assertArrayEquals(testBytes, copiedBytes);
445 }
446 }
447
448
449
450
451
452
453 private void verifyResultFile(final File testFile) throws IOException {
454 try (InputStream fis = Files.newInputStream(testFile.toPath())) {
455 assertEquals(testBytes.length, fis.available());
456
457 final byte[] resultBytes = new byte[testBytes.length];
458 assertEquals(testBytes.length, fis.read(resultBytes));
459
460 assertArrayEquals(resultBytes, testBytes);
461 assertEquals(-1, fis.read(resultBytes));
462 }
463 }
464 }