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.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.IOException;
26  import java.io.Reader;
27  import java.io.StringReader;
28  import java.util.ArrayList;
29  import java.util.Collection;
30  import java.util.List;
31  
32  import org.apache.commons.lang3.StringUtils;
33  import org.junit.jupiter.api.Test;
34  
35  /**
36   * Test case for {@link SequenceReader}.
37   */
38  public class SequenceReaderTest {
39  
40      private static class CustomReader extends Reader {
41  
42          boolean closed;
43  
44          protected void checkOpen() throws IOException {
45              if (closed) {
46                  throw new IOException("emptyReader already closed");
47              }
48          }
49  
50          @Override
51          public void close() throws IOException {
52              closed = true;
53          }
54  
55          public boolean isClosed() {
56              return closed;
57          }
58  
59          @Override
60          public int read(final char[] cbuf, final int off, final int len) throws IOException {
61              checkOpen();
62              close();
63              return EOF;
64          }
65      }
66  
67      private static final char NUL = 0;
68  
69      private void checkArray(final char[] expected, final char[] actual) {
70          for (int i = 0; i < expected.length; i++) {
71              assertEquals(expected[i], actual[i], "Compare[" + i + "]");
72          }
73      }
74  
75      private void checkRead(final Reader reader, final String expected) throws IOException {
76          for (int i = 0; i < expected.length(); i++) {
77              assertEquals(expected.charAt(i), (char) reader.read(), "Read[" + i + "] of '" + expected + "'");
78          }
79      }
80  
81      private void checkReadEof(final Reader reader) throws IOException {
82          for (int i = 0; i < 10; i++) {
83              assertEquals(-1, reader.read());
84          }
85      }
86  
87      @Test
88      public void testAutoClose() throws IOException {
89          try (Reader reader = new SequenceReader(new CharSequenceReader("FooBar"))) {
90              checkRead(reader, "Foo");
91              reader.close();
92              checkReadEof(reader);
93          }
94      }
95  
96      @Test
97      public void testClose() throws IOException {
98          final Reader reader = new SequenceReader(new CharSequenceReader("FooBar"));
99          checkRead(reader, "Foo");
100         reader.close();
101         checkReadEof(reader);
102     }
103 
104     @Test
105     public void testCloseReaders() throws IOException {
106         final CustomReader reader0 = new CustomReader();
107         final CustomReader reader1 = new CustomReader() {
108 
109             private final char[] content = {'A'};
110             private int position;
111 
112             @Override
113             public int read(final char[] cbuf, final int off, final int len) throws IOException {
114                 checkOpen();
115 
116                 if (off < 0) {
117                     throw new IndexOutOfBoundsException("off is negative");
118                 }
119                 if (len < 0) {
120                     throw new IndexOutOfBoundsException("len is negative");
121                 }
122                 if (len > cbuf.length - off) {
123                     throw new IndexOutOfBoundsException("len is greater than cbuf.length - off");
124                 }
125 
126                 if (position > 0) {
127                     return EOF;
128                 }
129 
130                 cbuf[off] = content[0];
131                 position++;
132                 return 1;
133             }
134 
135         };
136 
137         try (SequenceReader sequenceReader = new SequenceReader(reader1, reader0)) {
138             assertEquals('A', sequenceReader.read());
139             assertEquals(EOF, sequenceReader.read());
140         } finally {
141             assertTrue(reader1.isClosed());
142             assertTrue(reader0.isClosed());
143         }
144         assertTrue(reader1.isClosed());
145         assertTrue(reader0.isClosed());
146 
147     }
148 
149     @Test
150     public void testMarkSupported() throws Exception {
151         try (Reader reader = new SequenceReader()) {
152             assertFalse(reader.markSupported());
153         }
154     }
155 
156     @Test
157     public void testRead() throws IOException {
158         try (Reader reader = new SequenceReader(new StringReader("Foo"), new StringReader("Bar"))) {
159             assertEquals('F', reader.read());
160             assertEquals('o', reader.read());
161             assertEquals('o', reader.read());
162             assertEquals('B', reader.read());
163             assertEquals('a', reader.read());
164             assertEquals('r', reader.read());
165             checkReadEof(reader);
166         }
167     }
168 
169     @Test
170     public void testReadCharArray() throws IOException {
171         try (Reader reader = new SequenceReader(new StringReader("Foo"), new StringReader("Bar"))) {
172             char[] chars = new char[2];
173             assertEquals(2, reader.read(chars));
174             checkArray(new char[] { 'F', 'o' }, chars);
175             chars = new char[3];
176             assertEquals(3, reader.read(chars));
177             checkArray(new char[] { 'o', 'B', 'a' }, chars);
178             chars = new char[3];
179             assertEquals(1, reader.read(chars));
180             checkArray(new char[] { 'r', NUL, NUL }, chars);
181             assertEquals(-1, reader.read(chars));
182         }
183     }
184 
185     @Test
186     public void testReadCharArrayPortion() throws IOException {
187         final char[] chars = new char[10];
188         try (Reader reader = new SequenceReader(new StringReader("Foo"), new StringReader("Bar"))) {
189             assertEquals(3, reader.read(chars, 3, 3));
190             checkArray(new char[] { NUL, NUL, NUL, 'F', 'o', 'o' }, chars);
191             assertEquals(3, reader.read(chars, 0, 3));
192             checkArray(new char[] { 'B', 'a', 'r', 'F', 'o', 'o', NUL }, chars);
193             assertEquals(-1, reader.read(chars));
194             assertThrows(IndexOutOfBoundsException.class, () -> reader.read(chars, 10, 10));
195             assertThrows(NullPointerException.class, () -> reader.read(null, 0, 10));
196         }
197     }
198 
199     @Test
200     public void testReadClosedReader() throws IOException {
201         @SuppressWarnings("resource")
202         final Reader reader = new SequenceReader(new CharSequenceReader("FooBar"));
203         reader.close();
204         checkReadEof(reader);
205     }
206 
207     @Test
208     public void testReadCollection() throws IOException {
209         final Collection<Reader> readers = new ArrayList<>();
210         readers.add(new StringReader("F"));
211         readers.add(new StringReader("B"));
212         try (Reader reader = new SequenceReader(readers)) {
213             assertEquals('F', reader.read());
214             assertEquals('B', reader.read());
215             checkReadEof(reader);
216         }
217     }
218 
219     @Test
220     public void testReadIterable() throws IOException {
221         final Collection<Reader> readers = new ArrayList<>();
222         readers.add(new StringReader("F"));
223         readers.add(new StringReader("B"));
224         final Iterable<Reader> iterable = readers;
225         try (Reader reader = new SequenceReader(iterable)) {
226             assertEquals('F', reader.read());
227             assertEquals('B', reader.read());
228             checkReadEof(reader);
229         }
230     }
231 
232     @Test
233     public void testReadLength0Readers() throws IOException {
234         try (Reader reader = new SequenceReader(new StringReader(StringUtils.EMPTY),
235             new StringReader(StringUtils.EMPTY), new StringReader(StringUtils.EMPTY))) {
236             checkReadEof(reader);
237         }
238     }
239 
240     @Test
241     public void testReadLength1Readers() throws IOException {
242         try (Reader reader = new SequenceReader(
243         // @formatter:off
244             new StringReader("0"),
245             new StringReader("1"),
246             new StringReader("2"),
247             new StringReader("3"))) {
248             // @formatter:on
249             assertEquals('0', reader.read());
250             assertEquals('1', reader.read());
251             assertEquals('2', reader.read());
252             assertEquals('3', reader.read());
253         }
254     }
255 
256     @Test
257     public void testReadList() throws IOException {
258         final List<Reader> readers = new ArrayList<>();
259         readers.add(new StringReader("F"));
260         readers.add(new StringReader("B"));
261         try (Reader reader = new SequenceReader(readers)) {
262             assertEquals('F', reader.read());
263             assertEquals('B', reader.read());
264             checkReadEof(reader);
265         }
266     }
267 
268     @Test
269     public void testSkip() throws IOException {
270         try (Reader reader = new SequenceReader(new StringReader("Foo"), new StringReader("Bar"))) {
271             assertEquals(3, reader.skip(3));
272             checkRead(reader, "Bar");
273             assertEquals(0, reader.skip(3));
274         }
275     }
276 }