164562Sgshapiro#!/usr/bin/env python3 264562Sgshapiro 338032Speterfrom multiprocessing import Pool 438032Speterimport multiprocessing 538032Speterimport argparse 638032Speterimport tempfile 738032Speterimport logging 838032Speterimport os 938032Speterimport subprocess 1038032Speter 1138032Speter 1264562Sgshapirodef run_reproducer(path): 1338032Speter proc = subprocess.Popen([LLDB, '--replay', path], 1438032Speter stdout=subprocess.PIPE, 1538032Speter stderr=subprocess.PIPE) 1638032Speter reason = None 1738032Speter try: 1838032Speter outs, errs = proc.communicate(timeout=TIMEOUT) 1938032Speter success = proc.returncode == 0 2064562Sgshapiro result = 'PASSED' if success else 'FAILED' 2138032Speter if not success: 2238032Speter outs = outs.decode() 2338032Speter errs = errs.decode() 2438032Speter # Do some pattern matching to find out the cause of the failure. 2538032Speter if 'Encountered unexpected packet during replay' in errs: 2638032Speter reason = 'Unexpected packet' 2738032Speter elif 'Assertion failed' in errs: 2838032Speter reason = 'Assertion failed' 2938032Speter elif 'UNREACHABLE' in errs: 3038032Speter reason = 'Unreachable executed' 3138032Speter elif 'Segmentation fault' in errs: 3238032Speter reason = 'Segmentation fault' 3338032Speter elif 'Illegal instruction' in errs: 3438032Speter reason = 'Illegal instruction' 3538032Speter else: 3638032Speter reason = f'Exit code {proc.returncode}' 3738032Speter except subprocess.TimeoutExpired: 3838032Speter proc.kill() 3938032Speter success = False 4038032Speter outs, errs = proc.communicate() 4138032Speter result = 'TIMEOUT' 4238032Speter 4338032Speter if not FAILURE_ONLY or not success: 4438032Speter reason_str = f' ({reason})' if reason else '' 4538032Speter print(f'{result}: {path}{reason_str}') 4638032Speter if VERBOSE: 4738032Speter if outs: 4838032Speter print(outs) 4938032Speter if errs: 5038032Speter print(errs) 5138032Speter 5238032Speter 5338032Speterdef find_reproducers(path): 5438032Speter for root, dirs, files in os.walk(path): 5538032Speter for dir in dirs: 5638032Speter _, extension = os.path.splitext(dir) 5738032Speter if dir.startswith('Test') and extension == '.py': 5838032Speter yield os.path.join(root, dir) 5938032Speter 6038032Speter 6138032Speterif __name__ == '__main__': 6238032Speter parser = argparse.ArgumentParser( 6338032Speter description='LLDB API Test Replay Driver. ' 6438032Speter 'Replay one or more reproducers in parallel using the specified LLDB driver. ' 6538032Speter 'The script will look for reproducers generated by the API lit test suite. ' 6638032Speter 'To generate the reproducers, pass --param \'lldb-run-with-repro=capture\' to lit.' 6738032Speter ) 6838032Speter parser.add_argument( 6938032Speter '-j', 7038032Speter '--threads', 7138032Speter type=int, 7238032Speter default=multiprocessing.cpu_count(), 7338032Speter help='Number of threads. The number of CPU threads if not specified.') 7464562Sgshapiro parser.add_argument( 7538032Speter '-t', 7638032Speter '--timeout', 7738032Speter type=int, 7838032Speter default=60, 7938032Speter help='Replay timeout in seconds. 60 seconds if not specified.') 8038032Speter parser.add_argument( 8138032Speter '-p', 8264562Sgshapiro '--path', 8338032Speter type=str, 8438032Speter default=os.getcwd(), 8538032Speter help= 8638032Speter 'Path to the directory containing the reproducers. The current working directory if not specified.' 8738032Speter ) 8838032Speter parser.add_argument('-l', 8938032Speter '--lldb', 9038032Speter type=str, 9138032Speter required=True, 9238032Speter help='Path to the LLDB command line driver') 9338032Speter parser.add_argument('-v', 9438032Speter '--verbose', 9538032Speter help='Print replay output.', 9638032Speter action='store_true') 9738032Speter parser.add_argument('--failure-only', 9838032Speter help='Only log failures.', 9938032Speter action='store_true') 10038032Speter args = parser.parse_args() 10138032Speter 10238032Speter global LLDB 10338032Speter global TIMEOUT 10438032Speter global VERBOSE 10538032Speter global FAILURE_ONLY 10638032Speter LLDB = args.lldb 10764562Sgshapiro TIMEOUT = args.timeout 10838032Speter VERBOSE = args.verbose 10938032Speter FAILURE_ONLY = args.failure_only 11038032Speter 11138032Speter print( 11238032Speter f'Replaying reproducers in {args.path} with {args.threads} threads and a {args.timeout} seconds timeout' 11338032Speter ) 11438032Speter 11538032Speter try: 11638032Speter pool = Pool(args.threads) 11738032Speter pool.map(run_reproducer, find_reproducers(args.path)) 11864562Sgshapiro except KeyboardInterrupt: 11964562Sgshapiro print('Interrupted') 12064562Sgshapiro