Skip to content

Commit cdd79e0

Browse files
cbeauchesnedevflow.devflow-routing-intake
andauthored
Tag intermediate initializationError retries with test.final_status=skip in JUnit XML (#11010)
Removes Initialization error from junit XML Address comments Use java script apply the logic by classname Use JAVA_25_HOME Merge branch 'master' into cbeauchesne/remove-initialization-error Merge branch 'master' into cbeauchesne/remove-initialization-error Do not tag if the property already exists Merge branch 'master' into cbeauchesne/remove-initialization-error Better comment Update .gitlab/TagInitializationErrors.java Co-authored-by: Brice Dutheil <brice.dutheil@gmail.com> Update .gitlab/TagInitializationErrors.java Co-authored-by: Brice Dutheil <brice.dutheil@gmail.com> Update .gitlab/TagInitializationErrors.java Co-authored-by: Brice Dutheil <brice.dutheil@gmail.com> Add before/after in comment Write output to a temp file then atomically rename it Merge branch 'master' into cbeauchesne/remove-initialization-error Add XML configuration Co-authored-by: devflow.devflow-routing-intake <devflow.devflow-routing-intake@kubernetes.us1.ddbuild.io>
1 parent 1ee99fb commit cdd79e0

2 files changed

Lines changed: 117 additions & 0 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import org.w3c.dom.Element;
2+
import javax.xml.XMLConstants;
3+
import javax.xml.parsers.DocumentBuilderFactory;
4+
import javax.xml.transform.OutputKeys;
5+
import javax.xml.transform.TransformerFactory;
6+
import javax.xml.transform.dom.DOMSource;
7+
import javax.xml.transform.stream.StreamResult;
8+
import java.io.File;
9+
import java.nio.file.Files;
10+
import java.util.ArrayList;
11+
import java.util.LinkedHashMap;
12+
import java.util.List;
13+
import java.util.Map;
14+
15+
/// Tags intermediate `initializationError` retries with `dd_tags[test.final_status]=skip`.
16+
///
17+
/// Gradle generates synthetic "initializationError" testcases in JUnit reports for setup methods.
18+
/// When a setup is retried and eventually succeeds, multiple testcases are created, with only the
19+
/// last one passing. All intermediate attempts are marked skip so Test Optimization is not misled.
20+
///
21+
/// For any suite with multiple `initializationError` test cases (when retries occurred), all entries
22+
/// but the last one are tagged by this script with `dd_tags[test.final_status]=skip`. The last
23+
/// entry is left unmodified, allowing **Test Optimization** to apply its default status inference based
24+
/// on the actual outcome. Files with only one (or zero) `initializationError` test cases are left unmodified.
25+
///
26+
/// Before:
27+
///
28+
/// ```
29+
/// <testcase name="initializationError" />
30+
/// ```
31+
///
32+
/// After:
33+
///
34+
/// ```
35+
/// <testcase name="initializationError">
36+
/// <properties>
37+
/// <property name="dd_tags[test.final_status]" value="skip" />
38+
/// </properties>
39+
/// </testcase>
40+
/// ```
41+
///
42+
/// Usage (Java 25): `java TagInitializationErrors.java junit-report.xml`
43+
44+
class TagInitializationErrors {
45+
public static void main(String[] args) throws Exception {
46+
if (args.length == 0) {
47+
System.err.println("Usage: java TagInitializationErrors.java <xml-file>");
48+
System.exit(1);
49+
}
50+
var xmlFile = new File(args[0]);
51+
if (!xmlFile.exists()) {
52+
System.err.println("File not found: " + xmlFile);
53+
System.exit(1);
54+
}
55+
var dbf = DocumentBuilderFactory.newInstance();
56+
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
57+
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
58+
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
59+
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
60+
dbf.setExpandEntityReferences(false);
61+
var doc = dbf.newDocumentBuilder().parse(xmlFile);
62+
var testcases = doc.getElementsByTagName("testcase");
63+
Map<String, List<Element>> byClassname = new LinkedHashMap<>();
64+
for (int i = 0; i < testcases.getLength(); i++) {
65+
var e = (Element) testcases.item(i);
66+
if ("initializationError".equals(e.getAttribute("name"))) {
67+
byClassname.computeIfAbsent(e.getAttribute("classname"), k -> new ArrayList<>()).add(e);
68+
}
69+
}
70+
boolean modified = false;
71+
for (var group : byClassname.values()) {
72+
if (group.size() <= 1) continue;
73+
for (int i = 0; i < group.size() - 1; i++) {
74+
var testcase = group.get(i);
75+
var existingProperties = testcase.getElementsByTagName("properties");
76+
if (existingProperties.getLength() > 0) {
77+
var props = (Element) existingProperties.item(0);
78+
var existingProps = props.getElementsByTagName("property");
79+
boolean alreadyTagged = false;
80+
for (int j = 0; j < existingProps.getLength(); j++) {
81+
if ("dd_tags[test.final_status]".equals(((Element) existingProps.item(j)).getAttribute("name"))) {
82+
alreadyTagged = true;
83+
break;
84+
}
85+
}
86+
if (alreadyTagged) continue;
87+
var property = doc.createElement("property");
88+
property.setAttribute("name", "dd_tags[test.final_status]");
89+
property.setAttribute("value", "skip");
90+
props.appendChild(property);
91+
} else {
92+
var properties = doc.createElement("properties");
93+
var property = doc.createElement("property");
94+
property.setAttribute("name", "dd_tags[test.final_status]");
95+
property.setAttribute("value", "skip");
96+
properties.appendChild(property);
97+
testcase.appendChild(properties);
98+
}
99+
modified = true;
100+
}
101+
}
102+
if (!modified) return;
103+
var tmpFile = File.createTempFile("TagInitializationErrors", ".xml", xmlFile.getParentFile());
104+
try {
105+
var transformer = TransformerFactory.newInstance().newTransformer();
106+
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
107+
transformer.transform(new DOMSource(doc), new StreamResult(tmpFile));
108+
Files.move(tmpFile.toPath(), xmlFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
109+
} catch (Exception e) {
110+
tmpFile.delete();
111+
throw e;
112+
}
113+
}
114+
}

.gitlab/collect_results.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ do
9090
echo " (non-stable test names detected)"
9191
fi
9292

93+
echo "Add dd_tags[test.final_status] property on retried synthetics testcase initializationErrors"
94+
$JAVA_25_HOME/bin/java "$(dirname "$0")/TagInitializationErrors.java" "$TARGET_DIR/$AGGREGATED_FILE_NAME"
95+
9396
echo "Add dd_tags[test.final_status] property to each testcase on $TARGET_DIR/$AGGREGATED_FILE_NAME"
9497
xsl_file="$(dirname "$0")/add_final_status.xsl"
9598
tmp_file="$(mktemp)"

0 commit comments

Comments
 (0)