View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *     https://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.commons.io.input;
19  
20  import static org.apache.commons.io.IOUtils.EOF;
21  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.io.ByteArrayInputStream;
28  import java.io.CharArrayReader;
29  import java.io.IOException;
30  import java.io.InputStreamReader;
31  import java.io.PipedReader;
32  import java.io.Reader;
33  import java.io.StringReader;
34  import java.util.function.Supplier;
35  
36  import org.apache.commons.io.IOUtils;
37  import org.junit.jupiter.api.AfterEach;
38  import org.junit.jupiter.api.Test;
39  
40  /**
41   * Tests {@link UnsynchronizedBufferedReader}.
42   * <p>
43   * Provenance: Apache Harmony {@code BufferedReaderTest}, copied, and modified.
44   * </p>
45   */
46  class UnsynchronizedBufferedReaderTest {
47  
48      private UnsynchronizedBufferedReader br;
49  
50      private final String testString = "Test_All_Tests\nTest_java_io_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\n"
51              + "Test_java_io_ByteArrayOutputStream\nTest_java_io_DataInputStream\nTest_java_io_File\nTest_java_io_FileDescriptor\nTest_java_io_FileInputStream\n"
52              + "Test_java_io_FileNotFoundException\nTest_java_io_FileOutputStream\nTest_java_io_FilterInputStream\nTest_java_io_FilterOutputStream\n"
53              + "Test_java_io_InputStream\nTest_java_io_IOException\nTest_java_io_OutputStream\nTest_java_io_PrintStream\nTest_java_io_RandomAccessFile\n"
54              + "Test_java_io_SyncFailedException\nTest_java_lang_AbstractMethodError\nTest_java_lang_ArithmeticException\n"
55              + "Test_java_lang_ArrayIndexOutOfBoundsException\nTest_java_lang_ArrayStoreException\nTest_java_lang_Boolean\nTest_java_lang_Byte\n"
56              + "Test_java_lang_Character\nTest_java_lang_Class\nTest_java_lang_ClassCastException\nTest_java_lang_ClassCircularityError\n"
57              + "Test_java_lang_ClassFormatError\nTest_java_lang_ClassLoader\nTest_java_lang_ClassNotFoundException\nTest_java_lang_CloneNotSupportedException\n"
58              + "Test_java_lang_Double\nTest_java_lang_Error\nTest_java_lang_Exception\nTest_java_lang_ExceptionInInitializerError\nTest_java_lang_Float\n"
59              + "Test_java_lang_IllegalAccessError\nTest_java_lang_IllegalAccessException\nTest_java_lang_IllegalArgumentException\n"
60              + "Test_java_lang_IllegalMonitorStateException\nTest_java_lang_IllegalThreadStateException\nTest_java_lang_IncompatibleClassChangeError\n"
61              + "Test_java_lang_IndexOutOfBoundsException\nTest_java_lang_InstantiationError\nTest_java_lang_InstantiationException\nTest_java_lang_Integer\n"
62              + "Test_java_lang_InternalError\nTest_java_lang_InterruptedException\nTest_java_lang_LinkageError\nTest_java_lang_Long\nTest_java_lang_Math\n"
63              + "Test_java_lang_NegativeArraySizeException\nTest_java_lang_NoClassDefFoundError\nTest_java_lang_NoSuchFieldError\n"
64              + "Test_java_lang_NoSuchMethodError\nTest_java_lang_NullPointerException\nTest_java_lang_Number\nTest_java_lang_NumberFormatException\n"
65              + "Test_java_lang_Object\nTest_java_lang_OutOfMemoryError\nTest_java_lang_RuntimeException\nTest_java_lang_SecurityManager\nTest_java_lang_Short\n"
66              + "Test_java_lang_StackOverflowError\nTest_java_lang_String\nTest_java_lang_StringBuffer\nTest_java_lang_StringIndexOutOfBoundsException\n"
67              + "Test_java_lang_System\nTest_java_lang_Thread\nTest_java_lang_ThreadDeath\nTest_java_lang_ThreadGroup\nTest_java_lang_Throwable\n"
68              + "Test_java_lang_UnknownError\nTest_java_lang_UnsatisfiedLinkError\nTest_java_lang_VerifyError\nTest_java_lang_VirtualMachineError\n"
69              + "Test_java_lang_vm_Image\nTest_java_lang_vm_MemorySegment\nTest_java_lang_vm_ROMStoreException\nTest_java_lang_vm_VM\nTest_java_lang_Void\n"
70              + "Test_java_net_BindException\nTest_java_net_ConnectException\nTest_java_net_DatagramPacket\nTest_java_net_DatagramSocket\n"
71              + "Test_java_net_DatagramSocketImpl\nTest_java_net_InetAddress\nTest_java_net_NoRouteToHostException\nTest_java_net_PlainDatagramSocketImpl\n"
72              + "Test_java_net_PlainSocketImpl\nTest_java_net_Socket\nTest_java_net_SocketException\nTest_java_net_SocketImpl\nTest_java_net_SocketInputStream\n"
73              + "Test_java_net_SocketOutputStream\nTest_java_net_UnknownHostException\nTest_java_util_ArrayEnumerator\nTest_java_util_Date\n"
74              + "Test_java_util_EventObject\nTest_java_util_HashEnumerator\nTest_java_util_Hashtable\nTest_java_util_Properties\nTest_java_util_ResourceBundle\n"
75              + "Test_java_util_tm\nTest_java_util_Vector\n";
76  
77      /**
78       * Tears down the fixture, for example, close a network connection. This method is called after a test is executed.
79       */
80      @AfterEach
81      protected void afterEach() {
82          IOUtils.closeQuietly(br);
83      }
84  
85      private void assertLines(final String input, final String... lines) throws IOException {
86          assertReadLines(input, lines);
87          assertPeek(input, lines);
88      }
89  
90      private void assertPeek(final String input, final String... lines) throws IOException {
91          try (UnsynchronizedBufferedReader bufferedReader = new UnsynchronizedBufferedReader(new StringReader(input))) {
92              for (final String line : lines) {
93                  // all
94                  final char[] bufAFull = new char[line.length()];
95                  assertEquals(bufAFull.length, bufferedReader.peek(bufAFull));
96                  assertArrayEquals(line.toCharArray(), bufAFull);
97                  if (!line.isEmpty()) {
98                      // one
99                      assertEquals(line.charAt(0), bufferedReader.peek());
100                     // array
101                     for (int peekLen = 0; peekLen < line.length(); peekLen++) {
102                         assertPeekArray(bufferedReader, peekLen, line);
103                     }
104                 }
105                 // move test to the next fixture
106                 assertEquals(line, bufferedReader.readLine());
107             }
108             assertNull(bufferedReader.readLine());
109         }
110     }
111 
112     private void assertPeekArray(final UnsynchronizedBufferedReader bufferedReader, final int peekLen, final String line) throws IOException {
113         final char[] expectedBuf = new char[peekLen];
114         final int srcPeekLen = Math.min(peekLen, line.length());
115         line.getChars(0, srcPeekLen, expectedBuf, 0);
116         final char[] actualBuf = new char[peekLen];
117         final Supplier<String> msg = () -> String.format("len=%,d, line='%s'", peekLen, line);
118         assertEquals(actualBuf.length, bufferedReader.peek(actualBuf), msg);
119         assertArrayEquals(expectedBuf, actualBuf, msg);
120     }
121 
122     private void assertReadLines(final String input, final String... lines) throws IOException {
123         try (UnsynchronizedBufferedReader bufferedReader = new UnsynchronizedBufferedReader(new StringReader(input))) {
124             for (final String line : lines) {
125                 assertEquals(line, bufferedReader.readLine());
126             }
127             assertNull(bufferedReader.readLine());
128         }
129     }
130 
131     /**
132      * Tests {@link UnsynchronizedBufferedReader#close()}.
133      *
134      * @throws IOException test failure.
135      */
136     @Test
137     void testClose() throws IOException {
138         // Test for method void UnsynchronizedBufferedReader.close()
139         br = new UnsynchronizedBufferedReader(new StringReader(testString));
140         br.close();
141         assertThrows(IOException.class, br::read);
142     }
143 
144     @Test
145     void testEmptyInput() throws Exception {
146         try (UnsynchronizedBufferedReader br = new UnsynchronizedBufferedReader(new StringReader(""))) {
147             assertEquals(EOF, br.read());
148             assertEquals(EOF, br.peek());
149             assertNull(br.readLine());
150             assertEquals(0, br.read(new char[10], 0, 0));
151         }
152     }
153 
154     /**
155      * Tests {@link UnsynchronizedBufferedReader#mark(int)}.
156      *
157      * @throws IOException test failure.
158      */
159     @Test
160     void testMark() throws IOException {
161         // Test for method void UnsynchronizedBufferedReader.mark(int)
162         char[] buf = null;
163         br = new UnsynchronizedBufferedReader(new StringReader(testString));
164         br.skip(500);
165         br.mark(1000);
166         br.skip(250);
167         br.reset();
168         buf = new char[testString.length()];
169         br.read(buf, 0, 500);
170         assertTrue(testString.substring(500, 1000).equals(new String(buf, 0, 500)));
171 
172         br = new UnsynchronizedBufferedReader(new StringReader(testString), 800);
173         br.skip(500);
174         br.mark(250);
175         br.read(buf, 0, 1000);
176         assertThrows(IOException.class, br::reset);
177 
178         final char[] chars = new char[256];
179         for (int i = 0; i < 256; i++) {
180             chars[i] = (char) i;
181         }
182 
183         try (Reader in = new UnsynchronizedBufferedReader(new StringReader(new String(chars)), 12)) {
184             in.skip(6);
185             in.mark(14);
186             in.read(new char[14], 0, 14);
187             in.reset();
188             assertTrue(in.read() == (char) 6 && in.read() == (char) 7);
189         }
190         try (Reader in = new UnsynchronizedBufferedReader(new StringReader(new String(chars)), 12)) {
191             in.skip(6);
192             in.mark(8);
193             in.skip(7);
194             in.reset();
195             assertTrue(in.read() == (char) 6 && in.read() == (char) 7);
196         }
197         try (UnsynchronizedBufferedReader br = new UnsynchronizedBufferedReader(new StringReader("01234"), 2)) {
198             br.mark(3);
199             final char[] carray = new char[3];
200             final int result = br.read(carray);
201             assertEquals(3, result);
202             assertEquals('0', carray[0]);
203             assertEquals('1', carray[1]);
204             assertEquals('2', carray[2]);
205             assertEquals('3', br.read());
206         }
207         try (UnsynchronizedBufferedReader br = new UnsynchronizedBufferedReader(new StringReader("01234"), 2)) {
208             br.mark(3);
209             final char[] carray = new char[4];
210             final int result = br.read(carray);
211             assertEquals(4, result);
212             assertEquals('0', carray[0]);
213             assertEquals('1', carray[1]);
214             assertEquals('2', carray[2]);
215             assertEquals('3', carray[3]);
216             assertEquals('4', br.read());
217             assertEquals(-1, br.read());
218         }
219         try (UnsynchronizedBufferedReader reader = new UnsynchronizedBufferedReader(new StringReader("01234"))) {
220             reader.mark(Integer.MAX_VALUE);
221             reader.read();
222         }
223     }
224 
225     /**
226      * Tests {@link UnsynchronizedBufferedReader#markSupported()}.
227      */
228     @Test
229     void testMarkSupported() {
230         // Test for method boolean UnsynchronizedBufferedReader.markSupported()
231         br = new UnsynchronizedBufferedReader(new StringReader(testString));
232         assertTrue(br.markSupported());
233     }
234 
235     /**
236      * Tests {@link UnsynchronizedBufferedReader#peek()}.
237      *
238      * @throws IOException test failure.
239      */
240     @Test
241     void testPeek() throws IOException {
242         // Test for method int UnsynchronizedBufferedReader.read()
243         br = new UnsynchronizedBufferedReader(new StringReader(testString));
244         final int p = br.peek();
245         assertEquals(testString.charAt(0), p);
246         final int r = br.read();
247         assertEquals(testString.charAt(0), r);
248         br = new UnsynchronizedBufferedReader(new StringReader(new String(new char[] { '\u8765' })));
249         assertEquals(br.peek(), '\u8765');
250         assertEquals(br.read(), '\u8765');
251         // chars '\0'...'\255'
252         final char[] chars = new char[256];
253         for (int i = 0; i < 256; i++) {
254             chars[i] = (char) i;
255         }
256         try (UnsynchronizedBufferedReader in = new UnsynchronizedBufferedReader(new StringReader(new String(chars)), 12)) {
257             assertEquals(0, in.peek()); // Fill the buffer
258             assertEquals(0, in.read()); // Fill the buffer
259             final char[] buf = new char[14];
260             in.read(buf, 0, 14); // Read greater than the buffer
261             assertTrue(new String(buf).equals(new String(chars, 1, 14)));
262             assertEquals(15, in.peek()); // Check next byte
263             assertEquals(15, in.read()); // Check next byte
264         }
265         //
266         // regression test for HARMONY-841
267         try (UnsynchronizedBufferedReader reader = new UnsynchronizedBufferedReader(new CharArrayReader(new char[5], 1, 0), 2)) {
268             assertEquals(reader.peek(), -1);
269             assertEquals(reader.read(), -1);
270         }
271     }
272 
273     /**
274      * Tests {@link UnsynchronizedBufferedReader#peek()}.
275      *
276      * @throws IOException test failure.
277      */
278     @Test
279     void testPeekArray() throws IOException {
280         // Test for method int UnsynchronizedBufferedReader.read()
281         final char[] peekBuf1 = new char[1];
282         br = new UnsynchronizedBufferedReader(new StringReader(testString));
283         assertEquals(peekBuf1.length, br.peek(peekBuf1));
284         assertEquals(testString.charAt(0), peekBuf1[0]);
285         final int r = br.read();
286         assertEquals(testString.charAt(0), r);
287         br = new UnsynchronizedBufferedReader(new StringReader(new String(new char[] { '\u8765' })));
288         assertEquals(peekBuf1.length, br.peek(peekBuf1));
289         assertEquals(peekBuf1[0], '\u8765');
290         assertEquals(br.read(), '\u8765');
291         // chars '\0'...'\255'
292         final char[] chars = new char[256];
293         for (int i = 0; i < 256; i++) {
294             chars[i] = (char) i;
295         }
296         try (UnsynchronizedBufferedReader in = new UnsynchronizedBufferedReader(new StringReader(new String(chars)), 12)) {
297             assertEquals(peekBuf1.length, in.peek(peekBuf1)); // Fill the buffer
298             assertEquals(peekBuf1[0], 0);
299             assertEquals(0, in.read()); // Fill the buffer
300             final char[] peekBuf14 = new char[14];
301             assertEquals(peekBuf14.length, in.peek(peekBuf14)); // Peek greater than the buffer
302             assertTrue(new String(peekBuf14).equals(new String(chars, 1, 14)));
303             final char[] buf = new char[14];
304             in.read(buf, 0, 14); // Read greater than the buffer
305             assertTrue(new String(buf).equals(new String(chars, 1, 14)));
306             assertEquals(peekBuf1.length, in.peek(peekBuf1)); // Check next byte
307             assertEquals(15, peekBuf1[0]);
308             assertEquals(15, in.read()); // Check next byte
309         }
310         //
311         // regression test for HARMONY-841
312         try (UnsynchronizedBufferedReader reader = new UnsynchronizedBufferedReader(new CharArrayReader(new char[5], 1, 0), 2)) {
313             assertEquals(reader.peek(), -1);
314             assertEquals(reader.read(), -1);
315         }
316     }
317 
318     /**
319      * Tests {@link UnsynchronizedBufferedReader#read()}.
320      *
321      * @throws IOException test failure.
322      */
323     @Test
324     void testRead() throws IOException {
325         // Test for method int UnsynchronizedBufferedReader.read()
326         br = new UnsynchronizedBufferedReader(new StringReader(testString));
327         final int r = br.read();
328         assertEquals(testString.charAt(0), r);
329         br = new UnsynchronizedBufferedReader(new StringReader(new String(new char[] { '\u8765' })));
330         assertEquals(br.read(), '\u8765');
331         //
332         final char[] chars = new char[256];
333         for (int i = 0; i < 256; i++) {
334             chars[i] = (char) i;
335         }
336         try (Reader in = new UnsynchronizedBufferedReader(new StringReader(new String(chars)), 12)) {
337             assertEquals(0, in.read()); // Fill the buffer
338             final char[] buf = new char[14];
339             in.read(buf, 0, 14); // Read greater than the buffer
340             assertTrue(new String(buf).equals(new String(chars, 1, 14)));
341             assertEquals(15, in.read()); // Check next byte
342         }
343         //
344         // regression test for HARMONY-841
345         try (Reader reader = new UnsynchronizedBufferedReader(new CharArrayReader(new char[5], 1, 0), 2)) {
346             assertEquals(reader.read(), -1);
347         }
348     }
349 
350     /**
351      * Tests {@link UnsynchronizedBufferedReader#read(char[], int, int)}.
352      *
353      * @throws IOException test failure.
354      */
355     @Test
356     void testReadArray() throws IOException {
357         final char[] ca = new char[2];
358         try (UnsynchronizedBufferedReader toRet = new UnsynchronizedBufferedReader(new InputStreamReader(new ByteArrayInputStream(new byte[0])))) {
359             /* Null buffer should throw NPE even when len == 0 */
360             assertThrows(NullPointerException.class, () -> toRet.read(null, 1, 0));
361             toRet.close();
362             assertThrows(IOException.class, () -> toRet.read(null, 1, 0));
363             /* Closed reader should throw IOException reading zero bytes */
364             assertThrows(IOException.class, () -> toRet.read(ca, 0, 0));
365             /*
366              * Closed reader should throw IOException in preference to index out of bounds
367              */
368             // Read should throw IOException before
369             // ArrayIndexOutOfBoundException
370             assertThrows(IOException.class, () -> toRet.read(ca, 1, 5));
371         }
372         // Test to ensure that a drained stream returns 0 at EOF
373         try (UnsynchronizedBufferedReader toRet2 = new UnsynchronizedBufferedReader(new InputStreamReader(new ByteArrayInputStream(new byte[2])))) {
374             assertEquals(2, toRet2.read(ca, 0, 2));
375             assertEquals(-1, toRet2.read(ca, 0, 2));
376             assertEquals(0, toRet2.read(ca, 0, 0));
377         }
378 
379         // Test for method int UnsynchronizedBufferedReader.read(char [], int, int)
380         final char[] buf = new char[testString.length()];
381         br = new UnsynchronizedBufferedReader(new StringReader(testString));
382         br.read(buf, 50, 500);
383         assertTrue(new String(buf, 50, 500).equals(testString.substring(0, 500)));
384 
385         try (UnsynchronizedBufferedReader bufin = new UnsynchronizedBufferedReader(new Reader() {
386             int size = 2;
387             int pos;
388 
389             char[] contents = new char[size];
390 
391             @Override
392             public void close() throws IOException {
393                 // Empty
394             }
395 
396             @Override
397             public int read() throws IOException {
398                 if (pos >= size) {
399                     throw new IOException("Read past end of data");
400                 }
401                 return contents[pos++];
402             }
403 
404             @Override
405             public int read(final char[] buf, final int off, final int len) throws IOException {
406                 if (pos >= size) {
407                     throw new IOException("Read past end of data");
408                 }
409                 int toRead = len;
410                 if (toRead > size - pos) {
411                     toRead = size - pos;
412                 }
413                 System.arraycopy(contents, pos, buf, off, toRead);
414                 pos += toRead;
415                 return toRead;
416             }
417 
418             @Override
419             public boolean ready() throws IOException {
420                 return size - pos > 0;
421             }
422         })) {
423             bufin.read();
424             final int result = bufin.read(new char[2], 0, 2);
425             assertEquals(result, 1);
426         }
427         // regression for HARMONY-831
428         try (Reader reader = new UnsynchronizedBufferedReader(new PipedReader(), 9)) {
429             assertThrows(IndexOutOfBoundsException.class, () -> reader.read(new char[] {}, 7, 0));
430         }
431 
432         // Regression for HARMONY-54
433         final char[] ch = {};
434         @SuppressWarnings("resource")
435         final UnsynchronizedBufferedReader reader = new UnsynchronizedBufferedReader(new CharArrayReader(ch));
436         // Check exception thrown when the reader is open.
437         assertThrows(NullPointerException.class, () -> reader.read(null, 1, 0));
438 
439         // Now check IOException is thrown in preference to
440         // NullPointerexception when the reader is closed.
441         reader.close();
442         assertThrows(IOException.class, () -> reader.read(null, 1, 0));
443 
444         // And check that the IOException is thrown before
445         // ArrayIndexOutOfBoundException
446         assertThrows(IOException.class, () -> reader.read(ch, 0, 42));
447     }
448 
449     /**
450      * Tests {@link UnsynchronizedBufferedReader#read(char[], int, int)}.
451      *
452      * @throws IOException test failure.
453      */
454     @Test
455     void testReadArrayException() throws IOException {
456         br = new UnsynchronizedBufferedReader(new StringReader(testString));
457         final char[] nullCharArray = null;
458         final char[] charArray = testString.toCharArray();
459         assertThrows(IndexOutOfBoundsException.class, () -> br.read(nullCharArray, -1, -1));
460         assertThrows(IndexOutOfBoundsException.class, () -> br.read(nullCharArray, -1, 0));
461         assertThrows(NullPointerException.class, () -> br.read(nullCharArray, 0, -1));
462         assertThrows(NullPointerException.class, () -> br.read(nullCharArray, 0, 0));
463         assertThrows(NullPointerException.class, () -> br.read(nullCharArray, 0, 1));
464         assertThrows(IndexOutOfBoundsException.class, () -> br.read(charArray, -1, -1));
465         assertThrows(IndexOutOfBoundsException.class, () -> br.read(charArray, -1, 0));
466 
467         br.read(charArray, 0, 0);
468         br.read(charArray, 0, charArray.length);
469         br.read(charArray, charArray.length, 0);
470 
471         assertThrows(IndexOutOfBoundsException.class, () -> br.read(charArray, charArray.length + 1, 0));
472         assertThrows(IndexOutOfBoundsException.class, () -> br.read(charArray, charArray.length + 1, 1));
473 
474         br.close();
475 
476         assertThrows(IOException.class, () -> br.read(nullCharArray, -1, -1));
477         assertThrows(IOException.class, () -> br.read(charArray, -1, 0));
478         assertThrows(IOException.class, () -> br.read(charArray, 0, -1));
479     }
480 
481     /**
482      * Tests {@link UnsynchronizedBufferedReader#readLine()}.
483      *
484      * @throws IOException test failure.
485      */
486     @Test
487     void testReadLine() throws IOException {
488         // Test for method java.lang.String UnsynchronizedBufferedReader.readLine()
489         br = new UnsynchronizedBufferedReader(new StringReader(testString));
490         final String r = br.readLine();
491         assertEquals("Test_All_Tests", r);
492     }
493 
494     /**
495      * The spec says that BufferedReader.readLine() considers only "\r", "\n" and "\r\n" to be line separators. We must not permit additional separator
496      * characters.
497      *
498      * @throws IOException test failure.
499      */
500     @Test
501     void testReadLineIgnoresEbcdic85Characters() throws IOException {
502         assertLines("A\u0085B", "A\u0085B");
503     }
504 
505     @Test
506     void testReadLineSeparators() throws IOException {
507         assertLines("A\nB\nC", "A", "B", "C");
508         assertLines("A\rB\rC", "A", "B", "C");
509         assertLines("A\r\nB\r\nC", "A", "B", "C");
510         assertLines("A\n\rB\n\rC", "A", "", "B", "", "C");
511         assertLines("A\n\nB\n\nC", "A", "", "B", "", "C");
512         assertLines("A\r\rB\r\rC", "A", "", "B", "", "C");
513         assertLines("A\n\n", "A", "");
514         assertLines("A\n\r", "A", "");
515         assertLines("A\r\r", "A", "");
516         assertLines("A\r\n", "A");
517         assertLines("A\r\n\r\n", "A", "");
518     }
519 
520     /**
521      * Tests {@link UnsynchronizedBufferedReader#ready()}.
522      *
523      * @throws IOException test failure.
524      */
525     @Test
526     void testReady() throws IOException {
527         // Test for method boolean UnsynchronizedBufferedReader.ready()
528         br = new UnsynchronizedBufferedReader(new StringReader(testString));
529         assertTrue(br.ready());
530     }
531 
532     /**
533      * Tests {@link UnsynchronizedBufferedReader#reset()}.
534      *
535      * @throws IOException test failure.
536      */
537     @Test
538     void testReset() throws IOException {
539         // Test for method void UnsynchronizedBufferedReader.reset()
540         br = new UnsynchronizedBufferedReader(new StringReader(testString));
541         br.skip(500);
542         br.mark(900);
543         br.skip(500);
544         br.reset();
545         final char[] buf = new char[testString.length()];
546         br.read(buf, 0, 500);
547         assertTrue(testString.substring(500, 1000).equals(new String(buf, 0, 500)));
548         br = new UnsynchronizedBufferedReader(new StringReader(testString));
549         br.skip(500);
550         assertThrows(IOException.class, br::reset);
551     }
552 
553     @Test
554     void testReset_IOException() throws Exception {
555         final int[] expected = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', -1 };
556         br = new UnsynchronizedBufferedReader(new StringReader("1234567890"), 9);
557         br.mark(9);
558         for (int i = 0; i < 11; i++) {
559             assertEquals(expected[i], br.read());
560         }
561         assertThrows(IOException.class, br::reset);
562         for (int i = 0; i < 11; i++) {
563             assertEquals(-1, br.read());
564         }
565 
566         br = new UnsynchronizedBufferedReader(new StringReader("1234567890"));
567         br.mark(10);
568         for (int i = 0; i < 10; i++) {
569             assertEquals(expected[i], br.read());
570         }
571         br.reset();
572         for (int i = 0; i < 11; i++) {
573             assertEquals(expected[i], br.read());
574         }
575     }
576 
577     /**
578      * Tests {@link UnsynchronizedBufferedReader#skip(long)}.
579      *
580      * @throws IOException test failure.
581      */
582     @Test
583     void testSkip() throws IOException {
584         // Test for method long UnsynchronizedBufferedReader.skip(long)
585         br = new UnsynchronizedBufferedReader(new StringReader(testString));
586         br.skip(500);
587         final char[] buf = new char[testString.length()];
588         br.read(buf, 0, 500);
589         assertTrue(testString.substring(500, 1000).equals(new String(buf, 0, 500)));
590     }
591 }