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 testDataIntegrityWithBufferedReader()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 testDataIntegrityWithBufferedReader(final Path filePath, final FileSystem fileSystem, final Charset charset, final ReversedLinesFileReader reversedLinesFileReader)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 testDataIntegrityWithBufferedReader(final String fileName, final String charsetName, final Integer blockSize, final boolean useNonDefaultFileSystem, final boolean isResource)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 } 141