#!/usr/bin/env python3 """Tally a ctest --output-junit file as "passed failed skipped". Split out of .github/workflows/test.yml's negative-control step so that the workflow, the local gate and the control smoke test all count a run the same way. WHY THIS EXISTS AT ALL (ID-46 finding 8, second half). The counter this replaces lived inline in the workflow and counted a case as having "run" when it was merely not : if case.find('skipped') is None and case.get('status') not in ('notrun', 'disabled'): ran += 1 so a case that RAN AND FAILED armed the negative controls below it. Combined with the `|| true` that hid the baseline's exit code, a lane in which every split entry was already red reported itself armed, and a control that turns an already-red entry red then "passed". Passed, failed and skipped are three different answers and the caller needs all three. """ import sys import xml.etree.ElementTree as ET # P6 `t6`: ONE FLAG PER ARM, because the prefix IS the arm and a shared flag would let a lane # tally the other lane's entries and call itself run. Exit gate 9.3 compares the two. ARM_PREFIXES = { '--require-split-ran': 'DirectGLES.Split.', '--require-spawn-ran': 'DirectGLES.Spawn.', } def tally(path, prefix=None): passed = failed = skipped = 0 for case in ET.parse(path).getroot().iter('testcase'): if prefix is not None and not case.get('name', '').startswith(prefix): continue if case.find('failure') is not None or case.find('error') is not None: failed += 1 elif case.find('skipped') is not None or case.get('status') in ('notrun', 'disabled'): skipped += 1 else: passed += 1 return passed, failed, skipped def main(): if len(sys.argv) not in (2, 3) or (len(sys.argv) == 3 and sys.argv[2] not in ARM_PREFIXES): print("usage: junit_tally.py [" + " | ".join(sorted(ARM_PREFIXES)) + "]", file=sys.stderr) return 2 try: prefix = ARM_PREFIXES[sys.argv[2]] if len(sys.argv) == 3 else None passed, failed, skipped = tally(sys.argv[1], prefix=prefix) except Exception as exc: # a malformed file is not "zero of everything" print(f"junit_tally: cannot parse {sys.argv[1]}: {exc}", file=sys.stderr) return 1 print(f"{passed} {failed} {skipped}") if len(sys.argv) == 3 and (passed == 0 or failed): print(f'{prefix} baseline FAILED: no successful entries with that arm prefix, or an ' f'already-red selection', file=sys.stderr) return 1 return 0 if __name__ == '__main__': raise SystemExit(main())