Skip to content
84 changes: 84 additions & 0 deletions .gitlab/TagInitializationErrors.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
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.
*
* <p>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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 suggestion: ‏It would help if you describe the expected changes here. You can re-use stuff from the PR description 😉

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 899ee14

*
* <p>For any suite with multiple initializationError testcases (i.e. retries occurred), all entries
* except the last one are already tagged with an existing `dd_tags[test.final_status]`. 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 testcases are not modified.
*
* <p>Usage (JEP 330): java TagInitializationErrors.java <xml-file>
*/
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);
Copy link
Copy Markdown
Contributor

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?

Copy link
Copy Markdown
Contributor Author

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.

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));
}
}
3 changes: 3 additions & 0 deletions .gitlab/collect_results.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ do
echo " (non-stable test names detected)"
fi

echo "Add dd_tags[test.final_status] property on retried synthetics testcase initializationErrors"
$JAVA_25_HOME/bin/java "$(dirname "$0")/TagInitializationErrors.java" "$TARGET_DIR/$AGGREGATED_FILE_NAME"

echo "Add dd_tags[test.final_status] property to each testcase on $TARGET_DIR/$AGGREGATED_FILE_NAME"
xsl_file="$(dirname "$0")/add_final_status.xsl"
tmp_file="$(mktemp)"
Expand Down
Loading