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