1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.io;
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.assertNotNull;
22 import static org.junit.jupiter.api.Assertions.assertThrows;
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.Reader;
29 import java.io.StringReader;
30 import java.nio.charset.StandardCharsets;
31 import java.nio.charset.UnsupportedCharsetException;
32 import java.nio.file.Files;
33 import java.nio.file.NoSuchFileException;
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.NoSuchElementException;
37
38 import org.junit.jupiter.api.Test;
39 import org.junit.jupiter.api.io.TempDir;
40
41
42
43
44 public class LineIteratorTest {
45
46 private static final String UTF_8 = StandardCharsets.UTF_8.name();
47
48 @TempDir
49 public File temporaryFolder;
50
51 private void assertLines(final List<String> lines, final LineIterator iterator) {
52 try {
53 for (int i = 0; i < lines.size(); i++) {
54 final String line = iterator.nextLine();
55 assertEquals(lines.get(i), line, "nextLine() line " + i);
56 }
57 assertFalse(iterator.hasNext(), "No more expected");
58 } finally {
59 IOUtils.closeQuietly(iterator);
60 }
61 }
62
63
64
65
66
67
68
69
70
71 private List<String> createLinesFile(final File file, final int lineCount) throws IOException {
72 final List<String> lines = createStringLines(lineCount);
73 FileUtils.writeLines(file, lines);
74 return lines;
75 }
76
77
78
79
80
81
82
83
84
85
86 private List<String> createLinesFile(final File file, final String encoding, final int lineCount) throws IOException {
87 final List<String> lines = createStringLines(lineCount);
88 FileUtils.writeLines(file, encoding, lines);
89 return lines;
90 }
91
92
93
94
95
96
97
98 private List<String> createStringLines(final int lineCount) {
99 final List<String> lines = new ArrayList<>();
100 for (int i = 0; i < lineCount; i++) {
101 lines.add("LINE " + i);
102 }
103 return lines;
104 }
105
106
107
108
109
110
111
112
113 private void doTestFileWithSpecifiedLines(final int lineCount) throws IOException {
114 final String encoding = UTF_8;
115
116 final String fileName = "LineIterator-" + lineCount + "-test.txt";
117 final File testFile = new File(temporaryFolder, fileName);
118 final List<String> lines = createLinesFile(testFile, encoding, lineCount);
119
120 try (LineIterator iterator = FileUtils.lineIterator(testFile, encoding)) {
121 assertThrows(UnsupportedOperationException.class, iterator::remove);
122
123 int idx = 0;
124 while (iterator.hasNext()) {
125 final String line = iterator.next();
126 assertEquals(lines.get(idx), line, "Comparing line " + idx);
127 assertTrue(idx < lines.size(), "Exceeded expected idx=" + idx + " size=" + lines.size());
128 idx++;
129 }
130 assertEquals(idx, lines.size(), "Line Count doesn't match");
131
132
133 assertThrows(NoSuchElementException.class, iterator::next);
134 assertThrows(NoSuchElementException.class, iterator::nextLine);
135 }
136 }
137
138 @Test
139 public void testCloseEarly() throws Exception {
140 final String encoding = UTF_8;
141
142 final File testFile = new File(temporaryFolder, "LineIterator-closeEarly.txt");
143 createLinesFile(testFile, encoding, 3);
144
145 try (LineIterator iterator = FileUtils.lineIterator(testFile, encoding)) {
146
147 assertNotNull("Line expected", iterator.next());
148 assertTrue(iterator.hasNext(), "More expected");
149
150
151 iterator.close();
152 assertFalse(iterator.hasNext(), "No more expected");
153 assertThrows(NoSuchElementException.class, iterator::next);
154 assertThrows(NoSuchElementException.class, iterator::nextLine);
155
156 iterator.close();
157 assertThrows(NoSuchElementException.class, iterator::next);
158 assertThrows(NoSuchElementException.class, iterator::nextLine);
159 }
160 }
161
162 @Test
163 public void testConstructor() {
164 assertThrows(NullPointerException.class, () -> new LineIterator(null));
165 }
166
167 private void testFiltering(final List<String> lines, final Reader reader) throws IOException {
168 try (LineIterator iterator = new LineIterator(reader) {
169 @Override
170 protected boolean isValidLine(final String line) {
171 final char c = line.charAt(line.length() - 1);
172 return (c - 48) % 3 != 1;
173 }
174 }) {
175 assertThrows(UnsupportedOperationException.class, iterator::remove);
176
177 int idx = 0;
178 int actualLines = 0;
179 while (iterator.hasNext()) {
180 final String line = iterator.next();
181 actualLines++;
182 assertEquals(lines.get(idx), line, "Comparing line " + idx);
183 assertTrue(idx < lines.size(), "Exceeded expected idx=" + idx + " size=" + lines.size());
184 idx++;
185 if (idx % 3 == 1) {
186 idx++;
187 }
188 }
189 assertEquals(9, lines.size(), "Line Count doesn't match");
190 assertEquals(9, idx, "Line Count doesn't match");
191 assertEquals(6, actualLines, "Line Count doesn't match");
192
193
194 assertThrows(NoSuchElementException.class, iterator::next);
195 assertThrows(NoSuchElementException.class, iterator::nextLine);
196 }
197 }
198
199 @Test
200 public void testFilteringBufferedReader() throws Exception {
201 final String encoding = UTF_8;
202
203 final String fileName = "LineIterator-Filter-test.txt";
204 final File testFile = new File(temporaryFolder, fileName);
205 final List<String> lines = createLinesFile(testFile, encoding, 9);
206
207 final Reader reader = new BufferedReader(Files.newBufferedReader(testFile.toPath()));
208 this.testFiltering(lines, reader);
209 }
210
211 @Test
212 public void testFilteringFileReader() throws Exception {
213 final String encoding = UTF_8;
214
215 final String fileName = "LineIterator-Filter-test.txt";
216 final File testFile = new File(temporaryFolder, fileName);
217 final List<String> lines = createLinesFile(testFile, encoding, 9);
218
219 final Reader reader = Files.newBufferedReader(testFile.toPath());
220 this.testFiltering(lines, reader);
221 }
222
223 @Test
224 public void testInvalidEncoding() throws Exception {
225 final String encoding = "XXXXXXXX";
226
227 final File testFile = new File(temporaryFolder, "LineIterator-invalidEncoding.txt");
228 createLinesFile(testFile, UTF_8, 3);
229
230 assertThrows(UnsupportedCharsetException.class, () -> FileUtils.lineIterator(testFile, encoding));
231 }
232
233 @Test
234 public void testMissingFile() throws Exception {
235 final File testFile = new File(temporaryFolder, "dummy-missing-file.txt");
236 assertThrows(NoSuchFileException.class, () -> FileUtils.lineIterator(testFile, UTF_8));
237 }
238
239 @Test
240 public void testNextLineOnlyDefaultEncoding() throws Exception {
241 final File testFile = new File(temporaryFolder, "LineIterator-nextOnly.txt");
242 final List<String> lines = createLinesFile(testFile, 3);
243
244 final LineIterator iterator = FileUtils.lineIterator(testFile);
245 assertLines(lines, iterator);
246 }
247
248 @Test
249 public void testNextLineOnlyNullEncoding() throws Exception {
250 final String encoding = null;
251
252 final File testFile = new File(temporaryFolder, "LineIterator-nextOnly.txt");
253 final List<String> lines = createLinesFile(testFile, encoding, 3);
254
255 final LineIterator iterator = FileUtils.lineIterator(testFile, encoding);
256 assertLines(lines, iterator);
257 }
258
259 @Test
260 public void testNextLineOnlyUtf8Encoding() throws Exception {
261 final String encoding = UTF_8;
262
263 final File testFile = new File(temporaryFolder, "LineIterator-nextOnly.txt");
264 final List<String> lines = createLinesFile(testFile, encoding, 3);
265
266 final LineIterator iterator = FileUtils.lineIterator(testFile, encoding);
267 assertLines(lines, iterator);
268 }
269
270 @Test
271 public void testNextOnly() throws Exception {
272 final String encoding = null;
273
274 final File testFile = new File(temporaryFolder, "LineIterator-nextOnly.txt");
275 final List<String> lines = createLinesFile(testFile, encoding, 3);
276
277 try (LineIterator iterator = FileUtils.lineIterator(testFile, encoding)) {
278 for (int i = 0; i < lines.size(); i++) {
279 final String line = iterator.next();
280 assertEquals(lines.get(i), line, "next() line " + i);
281 }
282 assertFalse(iterator.hasNext(), "No more expected");
283 }
284 }
285
286 @Test
287 public void testNextWithException() throws Exception {
288 final Reader reader = new BufferedReader(new StringReader("")) {
289 @Override
290 public String readLine() throws IOException {
291 throw new IOException("hasNext");
292 }
293 };
294 try (LineIterator li = new LineIterator(reader)) {
295 assertThrows(IllegalStateException.class, li::hasNext);
296 }
297 }
298
299 @Test
300 public void testOneLines() throws Exception {
301 doTestFileWithSpecifiedLines(1);
302 }
303
304 @Test
305 public void testThreeLines() throws Exception {
306 doTestFileWithSpecifiedLines(3);
307 }
308
309 @Test
310 public void testTwoLines() throws Exception {
311 doTestFileWithSpecifiedLines(2);
312 }
313
314 @Test
315 public void testValidEncoding() throws Exception {
316 final String encoding = UTF_8;
317
318 final File testFile = new File(temporaryFolder, "LineIterator-validEncoding.txt");
319 createLinesFile(testFile, encoding, 3);
320
321 try (LineIterator iterator = FileUtils.lineIterator(testFile, encoding)) {
322 int count = 0;
323 while (iterator.hasNext()) {
324 assertNotNull(iterator.next());
325 count++;
326 }
327 assertEquals(3, count);
328 }
329 }
330
331 @Test
332 public void testZeroLines() throws Exception {
333 doTestFileWithSpecifiedLines(0);
334 }
335
336 }