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    *      http://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  package org.apache.commons.io.input;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
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.ByteArrayOutputStream;
26  import java.io.IOException;
27  import java.io.ObjectInputStream;
28  import java.io.ObjectOutputStream;
29  import java.io.Reader;
30  import java.nio.CharBuffer;
31  import java.util.Arrays;
32  
33  import org.apache.commons.io.TestResources;
34  import org.junit.jupiter.api.Test;
35  
36  /**
37   * Test case for {@link CharSequenceReader}.
38   */
39  public class CharSequenceReaderTest {
40      private static final char NONE = (new char[1])[0];
41  
42      private void checkArray(final char[] expected, final char[] actual) {
43          for (int i = 0; i < expected.length; i++) {
44              assertEquals(expected[i], actual[i], "Compare[" +i + "]");
45          }
46      }
47  
48      private void checkRead(final Reader reader, final String expected) throws IOException {
49          for (int i = 0; i < expected.length(); i++) {
50              assertEquals(expected.charAt(i), (char) reader.read(), "Read[" + i + "] of '" + expected + "'");
51          }
52      }
53  
54      @Test
55      public void testClose() throws IOException {
56          final Reader reader = new CharSequenceReader("FooBar");
57          checkRead(reader, "Foo");
58          reader.close();
59          checkRead(reader, "Foo");
60  
61          final Reader subReader = new CharSequenceReader("xFooBarx", 1, 7);
62          checkRead(subReader, "Foo");
63          subReader.close();
64          checkRead(subReader, "Foo");
65      }
66  
67      @Test
68      public void testConstructor() {
69          assertThrows(IllegalArgumentException.class, () -> new CharSequenceReader("FooBar", -1, 6),
70                  "Expected exception not thrown for negative start.");
71          assertThrows(IllegalArgumentException.class, () -> new CharSequenceReader("FooBar", 1, 0),
72                  "Expected exception not thrown for end before start.");
73      }
74  
75      @Test
76      public void testMark() throws IOException {
77          try (Reader reader = new CharSequenceReader("FooBar")) {
78              checkRead(reader, "Foo");
79              reader.mark(0);
80              checkRead(reader, "Bar");
81              reader.reset();
82              checkRead(reader, "Bar");
83              reader.close();
84              checkRead(reader, "Foo");
85              reader.reset();
86              checkRead(reader, "Foo");
87          }
88          try (Reader subReader = new CharSequenceReader("xFooBarx", 1, 7)) {
89              checkRead(subReader, "Foo");
90              subReader.mark(0);
91              checkRead(subReader, "Bar");
92              subReader.reset();
93              checkRead(subReader, "Bar");
94              subReader.close();
95              checkRead(subReader, "Foo");
96              subReader.reset();
97              checkRead(subReader, "Foo");
98          }
99      }
100 
101     @Test
102     public void testMarkSupported() throws Exception {
103         try (Reader reader = new CharSequenceReader("FooBar")) {
104             assertTrue(reader.markSupported());
105         }
106     }
107 
108     @Test
109     public void testRead() throws IOException {
110         final String value = "Foo";
111         testRead(value);
112         testRead(new StringBuilder(value));
113         testRead(new StringBuffer(value));
114         testRead(CharBuffer.wrap(value));
115     }
116 
117     private void testRead(final CharSequence charSequence) throws IOException {
118         try (Reader reader = new CharSequenceReader(charSequence)) {
119             assertEquals('F', reader.read());
120             assertEquals('o', reader.read());
121             assertEquals('o', reader.read());
122             assertEquals(-1, reader.read());
123             assertEquals(-1, reader.read());
124         }
125         try (Reader reader = new CharSequenceReader(charSequence, 1, 5)) {
126             assertEquals('o', reader.read());
127             assertEquals('o', reader.read());
128             assertEquals(-1, reader.read());
129             assertEquals(-1, reader.read());
130         }
131     }
132 
133     @Test
134     public void testReadCharArray() throws IOException {
135         final String value = "FooBar";
136         testReadCharArray(value);
137         testReadCharArray(new StringBuilder(value));
138         testReadCharArray(new StringBuffer(value));
139         testReadCharArray(CharBuffer.wrap(value));
140     }
141 
142     private void testReadCharArray(final CharSequence charSequence) throws IOException {
143         try (Reader reader = new CharSequenceReader(charSequence)) {
144             char[] chars = new char[2];
145             assertEquals(2, reader.read(chars));
146             checkArray(new char[] { 'F', 'o' }, chars);
147             chars = new char[3];
148             assertEquals(3, reader.read(chars));
149             checkArray(new char[] { 'o', 'B', 'a' }, chars);
150             chars = new char[3];
151             assertEquals(1, reader.read(chars));
152             checkArray(new char[] { 'r', NONE, NONE }, chars);
153             assertEquals(-1, reader.read(chars));
154         }
155         try (Reader reader = new CharSequenceReader(charSequence, 1, 5)) {
156             char[] chars = new char[2];
157             assertEquals(2, reader.read(chars));
158             checkArray(new char[] { 'o', 'o' }, chars);
159             chars = new char[3];
160             assertEquals(2, reader.read(chars));
161             checkArray(new char[] { 'B', 'a', NONE }, chars);
162             chars = new char[3];
163             assertEquals(-1, reader.read(chars));
164             checkArray(new char[] { NONE, NONE, NONE }, chars);
165             assertEquals(-1, reader.read(chars));
166         }
167     }
168 
169     @Test
170     public void testReadCharArrayPortion() throws IOException {
171         final String value = "FooBar";
172         testReadCharArrayPortion(value);
173         testReadCharArrayPortion(new StringBuilder(value));
174         testReadCharArrayPortion(new StringBuffer(value));
175         testReadCharArrayPortion(CharBuffer.wrap(value));
176     }
177 
178     private void testReadCharArrayPortion(final CharSequence charSequence) throws IOException {
179         final char[] chars = new char[10];
180         try (Reader reader = new CharSequenceReader(charSequence)) {
181             assertEquals(3, reader.read(chars, 3, 3));
182             checkArray(new char[] { NONE, NONE, NONE, 'F', 'o', 'o' }, chars);
183             assertEquals(3, reader.read(chars, 0, 3));
184             checkArray(new char[] { 'B', 'a', 'r', 'F', 'o', 'o', NONE }, chars);
185             assertEquals(-1, reader.read(chars));
186         }
187         Arrays.fill(chars, NONE);
188         try (Reader reader = new CharSequenceReader(charSequence, 1, 5)) {
189             assertEquals(2, reader.read(chars, 3, 2));
190             checkArray(new char[] { NONE, NONE, NONE, 'o', 'o', NONE }, chars);
191             assertEquals(2, reader.read(chars, 0, 3));
192             checkArray(new char[] { 'B', 'a', NONE, 'o', 'o', NONE }, chars);
193             assertEquals(-1, reader.read(chars));
194         }
195     }
196 
197     @Test
198     public void testReady() throws IOException {
199         final Reader reader = new CharSequenceReader("FooBar");
200         assertTrue(reader.ready());
201         reader.skip(3);
202         assertTrue(reader.ready());
203         checkRead(reader, "Bar");
204         assertFalse(reader.ready());
205         reader.reset();
206         assertTrue(reader.ready());
207         reader.skip(2);
208         assertTrue(reader.ready());
209         reader.skip(10);
210         assertFalse(reader.ready());
211         reader.close();
212         assertTrue(reader.ready());
213         reader.skip(20);
214         assertFalse(reader.ready());
215 
216         final Reader subReader = new CharSequenceReader("xFooBarx", 1, 7);
217         assertTrue(subReader.ready());
218         subReader.skip(3);
219         assertTrue(subReader.ready());
220         checkRead(subReader, "Bar");
221         assertFalse(subReader.ready());
222         subReader.reset();
223         assertTrue(subReader.ready());
224         subReader.skip(2);
225         assertTrue(subReader.ready());
226         subReader.skip(10);
227         assertFalse(subReader.ready());
228         subReader.close();
229         assertTrue(subReader.ready());
230         subReader.skip(20);
231         assertFalse(subReader.ready());
232     }
233 
234     @Test
235     public void testSerialization() throws IOException, ClassNotFoundException {
236         /*
237          * File CharSequenceReader.bin contains a CharSequenceReader that was serialized before
238          * the start and end fields were added. Its CharSequence is "FooBar".
239          * This part of the test will test that adding the fields does not break any existing
240          * serialized CharSequenceReaders.
241          */
242         try (ObjectInputStream ois = new ObjectInputStream(TestResources.getInputStream("CharSequenceReader.bin"))) {
243             final CharSequenceReader reader = (CharSequenceReader) ois.readObject();
244             assertEquals('F', reader.read());
245             assertEquals('o', reader.read());
246             assertEquals('o', reader.read());
247             assertEquals('B', reader.read());
248             assertEquals('a', reader.read());
249             assertEquals('r', reader.read());
250             assertEquals(-1, reader.read());
251             assertEquals(-1, reader.read());
252         }
253 
254         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
255         try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
256             final CharSequenceReader reader = new CharSequenceReader("xFooBarx", 1, 7);
257             oos.writeObject(reader);
258         }
259         try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
260             final CharSequenceReader reader = (CharSequenceReader) ois.readObject();
261             assertEquals('F', reader.read());
262             assertEquals('o', reader.read());
263             assertEquals('o', reader.read());
264             assertEquals('B', reader.read());
265             assertEquals('a', reader.read());
266             assertEquals('r', reader.read());
267             assertEquals(-1, reader.read());
268             assertEquals(-1, reader.read());
269             reader.reset();
270             assertEquals('F', reader.read());
271             assertEquals('o', reader.read());
272             assertEquals('o', reader.read());
273             assertEquals('B', reader.read());
274             assertEquals('a', reader.read());
275             assertEquals('r', reader.read());
276             assertEquals(-1, reader.read());
277             assertEquals(-1, reader.read());
278         }
279     }
280 
281     @Test
282     public void testSkip() throws IOException {
283         final Reader reader = new CharSequenceReader("FooBar");
284         assertEquals(3, reader.skip(3));
285         checkRead(reader, "Bar");
286         assertEquals(0, reader.skip(3));
287         reader.reset();
288         assertEquals(2, reader.skip(2));
289         assertEquals(4, reader.skip(10));
290         assertEquals(0, reader.skip(1));
291         reader.close();
292         assertEquals(6, reader.skip(20));
293         assertEquals(-1, reader.read());
294 
295         final Reader subReader = new CharSequenceReader("xFooBarx", 1, 7);
296         assertEquals(3, subReader.skip(3));
297         checkRead(subReader, "Bar");
298         assertEquals(0, subReader.skip(3));
299         subReader.reset();
300         assertEquals(2, subReader.skip(2));
301         assertEquals(4, subReader.skip(10));
302         assertEquals(0, subReader.skip(1));
303         subReader.close();
304         assertEquals(6, subReader.skip(20));
305         assertEquals(-1, subReader.read());
306     }
307 
308     @Test
309     @SuppressWarnings("resource") // don't really need to close CharSequenceReader here
310     public void testToString() {
311         assertEquals("FooBar", new CharSequenceReader("FooBar").toString());
312         assertEquals("FooBar", new CharSequenceReader("xFooBarx", 1, 7).toString());
313     }
314 }