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.jupiter.api.Assertions.assertEquals;
20  
21  import java.io.BufferedReader;
22  import java.io.IOException;
23  import java.io.Reader;
24  import java.io.Writer;
25  import java.net.URISyntaxException;
26  import java.nio.charset.Charset;
27  import java.nio.charset.StandardCharsets;
28  import java.nio.file.FileSystem;
29  import java.nio.file.Files;
30  import java.nio.file.Path;
31  import java.nio.file.Paths;
32  import java.util.Stack;
33  import java.util.stream.Stream;
34  
35  import org.apache.commons.io.Charsets;
36  import org.apache.commons.io.IOUtils;
37  import org.apache.commons.io.TestResources;
38  import org.junit.jupiter.params.ParameterizedTest;
39  import org.junit.jupiter.params.provider.Arguments;
40  import org.junit.jupiter.params.provider.MethodSource;
41  
42  import com.google.common.jimfs.Configuration;
43  import com.google.common.jimfs.Jimfs;
44  
45  /**
46   * Test checks symmetric behavior with BufferedReader.
47   */
48  public class ReversedLinesFileReaderTestParamFile {
49  
50      private static final String UTF_16BE = StandardCharsets.ISO_8859_1.name();
51      private static final String UTF_16LE = StandardCharsets.UTF_16LE.name();
52      private static final String UTF_8 = StandardCharsets.UTF_8.name();
53      private static final String ISO_8859_1 = StandardCharsets.ISO_8859_1.name();
54  
55      public static Stream<Arguments> testDataIntegrityWithBufferedReader() throws IOException, URISyntaxException {
56          // Make a file using the default encoding.
57          final Path sourcePath = TestResources.getPath("test-file-utf8-win-linebr.bin");
58          final Path targetPath = Files.createTempFile("ReversedLinesFileReaderTestParamFile", ".bin");
59          try (Reader input = Files.newBufferedReader(sourcePath, StandardCharsets.UTF_8);
60              Writer output = Files.newBufferedWriter(targetPath, Charset.defaultCharset())) {
61              IOUtils.copyLarge(input, output);
62          }
63          // All tests
64          // @formatter:off
65          return Stream.of(
66                  Arguments.of(targetPath.toAbsolutePath().toString(), null, null, false, false),
67                  Arguments.of("test-file-20byteslength.bin", ISO_8859_1, null, false, true),
68                  Arguments.of("test-file-iso8859-1-shortlines-win-linebr.bin", ISO_8859_1, null, false, true),
69                  Arguments.of("test-file-iso8859-1.bin", ISO_8859_1, null, false, true),
70                  Arguments.of("test-file-shiftjis.bin", "Shift_JIS", null, false, true),
71                  Arguments.of("test-file-utf16be.bin", UTF_16BE, null, false, true),
72                  Arguments.of("test-file-utf16le.bin", UTF_16LE, null, false, true),
73                  Arguments.of("test-file-utf8-cr-only.bin", UTF_8, null, false, true),
74                  Arguments.of("test-file-utf8-win-linebr.bin", UTF_8, null, false, true,
75                  Arguments.of("test-file-utf8-win-linebr.bin", UTF_8, 1, false, true),
76                  Arguments.of("test-file-utf8-win-linebr.bin", UTF_8, 2, false, true),
77                  Arguments.of("test-file-utf8-win-linebr.bin", UTF_8, 3, false, true),
78                  Arguments.of("test-file-utf8-win-linebr.bin", UTF_8, 4, false, true),
79                  Arguments.of("test-file-utf8.bin", UTF_8, null, false, true),
80                  Arguments.of("test-file-utf8.bin", UTF_8, null, true, true),
81                  Arguments.of("test-file-windows-31j.bin", "windows-31j", null, false, true),
82                  Arguments.of("test-file-gbk.bin", "gbk", null, false, true),
83                  Arguments.of("test-file-x-windows-949.bin", "x-windows-949", null, false, true),
84                  Arguments.of("test-file-x-windows-950.bin", "x-windows-950", null, false, true)));
85          // @formatter:on
86      }
87  
88      private void testDataIntegrityWithBufferedReader(final Path filePath, final FileSystem fileSystem, final Charset charset,
89              final ReversedLinesFileReader reversedLinesFileReader) throws IOException {
90          final Stack<String> lineStack = new Stack<>();
91          String line;
92  
93          try (BufferedReader bufferedReader = Files.newBufferedReader(filePath, Charsets.toCharset(charset))) {
94              // read all lines in normal order
95              while ((line = bufferedReader.readLine()) != null) {
96                  lineStack.push(line);
97              }
98          }
99  
100         // read in reverse order and compare with lines from stack
101         while ((line = reversedLinesFileReader.readLine()) != null) {
102             final String lineFromBufferedReader = lineStack.pop();
103             assertEquals(lineFromBufferedReader, line);
104         }
105         assertEquals(0, lineStack.size(), "Stack should be empty");
106 
107         if (fileSystem != null) {
108             fileSystem.close();
109         }
110     }
111 
112     @ParameterizedTest(name = "{0}, encoding={1}, blockSize={2}, useNonDefaultFileSystem={3}, isResource={4}")
113     @MethodSource
114     public void testDataIntegrityWithBufferedReader(final String fileName, final String charsetName, final Integer blockSize,
115             final boolean useNonDefaultFileSystem, final boolean isResource) throws IOException, URISyntaxException {
116 
117         Path filePath = isResource ? TestResources.getPath(fileName) : Paths.get(fileName);
118         FileSystem fileSystem = null;
119         if (useNonDefaultFileSystem) {
120             fileSystem = Jimfs.newFileSystem(Configuration.unix());
121             filePath = Files.copy(filePath, fileSystem.getPath("/" + fileName));
122         }
123 
124         // We want to test null Charset in the ReversedLinesFileReader constructor.
125         final Charset charset = charsetName != null ? Charset.forName(charsetName) : null;
126         try (ReversedLinesFileReader reversedLinesFileReader = blockSize == null ? new ReversedLinesFileReader(filePath, charset)
127                 : new ReversedLinesFileReader(filePath, blockSize, charset)) {
128             testDataIntegrityWithBufferedReader(filePath, fileSystem, charset, reversedLinesFileReader);
129         }
130         // @formatter:off
131         try (ReversedLinesFileReader reversedLinesFileReader = ReversedLinesFileReader.builder()
132                 .setPath(filePath)
133                 .setBufferSize(blockSize)
134                 .setCharset(charset)
135                 .get()) {
136             // @formatter:on
137             testDataIntegrityWithBufferedReader(filePath, fileSystem, charset, reversedLinesFileReader);
138         }
139     }
140 }