1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.io.input;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertThrows;
22 import static org.junit.jupiter.api.Assertions.assertTrue;
23
24 import java.io.ByteArrayInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.nio.charset.StandardCharsets;
29 import java.nio.file.Files;
30 import java.nio.file.Path;
31
32 import org.apache.commons.io.IOUtils;
33 import org.apache.commons.io.input.UnsynchronizedBufferedInputStream.Builder;
34 import org.apache.commons.lang3.StringUtils;
35 import org.junit.jupiter.api.AfterEach;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Test;
38
39
40
41
42
43
44
45 class UnsynchronizedBufferedInputStreamTest {
46
47 private static final int BUFFER_SIZE = 4096;
48
49 public static final String DATA = StringUtils.repeat("This is a test.", 500);
50
51 Path fileName;
52
53 private UnsynchronizedBufferedInputStream is;
54
55 private InputStream isFile;
56
57 byte[] ibuf = new byte[BUFFER_SIZE];
58
59 private Builder builder() {
60 return new UnsynchronizedBufferedInputStream.Builder();
61 }
62
63
64
65
66
67
68 @BeforeEach
69 protected void setUp() throws IOException {
70 fileName = Files.createTempFile(getClass().getSimpleName(), ".tst");
71 Files.write(fileName, DATA.getBytes(StandardCharsets.UTF_8));
72
73 isFile = Files.newInputStream(fileName);
74 is = builder().setInputStream(isFile).get();
75 }
76
77
78
79
80
81
82 @AfterEach
83 protected void tearDown() throws IOException {
84 IOUtils.closeQuietly(is);
85 Files.deleteIfExists(fileName);
86 }
87
88
89
90
91
92
93 @Test
94 void test_available() throws IOException {
95 assertEquals(DATA.length(), is.available(), "Returned incorrect number of available bytes");
96
97
98 final UnsynchronizedBufferedInputStream bis = builder()
99 .setInputStream(new ByteArrayInputStream(new byte[] { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' })).get();
100 final int available = bis.available();
101 bis.close();
102 assertTrue(available != 0);
103
104 assertThrows(IOException.class, () -> bis.available(), "Expected test to throw IOE.");
105 }
106
107
108
109
110
111
112 @Test
113 void test_close() throws IOException {
114 builder().setInputStream(isFile).get().close();
115
116 try (InputStream in = new InputStream() {
117 Object lock = new Object();
118
119 @Override
120 public void close() {
121 synchronized (lock) {
122 lock.notifyAll();
123 }
124 }
125
126 @Override
127 public int read() {
128 return 1;
129 }
130
131 @Override
132 public int read(final byte[] buf, final int offset, final int length) {
133 synchronized (lock) {
134 try {
135 lock.wait(3000);
136 } catch (final InterruptedException e) {
137
138 }
139 }
140 return 1;
141 }
142 }) {
143 final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(in).get();
144 final Thread thread = new Thread(() -> {
145 try {
146 Thread.sleep(1000);
147 bufin.close();
148 } catch (final Exception e) {
149
150 }
151 });
152 thread.start();
153 assertThrows(IOException.class, () -> bufin.read(new byte[100], 0, 99), "Should throw IOException");
154 }
155 }
156
157
158
159
160 @Test
161 void test_ConstructorLjava_io_InputStream() {
162 assertThrows(NullPointerException.class, () -> builder().setInputStream(null).get());
163 }
164
165
166
167
168 @Test
169 void test_ConstructorLjava_io_InputStreamI() throws IOException {
170 assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(1).get());
171
172
173
174
175 is = builder().setInputStream(isFile).setBufferSize(DATA.length()).get();
176
177 is.read();
178
179
180 isFile.close();
181
182
183 is.skip(DATA.length() - 2);
184 is.read();
185
186 assertThrows(IOException.class, () -> is.read());
187
188 assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(100).get());
189 assertThrows(NullPointerException.class, () -> builder().setInputStream(null));
190 }
191
192
193
194
195
196
197 @Test
198 void test_markI() throws IOException {
199 final byte[] buf1 = new byte[100];
200 final byte[] buf2 = new byte[100];
201 is.skip(3000);
202 is.mark(1000);
203 is.read(buf1, 0, buf1.length);
204 is.reset();
205 is.read(buf2, 0, buf2.length);
206 is.reset();
207 assertTrue(new String(buf1, 0, buf1.length).equals(new String(buf2, 0, buf2.length)), "Failed to mark correct position");
208
209 byte[] bytes = new byte[256];
210 for (int i = 0; i < 256; i++) {
211 bytes[i] = (byte) i;
212 }
213 InputStream in = builder().setInputStream(new ByteArrayInputStream(bytes)).setBufferSize(12).get();
214 in.skip(6);
215 in.mark(14);
216 in.read(new byte[14], 0, 14);
217 in.reset();
218 assertTrue(in.read() == 6 && in.read() == 7, "Wrong bytes");
219
220 in = builder().setInputStream(new ByteArrayInputStream(bytes)).setBufferSize(12).get();
221 in.skip(6);
222 in.mark(8);
223 in.skip(7);
224 in.reset();
225 assertTrue(in.read() == 6 && in.read() == 7, "Wrong bytes 2");
226
227 UnsynchronizedBufferedInputStream buf = builder().setInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 })).setBufferSize(2).get();
228 buf.mark(3);
229 bytes = new byte[3];
230 int result = buf.read(bytes);
231 assertEquals(3, result);
232 assertEquals(0, bytes[0], "Assert 0:");
233 assertEquals(1, bytes[1], "Assert 1:");
234 assertEquals(2, bytes[2], "Assert 2:");
235 assertEquals(3, buf.read(), "Assert 3:");
236
237 buf = builder().setInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 })).setBufferSize(2).get();
238 buf.mark(3);
239 bytes = new byte[4];
240 result = buf.read(bytes);
241 assertEquals(4, result);
242 assertEquals(0, bytes[0], "Assert 4:");
243 assertEquals(1, bytes[1], "Assert 5:");
244 assertEquals(2, bytes[2], "Assert 6:");
245 assertEquals(3, bytes[3], "Assert 7:");
246 assertEquals(4, buf.read(), "Assert 8:");
247 assertEquals(-1, buf.read(), "Assert 9:");
248
249 buf = builder().setInputStream(new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4 })).setBufferSize(2).get();
250 buf.mark(Integer.MAX_VALUE);
251 buf.read();
252 buf.close();
253 }
254
255
256
257
258 @Test
259 void test_markSupported() {
260 assertTrue(is.markSupported(), "markSupported returned incorrect value");
261 }
262
263
264
265
266
267
268 @Test
269 void test_read() throws IOException {
270 final InputStreamReader isr = new InputStreamReader(is);
271 final int c = isr.read();
272 assertEquals(DATA.charAt(0), c, "read returned incorrect char");
273
274 final byte[] bytes = new byte[256];
275 for (int i = 0; i < 256; i++) {
276 bytes[i] = (byte) i;
277 }
278 final InputStream in = builder().setInputStream(new ByteArrayInputStream(bytes)).setBufferSize(12).get();
279 assertEquals(0, in.read(), "Wrong initial byte");
280 final byte[] buf = new byte[14];
281 in.read(buf, 0, 14);
282 assertTrue(new String(buf, 0, 14).equals(new String(bytes, 1, 14)), "Wrong block read data");
283 assertEquals(15, in.read(), "Wrong bytes");
284 }
285
286
287
288
289
290
291 @Test
292 void test_read$BII() throws IOException {
293 final byte[] buf1 = new byte[100];
294 is.skip(3000);
295 is.mark(1000);
296 is.read(buf1, 0, buf1.length);
297 assertTrue(new String(buf1, 0, buf1.length).equals(DATA.substring(3000, 3100)), "Failed to read correct data");
298
299 try (UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new InputStream() {
300 int size = 2;
301 int pos;
302
303 byte[] contents = new byte[size];
304
305 @Override
306 public int available() {
307 return size - pos;
308 }
309
310 @Override
311 public int read() throws IOException {
312 if (pos >= size) {
313 throw new IOException("Read past end of data");
314 }
315 return contents[pos++];
316 }
317
318 @Override
319 public int read(final byte[] buf, final int off, final int len) throws IOException {
320 if (pos >= size) {
321 throw new IOException("Read past end of data");
322 }
323 int toRead = len;
324 if (toRead > available()) {
325 toRead = available();
326 }
327 System.arraycopy(contents, pos, buf, off, toRead);
328 pos += toRead;
329 return toRead;
330 }
331 }).get()) {
332 bufin.read();
333 final int result = bufin.read(new byte[2], 0, 2);
334 assertEquals(1, result, () -> "Incorrect result: " + result);
335 }
336 }
337
338
339
340
341
342
343 @Test
344 void test_reset() throws IOException {
345 final byte[] buf1 = new byte[10];
346 final byte[] buf2 = new byte[10];
347 is.mark(2000);
348 is.read(buf1, 0, 10);
349 is.reset();
350 is.read(buf2, 0, 10);
351 is.reset();
352 assertTrue(new String(buf1, 0, buf1.length).equals(new String(buf2, 0, buf2.length)), "Reset failed");
353
354 final UnsynchronizedBufferedInputStream bIn = builder().setInputStream(new ByteArrayInputStream("1234567890".getBytes())).get();
355 bIn.mark(10);
356 for (int i = 0; i < 11; i++) {
357 bIn.read();
358 }
359 bIn.reset();
360 }
361
362
363
364
365
366
367 @Test
368 void test_reset_scenario1() throws IOException {
369 final byte[] input = "12345678900".getBytes();
370 final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new ByteArrayInputStream(input)).get();
371 bufin.read();
372 bufin.mark(5);
373 bufin.skip(5);
374 bufin.reset();
375 }
376
377
378
379
380
381
382 @Test
383 void test_reset_scenario2() throws IOException {
384 final byte[] input = "12345678900".getBytes();
385 final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new ByteArrayInputStream(input)).get();
386 bufin.mark(5);
387 bufin.skip(6);
388 bufin.reset();
389 }
390
391
392
393
394
395
396 @Test
397 void test_skip_NullInputStream() throws IOException {
398 assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(5).get());
399 }
400
401
402
403
404
405
406 @Test
407 void test_skipJ() throws IOException {
408 final byte[] buf1 = new byte[10];
409 is.mark(2000);
410 is.skip(1000);
411 is.read(buf1, 0, buf1.length);
412 is.reset();
413 assertTrue(new String(buf1, 0, buf1.length).equals(DATA.substring(1000, 1010)), "Failed to skip to correct position");
414 }
415 }