| /* |
| * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* @test |
| * @bug 8072773 |
| * @library /lib/testlibrary/ ../../../util/stream/bootlib |
| * @build java.base/java.util.stream.OpTestCase |
| * @build jdk.testlibrary.RandomFactory |
| * @run testng/othervm StreamLinesTest |
| * @summary Tests streams returned from Files.lines, primarily focused on |
| * testing the file-channel-based stream stream with supported |
| * character sets |
| * @key randomness |
| */ |
| |
| import org.testng.annotations.DataProvider; |
| import org.testng.annotations.Test; |
| |
| import java.io.BufferedReader; |
| import java.io.BufferedWriter; |
| import java.io.IOException; |
| import java.nio.charset.Charset; |
| import java.nio.charset.StandardCharsets; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.StandardOpenOption; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.EnumSet; |
| import java.util.List; |
| import java.util.Random; |
| import java.util.function.IntFunction; |
| import java.util.function.Supplier; |
| import java.util.stream.OpTestCase; |
| import java.util.stream.Stream; |
| import java.util.stream.TestData; |
| import jdk.testlibrary.RandomFactory; |
| |
| public class StreamLinesTest extends OpTestCase { |
| |
| enum LineSeparator { |
| NONE(""), |
| N("\n"), |
| R("\r"), |
| RN("\r\n"); |
| |
| public final String value; |
| |
| LineSeparator(String value) { |
| this.value = value; |
| } |
| |
| public String toString() { |
| return name(); |
| } |
| } |
| |
| static Path generateTempFileWithLines(IntFunction<String> lineGenerator, |
| IntFunction<LineSeparator> lineSeparatorGenerator, |
| int lines, Charset cs, boolean endLineSep) throws IOException { |
| Path p = Files.createTempFile("lines", null); |
| BufferedWriter bw = Files.newBufferedWriter(p, cs); |
| |
| for (int i = 0; i < lines - 1; i++) { |
| bw.write(lineGenerator.apply(i)); |
| bw.write(lineSeparatorGenerator.apply(i).value); |
| } |
| if (lines > 0) { |
| bw.write(lineGenerator.apply(lines - 1)); |
| if (endLineSep) |
| bw.write(lineSeparatorGenerator.apply(lines - 1).value); |
| } |
| |
| bw.flush(); |
| bw.close(); |
| p.toFile().deleteOnExit(); |
| |
| return p; |
| } |
| |
| static void writeLineSeparator(Path p, |
| IntFunction<LineSeparator> lineSeparatorGenerator, |
| int lines, Charset cs) throws IOException { |
| BufferedWriter bw = Files.newBufferedWriter(p, cs, StandardOpenOption.APPEND); |
| bw.write(lineSeparatorGenerator.apply(lines - 1).value); |
| bw.flush(); |
| bw.close(); |
| } |
| |
| static List<String> readAllLines(Path path, Charset cs) throws IOException { |
| try (BufferedReader reader = Files.newBufferedReader(path, cs)) { |
| List<String> result = new ArrayList<>(); |
| for (; ; ) { |
| String line = reader.readLine(); |
| if (line == null) |
| break; |
| result.add(line); |
| } |
| return result; |
| } |
| } |
| |
| static Object[] of(String description, IntFunction<String> lineGenerator, |
| IntFunction<LineSeparator> separatorGenerator, int n, Charset cs) { |
| return new Object[]{description, lineGenerator, separatorGenerator, n, cs}; |
| } |
| |
| private static final Random random = RandomFactory.getRandom(); |
| |
| @DataProvider |
| public static Object[][] lines() { |
| List<Object[]> l = new ArrayList<>(); |
| |
| // Include the three supported optimal-line charsets and one |
| // which does not |
| List<Charset> charsets = Arrays.asList(StandardCharsets.UTF_8, |
| StandardCharsets.US_ASCII, |
| StandardCharsets.ISO_8859_1, |
| StandardCharsets.UTF_16); |
| String[] lines = {"", "A", "AB", "ABC", "ABCD"}; |
| int[] linesSizes = {0, 1, 2, 3, 4, 16, 256, 1024}; |
| |
| for (Charset charset : charsets) { |
| for (int linesSize : linesSizes) { |
| if (linesSize > 0) { |
| for (String line : lines) { |
| for (LineSeparator ls : EnumSet.complementOf(EnumSet.of(LineSeparator.NONE))) { |
| String description = String.format("%d lines of \"%s\" with separator %s", linesSize, line, ls); |
| l.add(of(description, |
| i -> line, |
| i -> ls, |
| linesSize, charset)); |
| } |
| } |
| } else { |
| l.add(of("Empty file: 0 lines", |
| i -> "", |
| i -> LineSeparator.NONE, |
| 0, charset)); |
| } |
| } |
| } |
| |
| for (Charset charset : charsets) { |
| l.add(of("A maximum of 1024 random lines and separators", |
| i -> lines[1 + random.nextInt(lines.length - 1)], |
| i -> LineSeparator.values()[random.nextInt(LineSeparator.values().length)], |
| 1024, charset)); |
| } |
| |
| for (Charset charset : charsets) { |
| l.add(of("One large line with no separators", |
| i -> "ABCD", |
| i -> LineSeparator.NONE, |
| 1024, charset)); |
| } |
| |
| return l.toArray(new Object[][]{}); |
| } |
| |
| @Test(dataProvider = "lines") |
| public void test(String description, |
| IntFunction<String> lineGenerator, IntFunction<LineSeparator> separatorGenerator, |
| int lines, Charset cs) throws IOException { |
| Path p = generateTempFileWithLines(lineGenerator, separatorGenerator, lines, cs, false); |
| |
| Supplier<Stream<String>> ss = () -> { |
| try { |
| return Files.lines(p, cs); |
| } |
| catch (IOException e) { |
| throw new RuntimeException(e); |
| } |
| }; |
| |
| // Test without a separator at the end |
| List<String> expected = readAllLines(p, cs); |
| withData(TestData.Factory.ofSupplier("Lines with no separator at end", ss)) |
| .stream(s -> s) |
| .expectedResult(expected) |
| .exercise(); |
| |
| // Test with a separator at the end |
| writeLineSeparator(p, separatorGenerator, lines, cs); |
| expected = readAllLines(p, cs); |
| withData(TestData.Factory.ofSupplier("Lines with separator at end", ss)) |
| .stream(s -> s) |
| .expectedResult(expected) |
| .exercise(); |
| } |
| |
| } |