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.*;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.io.UnsupportedEncodingException;
24  import java.net.URISyntaxException;
25  import java.util.Arrays;
26  import java.util.Collection;
27  
28  import org.junit.After;
29  import org.junit.Test;
30  import org.junit.runner.RunWith;
31  import org.junit.runners.Parameterized;
32  import org.junit.runners.Parameterized.Parameters;
33  
34  @RunWith(Parameterized.class)
35  public class ReversedLinesFileReaderTestParamBlockSize {
36  
37      private static final String UTF_8 = "UTF-8";
38      private static final String ISO_8859_1 = "ISO-8859-1";
39  
40      @SuppressWarnings("boxing")
41      // small and uneven block sizes are not used in reality but are good to show that the algorithm is solid
42      @Parameters(name = "BlockSize={0}")
43      public static Collection<Integer[]> blockSizes() {
44          return Arrays.asList(new Integer[][]{{1}, {3}, {8}, {256}, {4096}});
45      }
46  
47      private ReversedLinesFileReader reversedLinesFileReader;
48      private final int testParamBlockSize;
49  
50      public ReversedLinesFileReaderTestParamBlockSize(final Integer testWithBlockSize) {
51          testParamBlockSize = testWithBlockSize;
52      }
53  
54      // Strings are escaped in constants to avoid java source encoding issues (source file enc is UTF-8):
55  
56      // "A Test Line. Special chars: ÄäÜüÖöß Ãáéíïçñ ©µ¥£±²®"
57      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";
58      // Hiragana letters: �����
59      private static final String TEST_LINE_SHIFT_JIS1 = "Hiragana letters: \u3041\u3042\u3043\u3044\u3045";
60      // Kanji letters: 明輸�京
61      private static final String TEST_LINE_SHIFT_JIS2 = "Kanji letters: \u660E\u8F38\u5B50\u4EAC";
62      // windows-31j characters
63      private static final String TEST_LINE_WINDOWS_31J_1 = "\u3041\u3042\u3043\u3044\u3045";
64      private static final String TEST_LINE_WINDOWS_31J_2 = "\u660E\u8F38\u5B50\u4EAC";
65      // gbk characters (Simplified Chinese)
66      private static final String TEST_LINE_GBK_1 = "\u660E\u8F38\u5B50\u4EAC";
67      private static final String TEST_LINE_GBK_2 = "\u7B80\u4F53\u4E2D\u6587";
68      // x-windows-949 characters (Korean)
69      private static final String TEST_LINE_X_WINDOWS_949_1 = "\uD55C\uAD6D\uC5B4";
70      private static final String TEST_LINE_X_WINDOWS_949_2 = "\uB300\uD55C\uBBFC\uAD6D";
71      // x-windows-950 characters (Traditional Chinese)
72      private static final String TEST_LINE_X_WINDOWS_950_1 = "\u660E\u8F38\u5B50\u4EAC";
73      private static final String TEST_LINE_X_WINDOWS_950_2 = "\u7E41\u9AD4\u4E2D\u6587";
74  
75  
76      @After
77      public void closeReader() {
78          try {
79              reversedLinesFileReader.close();
80          } catch (final Exception e) {
81              // ignore
82          }
83      }
84  
85      @Test
86      public void testIsoFileDefaults() throws URISyntaxException, IOException {
87          final File testFileIso = new File(this.getClass().getResource("/test-file-iso8859-1.bin").toURI());
88          reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, ISO_8859_1);
89          assertFileWithShrinkingTestLines(reversedLinesFileReader);
90      }
91  
92      @Test
93      public void testUTF8FileWindowsBreaks() throws URISyntaxException, IOException {
94          final File testFileIso = new File(this.getClass().getResource("/test-file-utf8-win-linebr.bin").toURI());
95          reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, UTF_8);
96          assertFileWithShrinkingTestLines(reversedLinesFileReader);
97      }
98  
99      @Test
100     public void testUTF8FileCRBreaks() throws URISyntaxException, IOException {
101         final File testFileIso = new File(this.getClass().getResource("/test-file-utf8-cr-only.bin").toURI());
102         reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, UTF_8);
103         assertFileWithShrinkingTestLines(reversedLinesFileReader);
104     }
105 
106     @Test
107     public void testUTF8File() throws URISyntaxException, IOException {
108         final File testFileIso = new File(this.getClass().getResource("/test-file-utf8.bin").toURI());
109         reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, UTF_8);
110         assertFileWithShrinkingTestLines(reversedLinesFileReader);
111     }
112 
113     @Test
114     public void testEmptyFile() throws URISyntaxException, IOException {
115         final File testFileEmpty = new File(this.getClass().getResource("/test-file-empty.bin").toURI());
116         reversedLinesFileReader = new ReversedLinesFileReader(testFileEmpty, testParamBlockSize, UTF_8);
117         assertNull(reversedLinesFileReader.readLine());
118     }
119 
120     @Test
121     public void testUTF16BEFile() throws URISyntaxException, IOException {
122         final File testFileUTF16BE = new File(this.getClass().getResource("/test-file-utf16be.bin").toURI());
123         reversedLinesFileReader = new ReversedLinesFileReader(testFileUTF16BE, testParamBlockSize, "UTF-16BE");
124         assertFileWithShrinkingTestLines(reversedLinesFileReader);
125     }
126 
127     @Test
128     public void testUTF16LEFile() throws URISyntaxException, IOException {
129         final File testFileUTF16LE = new File(this.getClass().getResource("/test-file-utf16le.bin").toURI());
130         reversedLinesFileReader = new ReversedLinesFileReader(testFileUTF16LE, testParamBlockSize, "UTF-16LE");
131         assertFileWithShrinkingTestLines(reversedLinesFileReader);
132     }
133 
134     @Test
135     public void testShiftJISFile() throws URISyntaxException, IOException {
136         final File testFileShiftJIS = new File(this.getClass().getResource("/test-file-shiftjis.bin").toURI());
137         reversedLinesFileReader = new ReversedLinesFileReader(testFileShiftJIS, testParamBlockSize, "Shift_JIS");
138         assertEqualsAndNoLineBreaks(TEST_LINE_SHIFT_JIS2, reversedLinesFileReader.readLine());
139         assertEqualsAndNoLineBreaks(TEST_LINE_SHIFT_JIS1, reversedLinesFileReader.readLine());
140     }
141 
142     @Test
143     public void testWindows31jFile() throws URISyntaxException, IOException {
144         final File testFileWindows31J = new File(this.getClass().getResource("/test-file-windows-31j.bin").toURI());
145         reversedLinesFileReader = new ReversedLinesFileReader(testFileWindows31J, testParamBlockSize, "windows-31j");
146         assertEqualsAndNoLineBreaks(TEST_LINE_WINDOWS_31J_2, reversedLinesFileReader.readLine());
147         assertEqualsAndNoLineBreaks(TEST_LINE_WINDOWS_31J_1, reversedLinesFileReader.readLine());
148     }
149 
150     @Test
151     public void testGBK() throws URISyntaxException, IOException {
152         final File testFileGBK = new File(this.getClass().getResource("/test-file-gbk.bin").toURI());
153         reversedLinesFileReader = new ReversedLinesFileReader(testFileGBK, testParamBlockSize, "GBK");
154         assertEqualsAndNoLineBreaks(TEST_LINE_GBK_2, reversedLinesFileReader.readLine());
155         assertEqualsAndNoLineBreaks(TEST_LINE_GBK_1, reversedLinesFileReader.readLine());
156     }
157 
158     @Test
159     public void testxWindows949File() throws URISyntaxException, IOException {
160         final File testFilexWindows949 = new File(this.getClass().getResource("/test-file-x-windows-949.bin").toURI());
161         reversedLinesFileReader = new ReversedLinesFileReader(testFilexWindows949, testParamBlockSize, "x-windows-949");
162         assertEqualsAndNoLineBreaks(TEST_LINE_X_WINDOWS_949_2, reversedLinesFileReader.readLine());
163         assertEqualsAndNoLineBreaks(TEST_LINE_X_WINDOWS_949_1, reversedLinesFileReader.readLine());
164     }
165 
166     @Test
167     public void testxWindows950File() throws URISyntaxException, IOException {
168         final File testFilexWindows950 = new File(this.getClass().getResource("/test-file-x-windows-950.bin").toURI());
169         reversedLinesFileReader = new ReversedLinesFileReader(testFilexWindows950, testParamBlockSize, "x-windows-950");
170         assertEqualsAndNoLineBreaks(TEST_LINE_X_WINDOWS_950_2, reversedLinesFileReader.readLine());
171         assertEqualsAndNoLineBreaks(TEST_LINE_X_WINDOWS_950_1, reversedLinesFileReader.readLine());
172     }
173 
174     @Test // this test is run 3x for same block size as we want to test with 10
175     public void testFileSizeIsExactMultipleOfBlockSize() throws URISyntaxException, IOException {
176         final int blockSize = 10;
177         final File testFile20Bytes = new File(this.getClass().getResource("/test-file-20byteslength.bin").toURI());
178         reversedLinesFileReader = new ReversedLinesFileReader(testFile20Bytes, blockSize, ISO_8859_1);
179         final String testLine = "123456789";
180         assertEqualsAndNoLineBreaks(testLine, reversedLinesFileReader.readLine());
181         assertEqualsAndNoLineBreaks(testLine, reversedLinesFileReader.readLine());
182     }
183 
184     @Test
185     public void testUTF8FileWindowsBreaksSmallBlockSize2VerifyBlockSpanningNewLines() throws URISyntaxException, IOException {
186         final File testFileUtf8 = new File(this.getClass().getResource("/test-file-utf8-win-linebr.bin").toURI());
187         reversedLinesFileReader = new ReversedLinesFileReader(testFileUtf8, testParamBlockSize, UTF_8);
188         assertFileWithShrinkingTestLines(reversedLinesFileReader);
189     }
190 
191     @Test
192     public void testIsoFileManyWindowsBreaksSmallBlockSize2VerifyBlockSpanningNewLines() throws URISyntaxException, IOException {
193         final File testFileIso = new File(this.getClass().getResource("/test-file-iso8859-1-shortlines-win-linebr.bin").toURI());
194         reversedLinesFileReader = new ReversedLinesFileReader(testFileIso, testParamBlockSize, ISO_8859_1);
195 
196         for (int i = 3; i > 0; i--) {
197             for (int j = 1; j <= 3; j++) {
198                 assertEqualsAndNoLineBreaks("", reversedLinesFileReader.readLine());
199             }
200             assertEqualsAndNoLineBreaks("" + i, reversedLinesFileReader.readLine());
201         }
202     }
203 
204     @Test(expected = UnsupportedEncodingException.class)
205     public void testUnsupportedEncodingUTF16() throws URISyntaxException, IOException {
206         final File testFileEmpty = new File(this.getClass().getResource("/test-file-empty.bin").toURI());
207         new ReversedLinesFileReader(testFileEmpty, testParamBlockSize, "UTF-16").close();
208     }
209 
210     @Test(expected = UnsupportedEncodingException.class)
211     public void testUnsupportedEncodingBig5() throws URISyntaxException, IOException {
212         final File testFileEncodingBig5 = new File(this.getClass().getResource("/test-file-empty.bin").toURI());
213         new ReversedLinesFileReader(testFileEncodingBig5, testParamBlockSize, "Big5").close();
214     }
215 
216     private void assertFileWithShrinkingTestLines(final ReversedLinesFileReader reversedLinesFileReader) throws IOException {
217         String line = null;
218         int lineCount = 0;
219         while ((line = reversedLinesFileReader.readLine()) != null) {
220             lineCount++;
221             assertEqualsAndNoLineBreaks("Line " + lineCount + " is not matching", TEST_LINE.substring(0, lineCount), line);
222         }
223     }
224 
225     static void assertEqualsAndNoLineBreaks(final String msg, final String expected, final String actual) {
226         if (actual != null) {
227             assertFalse("Line contains \\n: line=" + actual, actual.contains("\n"));
228             assertFalse("Line contains \\r: line=" + actual, actual.contains("\r"));
229         }
230         assertEquals(msg, expected, actual);
231     }
232 
233     static void assertEqualsAndNoLineBreaks(final String expected, final String actual) {
234         assertEqualsAndNoLineBreaks(null, expected, actual);
235     }
236 }