1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.io.input;
18
19 import static org.apache.commons.lang3.ArrayUtils.EMPTY_BYTE_ARRAY;
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.assertThrows;
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.util.Arrays;
29
30 import org.apache.commons.io.IOUtils;
31 import org.apache.commons.lang3.RandomUtils;
32 import org.junit.jupiter.api.AfterEach;
33 import org.junit.jupiter.api.Assertions;
34 import org.junit.jupiter.api.Test;
35 import org.junit.jupiter.api.io.TempDir;
36 import org.junit.jupiter.params.ParameterizedTest;
37 import org.junit.jupiter.params.provider.MethodSource;
38 import org.junit.jupiter.params.provider.ValueSource;
39
40
41
42
43 class MemoryMappedFileInputStreamTest {
44
45 @TempDir
46 Path tempDir;
47
48 @AfterEach
49 public void afterEach() {
50
51
52
53 System.gc();
54 Thread.yield();
55 System.runFinalization();
56 Thread.yield();
57 System.gc();
58 Thread.yield();
59 System.runFinalization();
60 Thread.yield();
61 }
62
63 private Path createTestFile(final int size) throws IOException {
64 return Files.write(Files.createTempFile(tempDir, null, null), RandomUtils.insecure().randomBytes(size));
65 }
66
67 private MemoryMappedFileInputStream newInputStream(final Path file) throws IOException {
68 return MemoryMappedFileInputStream.builder().setPath(file).get();
69 }
70
71 private MemoryMappedFileInputStream newInputStream(final Path file, final int bufferSize) throws IOException {
72 return MemoryMappedFileInputStream.builder().setPath(file).setBufferSize(bufferSize).get();
73 }
74
75 @Test
76 void testAlternateBufferSize() throws IOException {
77
78 final Path file = createTestFile(1024 * 1024);
79 final byte[] expectedData = Files.readAllBytes(file);
80
81 try (InputStream inputStream = newInputStream(file, 1024)) {
82
83 assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream));
84 }
85 }
86
87 @SuppressWarnings("resource")
88 @ParameterizedTest
89 @MethodSource(AbstractInputStreamTest.ARRAY_LENGTHS_NAME)
90 void testAvailableAfterClose(final int len) throws Exception {
91 final Path file = createTestFile(len);
92 final InputStream shadow;
93 try (InputStream inputStream = newInputStream(file, 1024)) {
94
95 assertEquals(0, inputStream.available());
96 shadow = inputStream;
97 }
98 assertEquals(0, shadow.available());
99 }
100
101 @ParameterizedTest
102 @MethodSource(AbstractInputStreamTest.ARRAY_LENGTHS_NAME)
103 void testAvailableAfterOpen(final int len) throws Exception {
104 final Path file = createTestFile(len);
105 try (InputStream inputStream = newInputStream(file, 1024)) {
106
107 assertEquals(0, inputStream.available());
108 inputStream.read();
109 assertEquals(Math.max(len - 1, 0), inputStream.available());
110 IOUtils.toByteArray(inputStream);
111 assertEquals(0, inputStream.available());
112 }
113 }
114
115 @Test
116 void testEmptyFile() throws IOException {
117
118 final Path file = createTestFile(0);
119
120 try (InputStream inputStream = newInputStream(file)) {
121
122 assertArrayEquals(EMPTY_BYTE_ARRAY, IOUtils.toByteArray(inputStream));
123 }
124 }
125
126 @Test
127 void testLargerFile() throws IOException {
128
129 final Path file = createTestFile(1024 * 1024);
130 final byte[] expectedData = Files.readAllBytes(file);
131
132 try (InputStream inputStream = newInputStream(file)) {
133
134 assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream));
135 }
136 }
137
138 @Test
139 void testReadAfterClose() throws IOException {
140
141 final Path file = createTestFile(1 * 1024 * 1024);
142
143 try (InputStream inputStream = newInputStream(file, 1024)) {
144 inputStream.close();
145
146 Assertions.assertThrows(IOException.class, () -> IOUtils.toByteArray(inputStream));
147 }
148 }
149
150 @ParameterizedTest
151 @MethodSource(AbstractInputStreamTest.ARRAY_LENGTHS_NAME)
152 void testReadAfterClose(final int len) throws Exception {
153 final Path file = createTestFile(len);
154 try (InputStream inputStream = newInputStream(file, 1024)) {
155 inputStream.close();
156 assertThrows(IOException.class, inputStream::read);
157 }
158 }
159
160 @Test
161 void testReadSingleByte() throws IOException {
162
163 final Path file = createTestFile(2);
164 final byte[] expectedData = Files.readAllBytes(file);
165
166 try (InputStream inputStream = newInputStream(file, 1024)) {
167 final int b1 = inputStream.read();
168 final int b2 = inputStream.read();
169 assertEquals(-1, inputStream.read());
170
171 assertArrayEquals(expectedData, new byte[] {(byte) b1, (byte) b2});
172 }
173 }
174
175 @Test
176 void testSkipAtStart() throws IOException {
177
178 final Path file = createTestFile(100);
179 final byte[] expectedData = Files.readAllBytes(file);
180
181 try (InputStream inputStream = newInputStream(file, 10)) {
182 assertEquals(1, inputStream.skip(1));
183 final byte[] data = IOUtils.toByteArray(inputStream);
184
185 assertArrayEquals(Arrays.copyOfRange(expectedData, 1, expectedData.length), data);
186 }
187 }
188
189 @Test
190 void testSkipEmpty() throws IOException {
191
192 final Path file = createTestFile(0);
193
194 try (InputStream inputStream = newInputStream(file)) {
195 assertEquals(0, inputStream.skip(5));
196
197 assertArrayEquals(EMPTY_BYTE_ARRAY, IOUtils.toByteArray(inputStream));
198 }
199 }
200
201 @Test
202 void testSkipInCurrentBuffer() throws IOException {
203
204 final Path file = createTestFile(100);
205 final byte[] expectedData = Files.readAllBytes(file);
206
207 try (InputStream inputStream = newInputStream(file, 10)) {
208 IOUtils.toByteArray(inputStream, 5);
209 assertEquals(3, inputStream.skip(3));
210 final byte[] data = IOUtils.toByteArray(inputStream);
211
212 assertArrayEquals(Arrays.copyOfRange(expectedData, 8, expectedData.length), data);
213 }
214 }
215
216 @ParameterizedTest
217 @ValueSource(ints = {-5, -1, 0})
218 void testSkipNoop(final int amountToSkip) throws IOException {
219
220 final Path file = createTestFile(10);
221 final byte[] expectedData = Files.readAllBytes(file);
222
223 try (InputStream inputStream = newInputStream(file)) {
224 assertEquals(0, inputStream.skip(amountToSkip));
225
226 assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream));
227 }
228 }
229
230 @Test
231 void testSkipOutOfCurrentBuffer() throws IOException {
232
233 final Path file = createTestFile(100);
234 final byte[] expectedData = Files.readAllBytes(file);
235
236 try (InputStream inputStream = newInputStream(file, 10)) {
237 IOUtils.toByteArray(inputStream, 5);
238 assertEquals(6, inputStream.skip(6));
239 final byte[] data = IOUtils.toByteArray(inputStream);
240
241 assertArrayEquals(Arrays.copyOfRange(expectedData, 11, expectedData.length), data);
242 }
243 }
244
245 @Test
246 void testSkipPastEof() throws IOException {
247
248 final Path file = createTestFile(100);
249
250 try (InputStream inputStream = newInputStream(file, 10)) {
251 IOUtils.toByteArray(inputStream, 5);
252 assertEquals(95, inputStream.skip(96));
253
254 assertArrayEquals(EMPTY_BYTE_ARRAY, IOUtils.toByteArray(inputStream));
255 }
256 }
257
258 @Test
259 void testSkipToEndOfCurrentBuffer() throws IOException {
260
261 final Path file = createTestFile(100);
262 final byte[] expectedData = Files.readAllBytes(file);
263
264
265 try (InputStream inputStream = newInputStream(file, 10)) {
266 IOUtils.toByteArray(inputStream, 5);
267 assertEquals(5, inputStream.skip(5));
268 final byte[] data = IOUtils.toByteArray(inputStream);
269
270 assertArrayEquals(Arrays.copyOfRange(expectedData, 10, expectedData.length), data);
271 }
272 }
273
274 @Test
275 void testSkipToEndOfCurrentBufferBuilder() throws IOException {
276
277 final Path file = createTestFile(100);
278 final byte[] expectedData = Files.readAllBytes(file);
279
280 try (MemoryMappedFileInputStream inputStream = MemoryMappedFileInputStream.builder().setPath(file).setBufferSize(10).get()) {
281 assertEquals(10, inputStream.getBufferSize());
282 IOUtils.toByteArray(inputStream, 5);
283 assertEquals(5, inputStream.skip(5));
284 final byte[] data = IOUtils.toByteArray(inputStream);
285
286 assertArrayEquals(Arrays.copyOfRange(expectedData, 10, expectedData.length), data);
287 }
288 }
289
290 @Test
291 void testSmallFileBuilder() throws IOException {
292
293 final Path file = createTestFile(100);
294 final byte[] expectedData = Files.readAllBytes(file);
295
296 try (InputStream inputStream = MemoryMappedFileInputStream.builder().setFile(file.toFile()).get()) {
297
298 assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream));
299 }
300 }
301
302 @Test
303 void testSmallPath() throws IOException {
304
305 final Path file = createTestFile(100);
306 final byte[] expectedData = Files.readAllBytes(file);
307
308
309 try (InputStream inputStream = newInputStream(file)) {
310
311 assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream));
312 }
313 }
314
315 @Test
316 void testSmallPathBuilder() throws IOException {
317
318 final Path file = createTestFile(100);
319 final byte[] expectedData = Files.readAllBytes(file);
320
321 try (InputStream inputStream = MemoryMappedFileInputStream.builder().setPath(file).get()) {
322
323 assertArrayEquals(expectedData, IOUtils.toByteArray(inputStream));
324 }
325 }
326
327 }