-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8285452: Add a new test library API to replace a file content using FileUtils.java #8360
Conversation
👋 Welcome back ssahoo! A progress list of the required criteria for merging this PR into |
Webrevs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
API doc added along with some changes in the code.
/contributor add weijun |
@sisahoo |
var froms = from.stream() | ||
.map(String::trim) | ||
.collect(Collectors.joining()); | ||
if (!removed.equals(froms)) { | ||
throw new IOException("Removed not the same"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a bit strange. I would suggest to return the removed lines instead, or to pass a Consumer<String>
(or even better, a Predicate<String>
?) that will accept the removed lines. You could continue to remove if the predicate returns true and throw if it returns false. It would also enable you to tell exactly which line failed the check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We just want to provide the removed lines and the added lines at the same time (just like what a patch file looks like). The exception here can probably be enhanced to show the actual difference of removed
from from
. Two blocks of code (call and callback) would be needed if a consumer or predicate is used, and I don't feel it's worth doing. Here I've already trimmed the lines to make sure whitespaces do not matter.
Can you elaborate on the use case, what tests would it be used in? The hardcoded Is this equivalent to looking for a substring aka |
We have a test that dynamically downloads a source file from an artifact server, patches it, compiles it, and then runs it. We don't want to include a static copy of the file inside the test. This method is just a Java version of the Yes, all It's not equivalent to a find/replace because replacement can only happen between |
I can provide additional Test to Test this Test library. |
Or we can provide an example in the method spec. |
If it is just for one/few tests, it would fit better in the directory with the test or in the test itself. Overwriting the input file seems like a bad choice, it will be a trap for someone. |
Currently it's just for one test, but it's the exact kind of method that should go into the test library, i.e. a general purpose file manipulation utility that can be useful by everyone.
|
Please change the issue/pr title to indicate it is a new API in the test library. |
I've updated the title of the bug. Siba can update the PR title. You're right that it's not easy to discover such APIs. We put it in As for the API itself, we've imagined something like
but the current form is the simplest case and could be kept even if we have a verbose one. |
I will do a small change in method signature patch(Path path, int fromLine, int toLine, List from, String to) where the argument "List from" to be "String from". This looks more useful given java supports multi-line String. Also a new open Test will be added into this change-set to verify this new API . |
b | ||
c"""; | ||
// 1st line has a space character | ||
String sabc = " " + System.lineSeparator() + abc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's strange that jcheck fails, if there is space character in beginning of line in a multiline string. So i have to follow this way add a space character in the beginning of multiline string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use \s instead of space. Then you will have no complaints.
var lines = Files.readAllLines(path); | ||
if (from != null) { | ||
var removed = ""; | ||
for (int i = fromLine; i <= toLine; i++) { | ||
removed += lines.remove(fromLine - 1).trim(); | ||
} | ||
var froms = from.stream() | ||
var froms = Arrays.asList(from.split(System.lineSeparator())).stream() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about just using from.lines()
?
/** | ||
* Patches a part of a file. | ||
* @param path of file | ||
* @param fromLine the first line to patch. This is the number you see in an editor, 1-based. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this should mention whether the fromLine
is inclusive, like it's noted for the toLine
?
* @param to the newly added line, can be multiple lines or empty. Cannot be null. | ||
* @throws IOException | ||
*/ | ||
public static void patch(Path path, int fromLine, int toLine, String from, String to) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this method check whether the fromLine
and toLine
are valid values? Things like, negative value or 0 or toLine
being less than fromLine
. I'm not familiar with the expectations of test library code - maybe those checks aren't necessary since this is a test util?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lines.remove()
and lines.subList()
will throw the correct exception. Since you asked, we can add it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that we call subList
at the beginning, I think there's no need to explicitly perform a check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello Weijun, the change to this part of the code in context of index checks, looks fine to me now. Thank you for considering it.
if (from != null) { | ||
var removed = ""; | ||
for (int i = fromLine; i <= toLine; i++) { | ||
removed += lines.remove(fromLine - 1).trim(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't you insert a "\n" ? otherwise concatenating lines "ab" and "c" will be the same as concatenating lines "a" and "bc".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also calling trim() assumes that white spaces are not significant. This might not be the case in the general case (for instance - think of markdown files were leading spaces are significant).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comparison is intentionally made lax so the caller does not need to provide the exact indentation or even new line characters. We think along with fromLine
and toLine
this is enough to make sure we are not modifying the wrong lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the comparison be better implemented by the caller then, who will know whether spaces are important or not? That's why I had suggested taking a Predicate<String>
that could be called with each line removed, and the caller could interrupt the parsing by returning false when they detect a mismatch with what they expect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can provide a more sophisticated Function<String,String>
replacer if we want to let user to customize all the details. This time we still only want them to be string literals. I agree we can keep the new lines inside, but trimming on each line and the final block is still useful so caller does not need to care about indentation and empty lines at both ends.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK - if you keep the internal new lines I have no objection. The API doc should however say that lines will be trimmed before comparing them.
// Replace a range of lines with mismatched lines | ||
test(abcList, 1, 3, "ab", xyz, "xyz"); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any thought of using TestNG with a DataProvider? Seems more efficient
@sisahoo This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 132 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/integrate |
Going to push as commit 0462d5a.
Your commit was automatically rebased without conflicts. |
A new API to support replacing selective lines with desired content.
Progress
Issue
Reviewers
Contributors
<weijun@openjdk.org>
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/8360/head:pull/8360
$ git checkout pull/8360
Update a local copy of the PR:
$ git checkout pull/8360
$ git pull https://git.openjdk.java.net/jdk pull/8360/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 8360
View PR using the GUI difftool:
$ git pr show -t 8360
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/8360.diff