Index: lldb/scripts/reproducer-replay.py =================================================================== --- /dev/null +++ lldb/scripts/reproducer-replay.py @@ -0,0 +1,98 @@ +#! /usr/bin/env python3 + +from multiprocessing import Pool +import argparse +import tempfile +import logging +import os +import subprocess + + +def run_reproducer(path): + proc = subprocess.Popen([LLDB, '--replay', path], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + reason = None + try: + outs, errs = proc.communicate(timeout=TIMEOUT) + result = 'PASSED' if proc.returncode == 0 else 'FAILED' + if proc.returncode != 0: + outs = outs.decode() + errs = errs.decode() + # Do some pattern matching to find out the cause of the failure. + if 'Encountered unexpected packet during replay' in errs: + reason = 'Unexpected packet' + elif 'Assertion failed' in errs: + reason = 'Assertion failed' + elif 'UNREACHABLE' in errs: + reason = 'Unreachable executed' + elif 'Segmentation fault' in errs: + reason = 'Segmentation fault' + elif 'Illegal instruction' in errs: + reason = 'Illegal instruction' + else: + reason = f'Exit code {proc.returncode}' + except subprocess.TimeoutExpired: + proc.kill() + outs, errs = proc.communicate() + result = 'TIMEOUT' + + reason_str = f' ({reason})' if reason else '' + print(f'{result}: {path}{reason_str}') + + +def find_reproducers(path): + reproducers = [] + for root, dirs, files in os.walk(path): + for dir in dirs: + _, extension = os.path.splitext(dir) + if dir.startswith('Test') and extension == '.py': + reproducers.append(os.path.join(root, dir)) + return reproducers + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='LLDB Replay Driver') + parser.add_argument('-j', + '--threads', + type=int, + default=8, + help='Number of threads') + parser.add_argument('-t', + '--timeout', + type=int, + default=60, + help='Replay timeout') + parser.add_argument('-l', + '--lldb', + type=str, + required=True, + help='Path to the LLDB command line driver') + parser.add_argument('-p', + '--path', + type=str, + default=None, + help='Path to directory containing the reproducers') + args = parser.parse_args() + + global LLDB + global TIMEOUT + LLDB = args.lldb + TIMEOUT = args.timeout + + if args.path: + path = args.path + else: + path = tempfile.gettempdir() + + print(f'Looking for reproducers in {path}') + reproducers = find_reproducers(path) + print(f'Found {len(reproducers)} reproducers') + print( + f'Replaying with {args.threads} threads and {args.timeout} seconds timeout' + ) + try: + pool = Pool(args.threads) + pool.map(run_reproducer, reproducers) + except KeyboardInterrupt: + print('Interrupted')