ctest-postprocess.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #!/usr/bin/env python3
  2. import argparse
  3. import re
  4. from typing import TextIO
  5. import xml.etree.ElementTree as ET
  6. from log_parser import ctest_log_parser, log_reader, GTEST_MARK, YUNIT_MARK
  7. from mute_utils import mute_target, remove_failure, update_suite_info, MuteTestCheck
  8. def find_targets_to_remove(log_fp):
  9. target_with_tests = set()
  10. for target, reason, buf in ctest_log_parser(log_fp):
  11. if reason != "Failed":
  12. continue
  13. for line in buf:
  14. if line.startswith((GTEST_MARK, YUNIT_MARK)):
  15. target_with_tests.add(target)
  16. break
  17. return target_with_tests
  18. shard_suffix_re = re.compile(r"_\d+$")
  19. def strip_shardname(testcase):
  20. name = testcase.get('classname')
  21. classname = shard_suffix_re.sub('', name)
  22. testcase.set('classname', classname)
  23. def postprocess_ctest(log_fp: TextIO, ctest_junit_report, is_mute_shard, dry_run):
  24. to_remove = find_targets_to_remove(log_fp)
  25. tree = ET.parse(ctest_junit_report)
  26. root = tree.getroot()
  27. n_remove_failures = n_skipped = 0
  28. for testcase in root.findall("testcase"):
  29. target = testcase.attrib["classname"]
  30. strip_shardname(testcase)
  31. if is_mute_shard(target):
  32. if mute_target(testcase):
  33. print(f"mute {target}")
  34. testcase.set("status", "run") # CTEST specific
  35. n_remove_failures += 1
  36. n_skipped += 1
  37. elif target in to_remove:
  38. print(f"set {target} as passed")
  39. n_remove_failures += 1
  40. remove_failure(testcase)
  41. update_suite_info(root, n_remove_failures, n_skipped=n_skipped)
  42. print(f"{'(dry-run) ' if dry_run else ''}update {ctest_junit_report}")
  43. if not dry_run:
  44. tree.write(ctest_junit_report, xml_declaration=True, encoding="UTF-8")
  45. def main():
  46. parser = argparse.ArgumentParser()
  47. parser.add_argument("--dry-run", action="store_true", default=False)
  48. parser.add_argument("--filter-file", required=False)
  49. parser.add_argument("--decompress", action="store_true", default=False, help="decompress ctest log")
  50. parser.add_argument("ctest_log", type=str)
  51. parser.add_argument("ctest_junit_report")
  52. args = parser.parse_args()
  53. log = log_reader(args.ctest_log, args.decompress)
  54. is_mute_shard = MuteTestCheck(args.filter_file)
  55. postprocess_ctest(log, args.ctest_junit_report, is_mute_shard, args.dry_run)
  56. if __name__ == "__main__":
  57. main()