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