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;
18  
19  import java.io.File;
20  import java.io.FileNotFoundException;
21  import java.io.FileReader;
22  import java.io.IOException;
23  import java.io.Reader;
24  import java.io.UnsupportedEncodingException;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.NoSuchElementException;
28  
29  import junit.framework.Test;
30  import junit.framework.TestSuite;
31  import junit.textui.TestRunner;
32  
33  import org.apache.commons.io.testtools.FileBasedTestCase;
34  
35  /**
36   * This is used to test LineIterator for correctness.
37   *
38   * @author Niall Pemberton
39   * @author Stephen Colebourne
40   * @version $Id: LineIteratorTestCase.java 437567 2006-08-28 06:39:07Z bayard $
41   */
42  public class LineIteratorTestCase extends FileBasedTestCase {
43  
44      public static void main(String[] args) {
45          TestRunner.run(suite());
46      }
47  
48      public static Test suite() {
49          return new TestSuite(LineIteratorTestCase.class);
50      }
51  
52      public LineIteratorTestCase(String name) throws IOException {
53          super(name);
54      }
55  
56      /** @see junit.framework.TestCase#setUp() */
57      protected void setUp() throws Exception {
58          File dir = getTestDirectory();
59          if (dir.exists()) {
60              FileUtils.deleteDirectory(dir);
61          }
62          dir.mkdirs();
63  
64      }
65  
66      /** @see junit.framework.TestCase#tearDown() */
67      protected void tearDown() throws Exception {
68          FileUtils.deleteDirectory(getTestDirectory());
69      }
70  
71      //-----------------------------------------------------------------------
72      /**
73       * Test constructor.
74       */
75      public void testConstructor() throws Exception {
76          try {
77              new LineIterator((Reader) null);
78              fail();
79          } catch (IllegalArgumentException ex) {
80              // expected
81          }
82      }
83  
84      /**
85       * Test a file with no lines.
86       */
87      public void testZeroLines() throws Exception {
88          doTestFileWithSpecifiedLines(0);
89      }
90  
91      /**
92       * Test a file with 1 line.
93       */
94      public void testOneLines() throws Exception {
95          doTestFileWithSpecifiedLines(1);
96      }
97  
98      /**
99       * Test a file with 2 lines.
100      */
101     public void testTwoLines() throws Exception {
102         doTestFileWithSpecifiedLines(2);
103     }
104 
105     /**
106      * Test a file with 3 lines.
107      */
108     public void testThreeLines() throws Exception {
109         doTestFileWithSpecifiedLines(3);
110     }
111 
112     /**
113      * Test a missing File.
114      */
115     public void testMissingFile() throws Exception {
116         File testFile = new File(getTestDirectory(), "dummy-missing-file.txt");
117         
118         LineIterator iterator = null;
119         try {
120             iterator = FileUtils.lineIterator(testFile, "UTF-8");
121             fail("Expected FileNotFoundException");
122         } catch(FileNotFoundException expected) {
123             // ignore, expected result
124         } finally {
125             LineIterator.closeQuietly(iterator);
126         }
127     }
128 
129     /**
130      * Test a file with a Valid encoding.
131      */
132     public void testValidEncoding() throws Exception {
133         String encoding = "UTF-8";
134         
135         File testFile = new File(getTestDirectory(), "LineIterator-validEncoding.txt");
136         createFile(testFile, encoding, 3);
137         
138         LineIterator iterator = FileUtils.lineIterator(testFile, encoding);
139         try {
140             int count = 0;
141             while (iterator.hasNext()) {
142                 assertTrue(iterator.next() instanceof String);
143                 count++;
144             }
145             assertEquals(3, count);
146         } finally {
147             LineIterator.closeQuietly(iterator);
148         }
149     }
150 
151     /**
152      * Test a file with an Invalid encoding.
153      */
154     public void testInvalidEncoding() throws Exception {
155         String encoding = "XXXXXXXX";
156         
157         File testFile = new File(getTestDirectory(), "LineIterator-invalidEncoding.txt");
158         createFile(testFile, "UTF-8", 3);
159         
160         LineIterator iterator = null;
161         try {
162             iterator = FileUtils.lineIterator(testFile, encoding);
163             fail("Expected UnsupportedEncodingException");
164         } catch(UnsupportedEncodingException expected) {
165             // ignore, expected result
166         } finally {
167             LineIterator.closeQuietly(iterator);
168         }
169     }
170 
171     /**
172      * Test the iterator using only the next() method.
173      */
174     public void testNextOnly() throws Exception {
175         String encoding = null;
176         
177         File testFile = new File(getTestDirectory(), "LineIterator-nextOnly.txt");
178         List lines = createFile(testFile, encoding, 3);
179         
180         LineIterator iterator = FileUtils.lineIterator(testFile, encoding);
181         try {
182             for (int i = 0; i < lines.size(); i++) {
183                 String line = (String)iterator.next();
184                 assertEquals("next() line " + i, lines.get(i), line);
185             }
186             assertEquals("No more expected", false, iterator.hasNext());
187         } finally {
188             LineIterator.closeQuietly(iterator);
189         }
190     }
191 
192     /**
193      * Test the iterator using only the nextLine() method.
194      */
195     public void testNextLineOnly() throws Exception {
196         String encoding = null;
197         
198         File testFile = new File(getTestDirectory(), "LineIterator-nextOnly.txt");
199         List lines = createFile(testFile, encoding, 3);
200         
201         LineIterator iterator = FileUtils.lineIterator(testFile, encoding);
202         try {
203             for (int i = 0; i < lines.size(); i++) {
204                 String line = iterator.nextLine();
205                 assertEquals("nextLine() line " + i, lines.get(i), line);
206             }
207             assertFalse("No more expected", iterator.hasNext());
208         } finally {
209             LineIterator.closeQuietly(iterator);
210         }
211     }
212 
213     /**
214      * Test closing the iterator before all the file has been
215      * processed.
216      */
217     public void testCloseEarly() throws Exception {
218         String encoding = "UTF-8";
219         
220         File testFile = new File(getTestDirectory(), "LineIterator-closeEarly.txt");
221         createFile(testFile, encoding, 3);
222         
223         LineIterator iterator = FileUtils.lineIterator(testFile, encoding);
224         try {
225             // get
226             assertTrue("Line expected", iterator.next() instanceof String);
227             assertTrue("More expected", iterator.hasNext());
228     
229             // close
230             iterator.close();
231             assertFalse("No more expected", iterator.hasNext());
232             try {
233                 iterator.next();
234                 fail();
235             } catch (NoSuchElementException ex) {
236                 // expected
237             }
238             try {
239                 iterator.nextLine();
240                 fail();
241             } catch (NoSuchElementException ex) {
242                 // expected
243             }
244     
245             // try closing again
246             iterator.close();
247             try {
248                 iterator.next();
249                 fail();
250             } catch (NoSuchElementException ex) {
251                 // expected
252             }
253             try {
254                 iterator.nextLine();
255                 fail();
256             } catch (NoSuchElementException ex) {
257                 // expected
258             }
259         } finally {
260             LineIterator.closeQuietly(iterator);
261         }
262     }
263 
264     /**
265      * Utility method to create and test a file with a specified
266      * number of lines.
267      */
268     private void doTestFileWithSpecifiedLines(int lineCount) throws Exception {
269         String encoding = "UTF-8";
270         
271         String fileName = "LineIterator-" + lineCount + "-test.txt";
272         File testFile = new File(getTestDirectory(), fileName);
273         List lines = createFile(testFile, encoding, lineCount);
274         
275         LineIterator iterator = FileUtils.lineIterator(testFile, encoding);
276         try {
277             try {
278                 iterator.remove();
279                 fail("Remove is unsupported");
280             } catch (UnsupportedOperationException ex) {
281                 // expected
282             }
283     
284             int idx = 0;
285             while (iterator.hasNext()) {
286                 String line = (String)iterator.next();
287                 assertEquals("Comparing line " + idx, lines.get(idx), line);
288                 assertTrue("Exceeded expected idx=" + idx + " size=" + lines.size(), idx < lines.size());
289                 idx++;
290             }
291             assertEquals("Line Count doesn't match", idx, lines.size());
292     
293             // try calling next() after file processed
294             try {
295                 iterator.next();
296                 fail("Expected NoSuchElementException");
297             } catch (NoSuchElementException expected) {
298                 // ignore, expected result
299             }
300             try {
301                 iterator.nextLine();
302                 fail("Expected NoSuchElementException");
303             } catch (NoSuchElementException expected) {
304                 // ignore, expected result
305             }
306         } finally {
307             LineIterator.closeQuietly(iterator);
308         }
309     }
310 
311     /**
312      * Utility method to create a test file with a specified
313      * number of lines.
314      */
315     private List createFile(File file, String encoding, int lineCount) throws Exception {
316         List lines = new ArrayList();
317         for (int i = 0; i < lineCount; i++) {
318             lines.add("LINE " + i);
319         }
320         FileUtils.writeLines(file, encoding, lines);
321         return lines;
322     }
323 
324     //-----------------------------------------------------------------------
325     public void testFiltering() throws Exception {
326         String encoding = "UTF-8";
327         
328         String fileName = "LineIterator-Filter-test.txt";
329         File testFile = new File(getTestDirectory(), fileName);
330         List lines = createFile(testFile, encoding, 9);
331         
332         Reader reader = new FileReader(testFile);
333         LineIterator iterator = new LineIterator(reader) {
334             protected boolean isValidLine(String line) {
335                 char c = line.charAt(line.length() - 1);
336                 return ((c - 48) % 3 != 1);
337             }
338         };
339         try {
340             try {
341                 iterator.remove();
342                 fail("Remove is unsupported");
343             } catch (UnsupportedOperationException ex) {
344                 // expected
345             }
346             
347             int idx = 0;
348             int actualLines = 0;
349             while (iterator.hasNext()) {
350                 String line = (String) iterator.next();
351                 actualLines++;
352                 assertEquals("Comparing line " + idx, lines.get(idx), line);
353                 assertTrue("Exceeded expected idx=" + idx + " size=" + lines.size(), idx < lines.size());
354                 idx++;
355                 if (idx % 3 == 1) {
356                     idx++;
357                 }
358             }
359             assertEquals("Line Count doesn't match", 9, lines.size());
360             assertEquals("Line Count doesn't match", 9, idx);
361             assertEquals("Line Count doesn't match", 6, actualLines);
362     
363             // try calling next() after file processed
364             try {
365                 iterator.next();
366                 fail("Expected NoSuchElementException");
367             } catch (NoSuchElementException expected) {
368                 // ignore, expected result
369             }
370             try {
371                 iterator.nextLine();
372                 fail("Expected NoSuchElementException");
373             } catch (NoSuchElementException expected) {
374                 // ignore, expected result
375             }
376         } finally {
377             LineIterator.closeQuietly(iterator);
378         }
379     }
380 
381 }