-
Notifications
You must be signed in to change notification settings - Fork 331
Tag intermediate initializationError retries with test.final_status=skip in JUnit XML
#11010
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
Open
cbeauchesne
wants to merge
14
commits into
master
Choose a base branch
from
cbeauchesne/remove-initialization-error
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+102
−0
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
c42a128
Removes Initialization error from junit XML
cbeauchesne 1f3708d
Address comments
cbeauchesne c044bba
Use java script
cbeauchesne c1bbc59
apply the logic by classname
cbeauchesne fc75f5f
Use JAVA_25_HOME
cbeauchesne 42fbf91
Merge branch 'master' into cbeauchesne/remove-initialization-error
cbeauchesne 492abbc
Merge branch 'master' into cbeauchesne/remove-initialization-error
cbeauchesne 814275c
Do not tag if the property already exists
cbeauchesne 4af16af
Merge branch 'master' into cbeauchesne/remove-initialization-error
cbeauchesne 899ee14
Better comment
cbeauchesne 96b50d9
Update .gitlab/TagInitializationErrors.java
cbeauchesne e98c700
Update .gitlab/TagInitializationErrors.java
cbeauchesne d904031
Update .gitlab/TagInitializationErrors.java
cbeauchesne 1b5a33e
Add before/after in comment
cbeauchesne File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| import org.w3c.dom.Element; | ||
| import javax.xml.parsers.DocumentBuilderFactory; | ||
| import javax.xml.transform.OutputKeys; | ||
| import javax.xml.transform.TransformerFactory; | ||
| import javax.xml.transform.dom.DOMSource; | ||
| import javax.xml.transform.stream.StreamResult; | ||
| import java.io.File; | ||
| import java.util.ArrayList; | ||
| import java.util.LinkedHashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| /// Tags intermediate `initializationError` retries with `dd_tags[test.final_status]=skip`. | ||
| /// | ||
| /// Gradle generates synthetic "initializationError" testcases in JUnit reports for setup methods. | ||
| /// When a setup is retried and eventually succeeds, multiple testcases are created, with only the | ||
| /// last one passing. All intermediate attempts are marked skip so Test Optimization is not misled. | ||
| /// | ||
| /// For any suite with multiple `initializationError` test cases (when retries occurred), all entries | ||
| /// but the last one are tagged by this script with `dd_tags[test.final_status]=skip`. The last | ||
| /// entry is left unmodified, allowing **Test Optimization** to apply its default status inference based | ||
| /// on the actual outcome. Files with only one (or zero) `initializationError` test cases are left unmodified. | ||
| /// | ||
| /// Before: | ||
| /// | ||
| /// ``` | ||
| /// <testcase name="initializationError" /> | ||
| /// ``` | ||
| /// | ||
| /// After: | ||
| /// | ||
| /// ``` | ||
| /// <testcase name="initializationError"> | ||
| /// <properties> | ||
| /// <property name="dd_tags[test.final_status]" value="skip" /> | ||
| /// </properties> | ||
| /// </testcase> | ||
| /// ``` | ||
| /// | ||
| /// Usage (Java 25): `java TagInitializationErrors.java junit-report.xml` | ||
|
|
||
| class TagInitializationErrors { | ||
| public static void main(String[] args) throws Exception { | ||
| if (args.length == 0) { | ||
| System.err.println("Usage: java TagInitializationErrors.java <xml-file>"); | ||
| System.exit(1); | ||
| } | ||
| var xmlFile = new File(args[0]); | ||
| if (!xmlFile.exists()) { | ||
| System.err.println("File not found: " + xmlFile); | ||
| System.exit(1); | ||
| } | ||
| var doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlFile); | ||
| var testcases = doc.getElementsByTagName("testcase"); | ||
| Map<String, List<Element>> byClassname = new LinkedHashMap<>(); | ||
| for (int i = 0; i < testcases.getLength(); i++) { | ||
| var e = (Element) testcases.item(i); | ||
| if ("initializationError".equals(e.getAttribute("name"))) { | ||
| byClassname.computeIfAbsent(e.getAttribute("classname"), k -> new ArrayList<>()).add(e); | ||
| } | ||
| } | ||
| boolean modified = false; | ||
| for (var group : byClassname.values()) { | ||
| if (group.size() <= 1) continue; | ||
| for (int i = 0; i < group.size() - 1; i++) { | ||
| var testcase = group.get(i); | ||
| var existingProperties = testcase.getElementsByTagName("properties"); | ||
| if (existingProperties.getLength() > 0) { | ||
| var props = (Element) existingProperties.item(0); | ||
| var existingProps = props.getElementsByTagName("property"); | ||
| boolean alreadyTagged = false; | ||
| for (int j = 0; j < existingProps.getLength(); j++) { | ||
| if ("dd_tags[test.final_status]".equals(((Element) existingProps.item(j)).getAttribute("name"))) { | ||
| alreadyTagged = true; | ||
| break; | ||
| } | ||
| } | ||
| if (alreadyTagged) continue; | ||
| var property = doc.createElement("property"); | ||
| property.setAttribute("name", "dd_tags[test.final_status]"); | ||
| property.setAttribute("value", "skip"); | ||
| props.appendChild(property); | ||
| } else { | ||
| var properties = doc.createElement("properties"); | ||
| var property = doc.createElement("property"); | ||
| property.setAttribute("name", "dd_tags[test.final_status]"); | ||
| property.setAttribute("value", "skip"); | ||
| properties.appendChild(property); | ||
| testcase.appendChild(properties); | ||
| } | ||
| modified = true; | ||
| } | ||
| } | ||
| if (!modified) return; | ||
| var transformer = TransformerFactory.newInstance().newTransformer(); | ||
| transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); | ||
| transformer.transform(new DOMSource(doc), new StreamResult(xmlFile)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note: This modifies the file in-place. What happens if the app fails? Does it leaves invalid documents? |
||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
❔ question: Should we add some flags about entity resolution (for example) here to prevent security issue?
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.
Which security issue do you have in mind ? The entire workflow and data are derivated from the public content of this repo, and the script itself can be modified during a PR.
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.
I think @PerfectSlayer refers to XML external entity, or other tricks: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java.
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.
If it's those, everything that runs here is produced by the PR content, including the script that execute the command. So i'm don't think that there is any increase in the surface attack.