View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.io.input;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertTimeout;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.io.BufferedReader;
26  import java.io.File;
27  import java.io.IOException;
28  import java.io.LineNumberReader;
29  import java.io.Reader;
30  import java.io.StringReader;
31  import java.nio.charset.StandardCharsets;
32  import java.nio.file.Files;
33  import java.time.Duration;
34  import java.util.Arrays;
35  import java.util.concurrent.atomic.AtomicBoolean;
36  
37  import org.apache.commons.io.FileUtils;
38  import org.apache.commons.io.file.TempFile;
39  import org.junit.jupiter.api.Test;
40  
41  /**
42   * Tests {@link BoundedReader}.
43   */
44  public class BoundedReaderTest {
45  
46      private static final Duration TIMEOUT = Duration.ofSeconds(10);
47  
48      private static final String STRING_END_NO_EOL = "0\n1\n2";
49  
50      private static final String STRING_END_EOL = "0\n1\n2\n";
51  
52      private final Reader sr = new BufferedReader(new StringReader("01234567890"));
53  
54      private final Reader shortReader = new BufferedReader(new StringReader("01"));
55  
56      @Test
57      public void testCloseTest() throws IOException {
58          final AtomicBoolean closed = new AtomicBoolean();
59          try (Reader sr = new BufferedReader(new StringReader("01234567890")) {
60              @Override
61              public void close() throws IOException {
62                  closed.set(true);
63                  super.close();
64              }
65          }) {
66  
67              try (BoundedReader mr = new BoundedReader(sr, 3)) {
68                  // nothing
69              }
70          }
71          assertTrue(closed.get());
72      }
73  
74      private void testLineNumberReader(final Reader source) throws IOException {
75          try (LineNumberReader reader = new LineNumberReader(new BoundedReader(source, 10_000_000))) {
76              while (reader.readLine() != null) {
77                  // noop
78              }
79          }
80      }
81  
82      public void testLineNumberReaderAndFileReaderLastLine(final String data) throws IOException {
83          try (TempFile path = TempFile.create(getClass().getSimpleName(), ".txt")) {
84              final File file = path.toFile();
85              FileUtils.write(file, data, StandardCharsets.ISO_8859_1);
86              try (Reader source = Files.newBufferedReader(file.toPath())) {
87                  testLineNumberReader(source);
88              }
89          }
90      }
91  
92      @Test
93      public void testLineNumberReaderAndFileReaderLastLineEolNo() {
94          assertTimeout(TIMEOUT, () -> testLineNumberReaderAndFileReaderLastLine(STRING_END_NO_EOL));
95      }
96  
97      @Test
98      public void testLineNumberReaderAndFileReaderLastLineEolYes() {
99          assertTimeout(TIMEOUT, () -> testLineNumberReaderAndFileReaderLastLine(STRING_END_EOL));
100     }
101 
102     @Test
103     public void testLineNumberReaderAndStringReaderLastLineEolNo() {
104         assertTimeout(TIMEOUT, () -> testLineNumberReader(new StringReader(STRING_END_NO_EOL)));
105     }
106 
107     @Test
108     public void testLineNumberReaderAndStringReaderLastLineEolYes() {
109         assertTimeout(TIMEOUT, () -> testLineNumberReader(new StringReader(STRING_END_EOL)));
110     }
111 
112     @Test
113     public void testMarkReset() throws IOException {
114         try (BoundedReader mr = new BoundedReader(sr, 3)) {
115             mr.mark(3);
116             mr.read();
117             mr.read();
118             mr.read();
119             mr.reset();
120             mr.read();
121             mr.read();
122             mr.read();
123             assertEquals(-1, mr.read());
124         }
125     }
126 
127     @Test
128     public void testMarkResetFromOffset1() throws IOException {
129         try (BoundedReader mr = new BoundedReader(sr, 3)) {
130             mr.mark(3);
131             mr.read();
132             mr.read();
133             mr.read();
134             assertEquals(-1, mr.read());
135             mr.reset();
136             mr.mark(1);
137             mr.read();
138             assertEquals(-1, mr.read());
139         }
140     }
141 
142     @Test
143     public void testMarkResetMarkMore() throws IOException {
144         try (BoundedReader mr = new BoundedReader(sr, 3)) {
145             mr.mark(4);
146             mr.read();
147             mr.read();
148             mr.read();
149             mr.reset();
150             mr.read();
151             mr.read();
152             mr.read();
153             assertEquals(-1, mr.read());
154         }
155     }
156 
157     @Test
158     public void testMarkResetWithMarkOutsideBoundedReaderMax() throws IOException {
159         try (BoundedReader mr = new BoundedReader(sr, 3)) {
160             mr.mark(4);
161             mr.read();
162             mr.read();
163             mr.read();
164             assertEquals(-1, mr.read());
165         }
166     }
167 
168     @Test
169     public void testMarkResetWithMarkOutsideBoundedReaderMaxAndInitialOffset() throws IOException {
170         try (BoundedReader mr = new BoundedReader(sr, 3)) {
171             mr.read();
172             mr.mark(3);
173             mr.read();
174             mr.read();
175             assertEquals(-1, mr.read());
176         }
177     }
178 
179     @Test
180     public void testReadBytesEOF() {
181         assertTimeout(TIMEOUT, () -> {
182             final BoundedReader mr = new BoundedReader(sr, 3);
183             try (BufferedReader br = new BufferedReader(mr)) {
184                 br.readLine();
185                 br.readLine();
186             }
187         });
188     }
189 
190     @Test
191     public void testReadMulti() throws IOException {
192         try (BoundedReader mr = new BoundedReader(sr, 3)) {
193             final char[] cbuf = new char[4];
194             Arrays.fill(cbuf, 'X');
195             final int read = mr.read(cbuf, 0, 4);
196             assertEquals(3, read);
197             assertEquals('0', cbuf[0]);
198             assertEquals('1', cbuf[1]);
199             assertEquals('2', cbuf[2]);
200             assertEquals('X', cbuf[3]);
201         }
202     }
203 
204     @Test
205     public void testReadMultiWithOffset() throws IOException {
206         try (BoundedReader mr = new BoundedReader(sr, 3)) {
207             final char[] cbuf = new char[4];
208             Arrays.fill(cbuf, 'X');
209             final int read = mr.read(cbuf, 1, 2);
210             assertEquals(2, read);
211             assertEquals('X', cbuf[0]);
212             assertEquals('0', cbuf[1]);
213             assertEquals('1', cbuf[2]);
214             assertEquals('X', cbuf[3]);
215         }
216     }
217 
218     @Test
219     public void testReadTillEnd() throws IOException {
220         try (BoundedReader mr = new BoundedReader(sr, 3)) {
221             mr.read();
222             mr.read();
223             mr.read();
224             assertEquals(-1, mr.read());
225         }
226     }
227 
228     @Test
229     public void testShortReader() throws IOException {
230         try (BoundedReader mr = new BoundedReader(shortReader, 3)) {
231             mr.read();
232             mr.read();
233             assertEquals(-1, mr.read());
234         }
235     }
236 
237     @Test
238     public void testSkipTest() throws IOException {
239         try (BoundedReader mr = new BoundedReader(sr, 3)) {
240             mr.skip(2);
241             mr.read();
242             assertEquals(-1, mr.read());
243         }
244     }
245 }