From d1727ada18452c954bd8cb9ca04d96f82384d59a Mon Sep 17 00:00:00 2001 From: Shashank Date: Fri, 21 Nov 2025 17:45:43 +0530 Subject: [PATCH 1/2] Add graceful error handling for malformed XML reports --- tools/stats/upload_test_stats.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/stats/upload_test_stats.py b/tools/stats/upload_test_stats.py index 45a390fc5051d..4484197025835 100644 --- a/tools/stats/upload_test_stats.py +++ b/tools/stats/upload_test_stats.py @@ -49,7 +49,12 @@ def parse_xml_report( test_cases: list[dict[str, Any]] = [] - root = ET.parse(report) + try: + root = ET.parse(report) + except: + print(f"Warning: Could not parse {report}, skipping") + return test_cases + for test_case in root.iter(tag): case = process_xml_element(test_case) case["workflow_id"] = workflow_id From 30cc2093183b4603c772995cd4851b328d35f04d Mon Sep 17 00:00:00 2001 From: Shashank Date: Fri, 21 Nov 2025 17:56:40 +0530 Subject: [PATCH 2/2] Improve error handling and validation for test report processing --- tools/stats/upload_test_stats.py | 44 +++++++++++++++++++------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/tools/stats/upload_test_stats.py b/tools/stats/upload_test_stats.py index 4484197025835..aec191aa44904 100644 --- a/tools/stats/upload_test_stats.py +++ b/tools/stats/upload_test_stats.py @@ -88,7 +88,8 @@ def process_xml_element( # # becomes: # {"name": "test_foo", "classname": "test_bar"} - ret.update(element.attrib) + if element.attrib: + ret.update(element.attrib) # The XML format encodes all values as strings. Convert to ints/floats if # possible to make aggregation possible in SQL. @@ -206,22 +207,25 @@ def init_value(test_case: dict[str, Any]) -> dict[str, Any]: ret = {} for test_case in test_cases: - key = get_key(test_case) - if key not in ret: - ret[key] = init_value(test_case) - - ret[key]["tests"] += 1 - - if "failure" in test_case: - ret[key]["failures"] += 1 - elif "error" in test_case: - ret[key]["errors"] += 1 - elif "skipped" in test_case: - ret[key]["skipped"] += 1 - else: - ret[key]["successes"] += 1 - - ret[key]["time"] += test_case["time"] + try: + key = get_key(test_case) + if key not in ret: + ret[key] = init_value(test_case) + + ret[key]["tests"] += 1 + + if "failure" in test_case: + ret[key]["failures"] += 1 + elif "error" in test_case: + ret[key]["errors"] += 1 + elif "skipped" in test_case: + ret[key]["skipped"] += 1 + else: + ret[key]["successes"] += 1 + + ret[key]["time"] += test_case.get("time", 0) + except: + continue return list(ret.values()) @@ -252,7 +256,11 @@ def init_value(test_case: dict[str, Any]) -> dict[str, Any]: print(f"Workflow id is: {args.workflow_run_id}") - test_cases = get_tests(args.workflow_run_id, args.workflow_run_attempt) + try: + test_cases = get_tests(args.workflow_run_id, args.workflow_run_attempt) + except Exception as e: + print(f"Error getting tests: {e}") + test_cases = [] # Flush stdout so that any errors in the upload show up last in the logs. sys.stdout.flush()