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.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertNull;
22  
23  import java.io.File;
24  import java.io.IOException;
25  import java.io.UnsupportedEncodingException;
26  import java.net.URISyntaxException;
27  import java.util.Arrays;
28  import java.util.Collection;
29  
30  import org.junit.After;
31  import org.junit.Test;
32  import org.junit.runner.RunWith;
33  import org.junit.runners.Parameterized;
34  import org.junit.runners.Parameterized.Parameters;
35  
36  @RunWith(Parameterized.class)
37  public class ReversedLinesFileReaderTestParamBlockSize {
38  
39      private static final String UTF_8 = "UTF-8";
40      private static final String ISO_8859_1 = "ISO-8859-1";
41  
42      @SuppressWarnings("boxing")
43      @Parameters // small and uneven block sizes are not used in reality but are good to show that the algorithm is solid
44      public static Collection<Integer[]> blockSizes() {
45              return Arrays.asList(new Integer[][] { {1}, {3}, {8}, {256}, {4096} });
46      }
47  
48      private ReversedLinesFileReader reversedLinesFileReader;
49      private final int testParamBlockSize;
50  
51      public ReversedLinesFileReaderTestParamBlockSize(final Integer testWithBlockSize) {
52          testParamBlockSize = testWithBlockSize.intValue();
53      }
54  
55      // Strings are escaped in constants to avoid java source encoding issues (source file enc is UTF-8):
56  
57      // "A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£±²®"
58      private static final String TEST_LINE = "A Test Line. Special chars: \u00C4\u00E4\u00DC\u00FC\u00D6\u00F6\u00DF \u00C3\u00E1\u00E9\u00ED\u00EF\u00E7\u00F1\u00C2 \u00A9\u00B5\u00A5\u00A3\u00B1\u00B2\u00AE";
59      // Hiragana letters: �����
60      private static final String TEST_LINE_SHIFT_JIS1 = "Hiragana letters: \u3041\u3042\u3043\u3044\u3045";
61      // Kanji letters: 明輸�京
62      private static final String TEST_LINE_SHIFT_JIS2 = "Kanji letters: \u660E\u8F38\u5B50\u4EAC";
63  
64  
65  
66      @After
67      public void closeReader() {
68          try {
69              reversedLinesFileReader.close();
70          } catch(final Exception e) {
71              // ignore
72          }
73      }
74  
75      @Test
76      public void testIsoFileDefaults() throws URISyntaxException, IOException {
77          final File testFileIso = new File(this.getClass().getResource("/test-file-iso8859-1.bin").toURI());
78          reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, ISO_8859_1);
79          assertFileWithShrinkingTestLines(reversedLinesFileReader);
80      }
81  
82      @Test
83      public void testUTF8FileWindowsBreaks() throws URISyntaxException, IOException {
84          final File testFileIso = new File(this.getClass().getResource("/test-file-utf8-win-linebr.bin").toURI());
85          reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, UTF_8);
86          assertFileWithShrinkingTestLines(reversedLinesFileReader);
87      }
88      @Test
89      public void testUTF8FileCRBreaks() throws URISyntaxException, IOException {
90          final File testFileIso = new File(this.getClass().getResource("/test-file-utf8-cr-only.bin").toURI());
91          reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, UTF_8);
92          assertFileWithShrinkingTestLines(reversedLinesFileReader);
93      }
94  
95      @Test
96      public void testUTF8File() throws URISyntaxException, IOException {
97          final File testFileIso = new File(this.getClass().getResource("/test-file-utf8.bin").toURI());
98          reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, UTF_8);
99          assertFileWithShrinkingTestLines(reversedLinesFileReader);
100     }
101 
102     @Test
103     public void testEmptyFile() throws URISyntaxException, IOException {
104         final File testFileEmpty = new File(this.getClass().getResource("/test-file-empty.bin").toURI());
105         reversedLinesFileReader = new ReversedLinesFileReader(testFileEmpty, testParamBlockSize, UTF_8);
106         assertNull(reversedLinesFileReader.readLine());
107     }
108 
109     @Test
110     public void testUTF16BEFile() throws URISyntaxException, IOException {
111         final File testFileUTF16BE = new File(this.getClass().getResource("/test-file-utf16be.bin").toURI());
112         reversedLinesFileReader = new ReversedLinesFileReader(testFileUTF16BE, testParamBlockSize, "UTF-16BE");
113         assertFileWithShrinkingTestLines(reversedLinesFileReader);
114     }
115 
116     @Test
117     public void testUTF16LEFile() throws URISyntaxException, IOException {
118         final File testFileUTF16LE = new File(this.getClass().getResource("/test-file-utf16le.bin").toURI());
119         reversedLinesFileReader = new ReversedLinesFileReader(testFileUTF16LE, testParamBlockSize, "UTF-16LE");
120         assertFileWithShrinkingTestLines(reversedLinesFileReader);
121     }
122 
123     @Test
124     public void testShiftJISFile() throws URISyntaxException, IOException {
125         final File testFileShiftJIS = new File(this.getClass().getResource("/test-file-shiftjis.bin").toURI());
126         reversedLinesFileReader = new ReversedLinesFileReader(testFileShiftJIS, testParamBlockSize, "Shift_JIS");
127         assertEqualsAndNoLineBreaks(TEST_LINE_SHIFT_JIS2, reversedLinesFileReader.readLine());
128         assertEqualsAndNoLineBreaks(TEST_LINE_SHIFT_JIS1, reversedLinesFileReader.readLine());
129     }
130 
131     @Test // this test is run 3x for same block size as we want to test with 10
132     public void testFileSizeIsExactMultipleOfBlockSize() throws URISyntaxException, IOException {
133         final int blockSize = 10;
134         final File testFile20Bytes = new File(this.getClass().getResource("/test-file-20byteslength.bin").toURI());
135         reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, ISO_8859_1);
136         final String testLine = "123456789";
137         assertEqualsAndNoLineBreaks(testLine, reversedLinesFileReader.readLine());
138         assertEqualsAndNoLineBreaks(testLine, reversedLinesFileReader.readLine());
139     }
140 
141     @Test
142     public void testUTF8FileWindowsBreaksSmallBlockSize2VerifyBlockSpanningNewLines() throws URISyntaxException, IOException {
143         final File testFileUtf8 = new File(this.getClass().getResource("/test-file-utf8-win-linebr.bin").toURI());
144         reversedLinesFileReader = new ReversedLinesFileReader(testFileUtf8, testParamBlockSize, UTF_8);
145         assertFileWithShrinkingTestLines(reversedLinesFileReader);
146     }
147 
148     @Test
149     public void testIsoFileManyWindowsBreaksSmallBlockSize2VerifyBlockSpanningNewLines() throws URISyntaxException, IOException {
150         final File testFileIso = new File(this.getClass().getResource("/test-file-iso8859-1-shortlines-win-linebr.bin").toURI());
151         reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, ISO_8859_1);
152 
153         for(int i=3;i>0;i--) {
154             for(int j=1;j<=3;j++) {
155                 assertEqualsAndNoLineBreaks("", reversedLinesFileReader.readLine());
156             }
157             assertEqualsAndNoLineBreaks(""+i, reversedLinesFileReader.readLine());
158         }
159     }
160 
161     @Test(expected=UnsupportedEncodingException.class)
162     public void testUnsupportedEncodingUTF16() throws URISyntaxException, IOException {
163         final File testFileEmpty = new File(this.getClass().getResource("/test-file-empty.bin").toURI());
164         new ReversedLinesFileReader(testFileEmpty, testParamBlockSize, "UTF-16").close();
165     }
166 
167     @Test(expected=UnsupportedEncodingException.class)
168     public void testUnsupportedEncodingBig5() throws URISyntaxException, IOException {
169         final File testFileEncodingBig5 = new File(this.getClass().getResource("/test-file-empty.bin").toURI());
170         new ReversedLinesFileReader(testFileEncodingBig5, testParamBlockSize, "Big5").close();
171     }
172 
173     private void assertFileWithShrinkingTestLines(final ReversedLinesFileReader reversedLinesFileReader) throws IOException {
174         String line = null;
175         int lineCount = 0;
176         while ((line = reversedLinesFileReader.readLine()) != null) {
177             lineCount++;
178             assertEqualsAndNoLineBreaks("Line "+lineCount+" is not matching", TEST_LINE.substring(0, lineCount), line);
179         }
180     }
181 
182     static void assertEqualsAndNoLineBreaks(final String msg, final String expected, final String actual) {
183         if(actual!=null) {
184             assertFalse("Line contains \\n: line="+actual, actual.contains("\n"));
185             assertFalse("Line contains \\r: line="+actual, actual.contains("\r"));
186         }
187         assertEquals(msg, expected, actual);
188     }
189     static void assertEqualsAndNoLineBreaks(final String expected, final String actual) {
190         assertEqualsAndNoLineBreaks(null, expected, actual);
191     }
192 }