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 public 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 public 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 public 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 public void test_ConstructorLjava_io_InputStream() {
162 assertThrows(NullPointerException.class, () -> builder().setInputStream(null).get());
163 }
164
165
166
167
168 @Test
169 public 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 public 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 public void test_markSupported() {
260 assertTrue(is.markSupported(), "markSupported returned incorrect value");
261 }
262
263
264
265
266
267
268 @Test
269 public 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 public 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, pos = 0;
301
302 byte[] contents = new byte[size];
303
304 @Override
305 public int available() {
306 return size - pos;
307 }
308
309 @Override
310 public int read() throws IOException {
311 if (pos >= size) {
312 throw new IOException("Read past end of data");
313 }
314 return contents[pos++];
315 }
316
317 @Override
318 public int read(final byte[] buf, final int off, final int len) throws IOException {
319 if (pos >= size) {
320 throw new IOException("Read past end of data");
321 }
322 int toRead = len;
323 if (toRead > available()) {
324 toRead = available();
325 }
326 System.arraycopy(contents, pos, buf, off, toRead);
327 pos += toRead;
328 return toRead;
329 }
330 }).get()) {
331 bufin.read();
332 final int result = bufin.read(new byte[2], 0, 2);
333 assertEquals(1, result, () -> "Incorrect result: " + result);
334 }
335 }
336
337
338
339
340
341
342 @Test
343 public void test_reset() throws IOException {
344 final byte[] buf1 = new byte[10];
345 final byte[] buf2 = new byte[10];
346 is.mark(2000);
347 is.read(buf1, 0, 10);
348 is.reset();
349 is.read(buf2, 0, 10);
350 is.reset();
351 assertTrue(new String(buf1, 0, buf1.length).equals(new String(buf2, 0, buf2.length)), "Reset failed");
352
353 final UnsynchronizedBufferedInputStream bIn = builder().setInputStream(new ByteArrayInputStream("1234567890".getBytes())).get();
354 bIn.mark(10);
355 for (int i = 0; i < 11; i++) {
356 bIn.read();
357 }
358 bIn.reset();
359 }
360
361
362
363
364
365
366 @Test
367 public void test_reset_scenario1() throws IOException {
368 final byte[] input = "12345678900".getBytes();
369 final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new ByteArrayInputStream(input)).get();
370 bufin.read();
371 bufin.mark(5);
372 bufin.skip(5);
373 bufin.reset();
374 }
375
376
377
378
379
380
381 @Test
382 public void test_reset_scenario2() throws IOException {
383 final byte[] input = "12345678900".getBytes();
384 final UnsynchronizedBufferedInputStream bufin = builder().setInputStream(new ByteArrayInputStream(input)).get();
385 bufin.mark(5);
386 bufin.skip(6);
387 bufin.reset();
388 }
389
390
391
392
393
394
395 @Test
396 public void test_skip_NullInputStream() throws IOException {
397 assertThrows(NullPointerException.class, () -> builder().setInputStream(null).setBufferSize(5).get());
398 }
399
400
401
402
403
404
405 @Test
406 public void test_skipJ() throws IOException {
407 final byte[] buf1 = new byte[10];
408 is.mark(2000);
409 is.skip(1000);
410 is.read(buf1, 0, buf1.length);
411 is.reset();
412 assertTrue(new String(buf1, 0, buf1.length).equals(DATA.substring(1000, 1010)), "Failed to skip to correct position");
413 }
414 }