diff --git a/.gitlab/TagInitializationErrors.java b/.gitlab/TagInitializationErrors.java new file mode 100644 index 0000000000..4b477ea107 --- /dev/null +++ b/.gitlab/TagInitializationErrors.java @@ -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. + * + *

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 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. + * + *

Usage (JEP 330): java TagInitializationErrors.java + */ +class TagInitializationErrors { + public static void main(String[] args) throws Exception { + if (args.length == 0) { + System.err.println("Usage: java TagInitializationErrors.java "); + 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> 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)); + } +} diff --git a/.gitlab/collect_results.sh b/.gitlab/collect_results.sh index 5991a12590..dec34ed5d5 100755 --- a/.gitlab/collect_results.sh +++ b/.gitlab/collect_results.sh @@ -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)"