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.io.IOUtils.EOF;
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertThrows;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24
25 import java.io.ByteArrayInputStream;
26 import java.nio.charset.StandardCharsets;
27 import java.util.concurrent.atomic.AtomicBoolean;
28
29 import org.apache.commons.io.IOUtils;
30 import org.apache.commons.lang3.mutable.MutableInt;
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.params.ParameterizedTest;
33 import org.junit.jupiter.params.provider.ValueSource;
34
35
36
37
38 public class BoundedInputStreamTest {
39
40 private void compare(final String message, final byte[] expected, final byte[] actual) {
41 assertEquals(expected.length, actual.length, () -> message + " (array length equals check)");
42 final MutableInt mi = new MutableInt();
43 for (int i = 0; i < expected.length; i++) {
44 mi.setValue(i);
45 assertEquals(expected[i], actual[i], () -> message + " byte[" + mi + "]");
46 }
47 }
48
49 @Test
50 public void testBuilderGet() {
51
52 assertThrows(IllegalStateException.class, () -> BoundedInputStream.builder().get());
53 }
54
55 @SuppressWarnings("deprecation")
56 @ParameterizedTest
57 @ValueSource(longs = { -100, -1, 0, 1, 2, 4, 8, 16, 32, 64 })
58 public void testCounts(final long startCount) throws Exception {
59
60 final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8);
61 final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8);
62 final long actualStart = startCount < 0 ? 0 : startCount;
63
64
65 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setCount(startCount)
66 .setMaxCount(helloWorld.length).get()) {
67 assertTrue(bounded.markSupported());
68 assertEquals(helloWorld.length, bounded.getMaxCount());
69 assertEquals(helloWorld.length, bounded.getMaxLength());
70 assertEquals(actualStart, bounded.getCount());
71 assertEquals(Math.max(0, bounded.getMaxCount() - actualStart), bounded.getRemaining());
72 assertEquals(Math.max(0, bounded.getMaxLength() - actualStart), bounded.getRemaining());
73 int readCount = 0;
74 for (int i = 0; i < helloWorld.length; i++) {
75 final byte expectedCh = bounded.getRemaining() > 0 ? helloWorld[i] : EOF;
76 final int actualCh = bounded.read();
77 assertEquals(expectedCh, actualCh, "limit = length byte[" + i + "]");
78 if (actualCh != EOF) {
79 readCount++;
80 }
81 assertEquals(helloWorld.length, bounded.getMaxCount());
82 assertEquals(helloWorld.length, bounded.getMaxLength());
83 assertEquals(actualStart + readCount, bounded.getCount(), "i=" + i);
84 assertEquals(Math.max(0, bounded.getMaxCount() - (readCount + actualStart)), bounded.getRemaining());
85 assertEquals(Math.max(0, bounded.getMaxLength() - (readCount + actualStart)), bounded.getRemaining());
86 }
87 assertEquals(-1, bounded.read(), "limit = length end");
88 assertEquals(helloWorld.length, bounded.getMaxLength());
89 assertEquals(readCount + actualStart, bounded.getCount());
90 assertEquals(0, bounded.getRemaining());
91 assertEquals(0, bounded.available());
92
93 assertTrue(bounded.markSupported());
94 }
95
96 final int maxCountP1 = helloWorld.length + 1;
97 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setCount(startCount)
98 .setMaxCount(maxCountP1).get()) {
99 assertTrue(bounded.markSupported());
100 assertEquals(maxCountP1, bounded.getMaxLength());
101 assertEquals(actualStart, bounded.getCount());
102 assertEquals(Math.max(0, bounded.getMaxCount() - actualStart), bounded.getRemaining());
103 assertEquals(Math.max(0, bounded.getMaxLength() - actualStart), bounded.getRemaining());
104 int readCount = 0;
105 for (int i = 0; i < helloWorld.length; i++) {
106 final byte expectedCh = bounded.getRemaining() > 0 ? helloWorld[i] : EOF;
107 final int actualCh = bounded.read();
108 assertEquals(expectedCh, actualCh, "limit = length byte[" + i + "]");
109 if (actualCh != EOF) {
110 readCount++;
111 }
112 assertEquals(maxCountP1, bounded.getMaxCount());
113 assertEquals(maxCountP1, bounded.getMaxLength());
114 assertEquals(actualStart + readCount, bounded.getCount(), "i=" + i);
115 assertEquals(Math.max(0, bounded.getMaxCount() - (readCount + actualStart)), bounded.getRemaining());
116 assertEquals(Math.max(0, bounded.getMaxLength() - (readCount + actualStart)), bounded.getRemaining());
117 }
118 assertEquals(-1, bounded.read(), "limit > length end");
119 assertEquals(0, bounded.available());
120 assertEquals(maxCountP1, bounded.getMaxLength());
121 assertEquals(readCount + actualStart, bounded.getCount());
122 assertEquals(Math.max(0, maxCountP1 - bounded.getCount()), bounded.getRemaining());
123
124 assertTrue(bounded.markSupported());
125 }
126
127 try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), hello.length)) {
128 assertTrue(bounded.markSupported());
129 assertEquals(hello.length, bounded.getMaxLength());
130 assertEquals(0, bounded.getCount());
131 assertEquals(bounded.getMaxLength(), bounded.getRemaining());
132 int readCount = 0;
133 for (int i = 0; i < hello.length; i++) {
134 assertEquals(hello[i], bounded.read(), "limit < length byte[" + i + "]");
135 readCount++;
136 assertEquals(hello.length, bounded.getMaxLength());
137 assertEquals(readCount, bounded.getCount());
138 assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining());
139 }
140 assertEquals(-1, bounded.read(), "limit < length end");
141 assertEquals(0, bounded.available());
142 assertEquals(hello.length, bounded.getMaxLength());
143 assertEquals(readCount, bounded.getCount());
144 assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining());
145
146 assertTrue(bounded.markSupported());
147 }
148 }
149
150 @Test
151 public void testMarkReset() throws Exception {
152 final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8);
153 final int helloWorldLen = helloWorld.length;
154 final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8);
155 final byte[] world = " World".getBytes(StandardCharsets.UTF_8);
156 final int helloLen = hello.length;
157
158 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).get()) {
159 assertTrue(bounded.markSupported());
160 bounded.mark(0);
161 compare("limit = -1", helloWorld, IOUtils.toByteArray(bounded));
162
163 assertTrue(bounded.markSupported());
164
165 bounded.reset();
166 compare("limit = -1", hello, IOUtils.toByteArray(bounded, helloLen));
167 bounded.mark(helloWorldLen);
168 compare("limit = -1", world, IOUtils.toByteArray(bounded));
169 bounded.reset();
170 compare("limit = -1", world, IOUtils.toByteArray(bounded));
171
172 assertTrue(bounded.markSupported());
173 }
174
175 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setMaxCount(0).get()) {
176 assertTrue(bounded.markSupported());
177 bounded.mark(0);
178 compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded));
179
180 assertTrue(bounded.markSupported());
181
182 bounded.reset();
183 compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded));
184 bounded.mark(helloWorldLen);
185 compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded));
186
187 assertTrue(bounded.markSupported());
188 }
189
190 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld))
191 .setMaxCount(helloWorld.length).get()) {
192 assertTrue(bounded.markSupported());
193 bounded.mark(0);
194 compare("limit = length", helloWorld, IOUtils.toByteArray(bounded));
195
196 assertTrue(bounded.markSupported());
197
198 bounded.reset();
199 compare("limit = length", hello, IOUtils.toByteArray(bounded, helloLen));
200 bounded.mark(helloWorldLen);
201 compare("limit = length", world, IOUtils.toByteArray(bounded));
202 bounded.reset();
203 compare("limit = length", world, IOUtils.toByteArray(bounded));
204
205 assertTrue(bounded.markSupported());
206 }
207
208 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld))
209 .setMaxCount(helloWorld.length + 1).get()) {
210 assertTrue(bounded.markSupported());
211 bounded.mark(0);
212 compare("limit > length", helloWorld, IOUtils.toByteArray(bounded));
213
214 assertTrue(bounded.markSupported());
215
216 bounded.reset();
217 compare("limit > length", helloWorld, IOUtils.toByteArray(bounded));
218 bounded.reset();
219 compare("limit > length", hello, IOUtils.toByteArray(bounded, helloLen));
220 bounded.mark(helloWorldLen);
221 compare("limit > length", world, IOUtils.toByteArray(bounded));
222 bounded.reset();
223 compare("limit > length", world, IOUtils.toByteArray(bounded));
224
225 assertTrue(bounded.markSupported());
226 }
227
228 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld))
229 .setMaxCount(helloWorld.length - (hello.length + 1)).get()) {
230 assertTrue(bounded.markSupported());
231 bounded.mark(0);
232 compare("limit < length", hello, IOUtils.toByteArray(bounded));
233
234 assertTrue(bounded.markSupported());
235
236 bounded.reset();
237 compare("limit < length", hello, IOUtils.toByteArray(bounded));
238 bounded.reset();
239 compare("limit < length", hello, IOUtils.toByteArray(bounded, helloLen));
240 bounded.mark(helloWorldLen);
241 compare("limit < length", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded));
242 bounded.reset();
243 compare("limit < length", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded));
244
245 assertTrue(bounded.markSupported());
246 }
247 }
248
249 @SuppressWarnings("deprecation")
250 @Test
251 public void testOnMaxLength() throws Exception {
252 final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8);
253 final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8);
254 final AtomicBoolean boolRef = new AtomicBoolean();
255
256 try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length) {
257 @Override
258 protected void onMaxLength(final long max, final long readCount) {
259 boolRef.set(true);
260 }
261 }) {
262 assertTrue(bounded.markSupported());
263 assertEquals(helloWorld.length, bounded.getMaxCount());
264 assertEquals(helloWorld.length, bounded.getMaxLength());
265 assertEquals(0, bounded.getCount());
266 assertEquals(bounded.getMaxCount(), bounded.getRemaining());
267 assertEquals(bounded.getMaxLength(), bounded.getRemaining());
268 assertFalse(boolRef.get());
269 int readCount = 0;
270 for (int i = 0; i < helloWorld.length; i++) {
271 assertEquals(helloWorld[i], bounded.read(), "limit = length byte[" + i + "]");
272 readCount++;
273 assertEquals(helloWorld.length, bounded.getMaxCount());
274 assertEquals(helloWorld.length, bounded.getMaxLength());
275 assertEquals(readCount, bounded.getCount());
276 assertEquals(bounded.getMaxCount() - readCount, bounded.getRemaining());
277 assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining());
278 }
279 assertEquals(-1, bounded.read(), "limit = length end");
280 assertEquals(0, bounded.available());
281 assertEquals(helloWorld.length, bounded.getMaxLength());
282 assertEquals(readCount, bounded.getCount());
283 assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining());
284 assertTrue(boolRef.get());
285
286 assertTrue(bounded.markSupported());
287 }
288
289 boolRef.set(false);
290 final int length2 = helloWorld.length + 1;
291 try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), length2) {
292 @Override
293 protected void onMaxLength(final long max, final long readCount) {
294 boolRef.set(true);
295 }
296 }) {
297 assertTrue(bounded.markSupported());
298 assertEquals(length2, bounded.getMaxLength());
299 assertEquals(0, bounded.getCount());
300 assertEquals(bounded.getMaxLength(), bounded.getRemaining());
301 assertFalse(boolRef.get());
302 int readCount = 0;
303 for (int i = 0; i < helloWorld.length; i++) {
304 assertEquals(helloWorld[i], bounded.read(), "limit > length byte[" + i + "]");
305 readCount++;
306 assertEquals(length2, bounded.getMaxLength());
307 assertEquals(readCount, bounded.getCount());
308 assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining());
309 }
310 assertEquals(0, bounded.available());
311 assertEquals(-1, bounded.read(), "limit > length end");
312 assertEquals(length2, bounded.getMaxLength());
313 assertEquals(readCount, bounded.getCount());
314 assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining());
315 assertFalse(boolRef.get());
316
317 assertTrue(bounded.markSupported());
318 }
319
320 boolRef.set(false);
321 try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), hello.length) {
322 @Override
323 protected void onMaxLength(final long max, final long readCount) {
324 boolRef.set(true);
325 }
326 }) {
327 assertTrue(bounded.markSupported());
328 assertEquals(hello.length, bounded.getMaxLength());
329 assertEquals(0, bounded.getCount());
330 assertEquals(bounded.getMaxLength(), bounded.getRemaining());
331 assertFalse(boolRef.get());
332 int readCount = 0;
333 for (int i = 0; i < hello.length; i++) {
334 assertEquals(hello[i], bounded.read(), "limit < length byte[" + i + "]");
335 readCount++;
336 assertEquals(hello.length, bounded.getMaxLength());
337 assertEquals(readCount, bounded.getCount());
338 assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining());
339 }
340 assertEquals(-1, bounded.read(), "limit < length end");
341 assertEquals(hello.length, bounded.getMaxLength());
342 assertEquals(readCount, bounded.getCount());
343 assertEquals(bounded.getMaxLength() - readCount, bounded.getRemaining());
344 assertTrue(boolRef.get());
345
346 assertTrue(bounded.markSupported());
347 }
348 }
349
350 @Test
351 public void testReadArray() throws Exception {
352 final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8);
353 final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8);
354 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).get()) {
355 assertTrue(bounded.markSupported());
356 compare("limit = -1", helloWorld, IOUtils.toByteArray(bounded));
357
358 assertTrue(bounded.markSupported());
359 }
360 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setMaxCount(0).get()) {
361 assertTrue(bounded.markSupported());
362 compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded));
363
364 assertTrue(bounded.markSupported());
365 }
366 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld))
367 .setMaxCount(helloWorld.length).get()) {
368 assertTrue(bounded.markSupported());
369 compare("limit = length", helloWorld, IOUtils.toByteArray(bounded));
370
371 assertTrue(bounded.markSupported());
372 }
373 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld))
374 .setMaxCount(helloWorld.length + 1).get()) {
375 assertTrue(bounded.markSupported());
376 compare("limit > length", helloWorld, IOUtils.toByteArray(bounded));
377
378 assertTrue(bounded.markSupported());
379 }
380 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld))
381 .setMaxCount(helloWorld.length - 6).get()) {
382 assertTrue(bounded.markSupported());
383 compare("limit < length", hello, IOUtils.toByteArray(bounded));
384
385 assertTrue(bounded.markSupported());
386 }
387 }
388
389 @SuppressWarnings("deprecation")
390 @Test
391 public void testReadSingle() throws Exception {
392 final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8);
393 final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8);
394
395 try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length)) {
396 assertTrue(bounded.markSupported());
397 for (int i = 0; i < helloWorld.length; i++) {
398 assertEquals(helloWorld[i], bounded.read(), "limit = length byte[" + i + "]");
399 }
400 assertEquals(-1, bounded.read(), "limit = length end");
401
402 assertTrue(bounded.markSupported());
403 }
404
405 try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), helloWorld.length + 1)) {
406 assertTrue(bounded.markSupported());
407 for (int i = 0; i < helloWorld.length; i++) {
408 assertEquals(helloWorld[i], bounded.read(), "limit > length byte[" + i + "]");
409 }
410 assertEquals(-1, bounded.read(), "limit > length end");
411
412 assertTrue(bounded.markSupported());
413 }
414
415 try (BoundedInputStream bounded = new BoundedInputStream(new ByteArrayInputStream(helloWorld), hello.length)) {
416 assertTrue(bounded.markSupported());
417 for (int i = 0; i < hello.length; i++) {
418 assertEquals(hello[i], bounded.read(), "limit < length byte[" + i + "]");
419 }
420 assertEquals(-1, bounded.read(), "limit < length end");
421
422 assertTrue(bounded.markSupported());
423 }
424 }
425
426 @Test
427 public void testReset() throws Exception {
428 final byte[] helloWorld = "Hello World".getBytes(StandardCharsets.UTF_8);
429 final byte[] hello = "Hello".getBytes(StandardCharsets.UTF_8);
430
431 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).get()) {
432 assertTrue(bounded.markSupported());
433 bounded.reset();
434 compare("limit = -1", helloWorld, IOUtils.toByteArray(bounded));
435
436 assertTrue(bounded.markSupported());
437
438 bounded.reset();
439 compare("limit = -1", helloWorld, IOUtils.toByteArray(bounded));
440
441 assertTrue(bounded.markSupported());
442 }
443
444 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld)).setMaxCount(0).get()) {
445 assertTrue(bounded.markSupported());
446 bounded.reset();
447 compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded));
448
449 assertTrue(bounded.markSupported());
450
451 bounded.reset();
452 compare("limit = 0", IOUtils.EMPTY_BYTE_ARRAY, IOUtils.toByteArray(bounded));
453
454 assertTrue(bounded.markSupported());
455 }
456
457 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld))
458 .setMaxCount(helloWorld.length).get()) {
459 assertTrue(bounded.markSupported());
460 bounded.reset();
461 compare("limit = length", helloWorld, IOUtils.toByteArray(bounded));
462
463 assertTrue(bounded.markSupported());
464
465 bounded.reset();
466 compare("limit = length", helloWorld, IOUtils.toByteArray(bounded));
467
468 assertTrue(bounded.markSupported());
469 }
470
471 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld))
472 .setMaxCount(helloWorld.length + 1).get()) {
473 assertTrue(bounded.markSupported());
474 bounded.reset();
475 compare("limit > length", helloWorld, IOUtils.toByteArray(bounded));
476
477 assertTrue(bounded.markSupported());
478
479 bounded.reset();
480 compare("limit > length", helloWorld, IOUtils.toByteArray(bounded));
481
482 assertTrue(bounded.markSupported());
483 }
484
485 try (BoundedInputStream bounded = BoundedInputStream.builder().setInputStream(new ByteArrayInputStream(helloWorld))
486 .setMaxCount(helloWorld.length - 6).get()) {
487 assertTrue(bounded.markSupported());
488 bounded.reset();
489 compare("limit < length", hello, IOUtils.toByteArray(bounded));
490
491 assertTrue(bounded.markSupported());
492
493 bounded.reset();
494 compare("limit < length", hello, IOUtils.toByteArray(bounded));
495
496 assertTrue(bounded.markSupported());
497 }
498 }
499 }