8285452: Add a new test library API to replace a file content using FileUtils.java
Co-authored-by: Weijun Wang <weijun@openjdk.org> Reviewed-by: weijun, dfuchs
This commit is contained in:
parent
4282fb2b0d
commit
0462d5a252
124
test/lib-test/jdk/test/lib/FileUtilsTest.java
Normal file
124
test/lib-test/jdk/test/lib/FileUtilsTest.java
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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 8285452
|
||||
* @summary Unit Test for a common Test API in jdk.test.lib.util.FileUtils
|
||||
* @library .. /test/lib
|
||||
* @run main FileUtilsTest
|
||||
*/
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.util.FileUtils;
|
||||
|
||||
public class FileUtilsTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Replace with same line
|
||||
test("a", 1, 1, null, "a", "a\n");
|
||||
// Replace with different line
|
||||
test("a", 1, 1, null, "z", "z\n");
|
||||
// Replace with same line based on line match
|
||||
test("a", 1, 1, "a", "a", "a\n");
|
||||
// Replace with different line based on line match
|
||||
test("a", 1, 1, "a", "z", "z\n");
|
||||
// Replace single line with multiple lines
|
||||
test("a", 1, 1, null, "x\ny\nz", "x\ny\nz\n");
|
||||
// Replace single line with multiple lines based on lines match
|
||||
test("a", 1, 1, "a", "x\ny\nz", "x\ny\nz\n");
|
||||
// Replace all lines
|
||||
test("a\nb\nc", 1, 3, null, "x\ny\nz", "x\ny\nz\n");
|
||||
// Replace all lines based on lines match
|
||||
test("a\nb\nc", 1, 3, "a\nb\nc", "x\ny\nz", "x\ny\nz\n");
|
||||
// Replace all lines with single line based on lines match
|
||||
test("a\nb\nc", 1, 3, "a\nb\nc", "z", "z\n");
|
||||
// Replace single line
|
||||
test("a\nb\nc", 1, 1, null, "z", "z\nb\nc\n");
|
||||
// Replace single line based on line match
|
||||
test("a\nb\nc", 1, 1, "a", "z", "z\nb\nc\n");
|
||||
// Replace multiple lines
|
||||
test("a\nb\nc", 1, 2, null, "z", "z\nc\n");
|
||||
// Replace multiple lines based on line match
|
||||
test("a\nb\nc", 1, 2, "a\nb", "z", "z\nc\n");
|
||||
// Replace multiple lines based on line match
|
||||
test("a\nb\nc", 1, 2, "a\nb", "x\ny\nz", "x\ny\nz\nc\n");
|
||||
|
||||
// Test with space characters
|
||||
// Replace with space line
|
||||
test("\n", 1, 1, null, " ", " \n");
|
||||
// Replace empty line with another line based on line match
|
||||
test("\n", 1, 1, " ", "a", "a\n");
|
||||
// Replace with space line
|
||||
test(" \na\nb\nc", 1, 1, null, "a", "a\na\nb\nc\n");
|
||||
// Replace empty line with different line based on line match
|
||||
test(" \na\nb\nc", 1, 1, " ", "a", "a\na\nb\nc\n");
|
||||
// Replace range of lines with space to different lines based on line match
|
||||
test(" \na\nb\nc", 1, 2, " \na", "x\ny\nz", "x\ny\nz\nb\nc\n");
|
||||
|
||||
test("a\nb\nc\n", 1, 2, "a\nb", "1\n2", "1\n2\nc\n");
|
||||
test("a\nb\nc\n", 1, 2, " a\nb", "1\n2", "1\n2\nc\n"); // free to add spaces around a line in from
|
||||
test("a\nb\nc\n", 1, 2, "a \nb", "1\n2", "1\n2\nc\n");
|
||||
test("a\nb\nc\n", 1, 2, "a\n b ", "1\n2", "1\n2\nc\n");
|
||||
test("a\nb\nc\n", 1, 2, "\na\nb", "1\n2", "1\n2\nc\n"); // free to add empty lines at both ends of from
|
||||
test("a\nb\nc\n", 1, 2, "a\nb\n", "1\n2", "1\n2\nc\n");
|
||||
test("a\nb\nc\n", 1, 2, "\na\nb\n", "1\n2", "1\n2\nc\n");
|
||||
test("a\nb\nc\n", 1, 2, "\n\na\nb\n\n", "1\n2", "1\n2\nc\n");
|
||||
test("a\nb\nc\n", 1, 2, "a\nb", "1\n2\n", "1\n2\nc\n"); // ok to add a new line at end of to
|
||||
test("a\nb\nc\n", 1, 2, "a\nb", "1\n2\n\n", "1\n2\n\nc\n"); // more will change result
|
||||
test("a\nb\nc\n", 1, 2, "a\nb", "\n1\n2", "\n1\n2\nc\n");
|
||||
test("a\nb\nc\n", 1, 2, "a\n\nb", "1\n2\n", null); // no extra new line inside
|
||||
test("a\nb\nc\n", 1, 2, "ab", "1\n2\n", null); // new line inside must preserve
|
||||
test("a\nb\nc\n", 1, 2, "a", "1\n2\n", null); // must be all
|
||||
test("a\nb\nc\n", 1, 2, "b", "1\n2\n", null); // must be all
|
||||
|
||||
test("a\nb\nc\n", 1, 2, "a\nb", "", "c\n"); // just remove
|
||||
test("a\nb\nc\n", 1, 0, "", "1\n2", "1\n2\na\nb\nc\n"); // just add
|
||||
|
||||
// Mismatched range with "replace" lines Tests
|
||||
// Replace all lines with mismatched line
|
||||
test("a", 1, 1, "z", "z", null);
|
||||
// Replace all lines with mismatched lines
|
||||
test("a\nb\nc", 1, 3, "x\ny\nz", "x\ny\nz", null);
|
||||
// Replace single line with mismatched line
|
||||
test("a\nb\nc", 1, 1, "z", "z", null);
|
||||
// Replace a range of lines with mismatched lines
|
||||
test("a\nb\nc", 1, 3, "ab", "x\ny\nz", null);
|
||||
}
|
||||
|
||||
private static void test(String content, int from, int to, String replace,
|
||||
String replaceTo, String expected) throws IOException {
|
||||
String name = "Test-" + new Exception().getStackTrace()[1].getLineNumber();
|
||||
Path path = Files.writeString(Paths.get(name), content);
|
||||
String output = null;
|
||||
try {
|
||||
FileUtils.patch(path, from, to, replace, replaceTo);
|
||||
output = Files.readString(path);
|
||||
} catch (IOException e) {
|
||||
// output is null
|
||||
}
|
||||
Asserts.assertEQ(output, (expected != null) ? expected.replaceAll("\n", System.lineSeparator()) : null);
|
||||
}
|
||||
}
|
@ -47,7 +47,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
import com.sun.management.UnixOperatingSystemMXBean;
|
||||
@ -377,6 +377,44 @@ public final class FileUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches a part of a file.
|
||||
*
|
||||
* @param path the file
|
||||
* @param fromLine the first line to patch. This is the number you see in an editor, 1-based, inclusive.
|
||||
* @param toLine the last line to patch. This is the number you see in an editor, inclusive.
|
||||
* Set {@code toLine} to {@code fromLine - 1} if you only want to insert lines.
|
||||
* @param from lines to remove, used to ensure the correct lines are removed. Can be multiple lines or empty.
|
||||
* It's compared to existing lines with all lines trimmed and no new lines at both ends. Ignored if null.
|
||||
* @param to the newly added lines, can be multiple lines or empty. New line at end is optional. Cannot be null.
|
||||
* @throws IOException if there's an I/O error or {@code from} does not match the existing lines
|
||||
* @throws IndexOutOfBoundsException if {@code fromLine} or {@code toLine} is invalid
|
||||
*/
|
||||
public static void patch(Path path, int fromLine, int toLine, String from, String to) throws IOException {
|
||||
var lines = Files.readAllLines(path);
|
||||
// The next line does a from/to as well
|
||||
var subList = lines.subList(fromLine - 1, toLine);
|
||||
if (from != null) {
|
||||
// Each line is trimmed so caller needs not care about indentation.
|
||||
// Caller also needs not care about new lines on both ends.
|
||||
// New lines inside are preserved.
|
||||
String actuallyRemoved = subList.stream()
|
||||
.map(String::trim)
|
||||
.collect(Collectors.joining("\n")).trim();
|
||||
String wantToRemove = from.lines()
|
||||
.map(String::trim)
|
||||
.collect(Collectors.joining("\n")).trim();
|
||||
if (!actuallyRemoved.equals(wantToRemove)) {
|
||||
throw new IOException("Removed not the same: ["
|
||||
+ String.join("\\n", subList) + "] and ["
|
||||
+ from.replaceAll("\\n", "\\\\n") + "]");
|
||||
}
|
||||
}
|
||||
subList.clear();
|
||||
lines.addAll(fromLine - 1, to.lines().toList());
|
||||
Files.write(path, lines);
|
||||
}
|
||||
|
||||
private static native long getWinProcessHandleCount();
|
||||
|
||||
// Possible command locations and arguments
|
||||
|
Loading…
x
Reference in New Issue
Block a user