[docs] Update HowToReleaseLLVM documentation.
[llvm-project.git] / lldb / scripts / reproducer-replay.py
blob40d7cebca05d4e76a42bfd6a4280140f4336a1aa
1 #!/usr/bin/env python3
3 from multiprocessing import Pool
4 import multiprocessing
5 import argparse
6 import tempfile
7 import logging
8 import os
9 import subprocess
12 def run_reproducer(path):
13 proc = subprocess.Popen([LLDB, '--replay', path],
14 stdout=subprocess.PIPE,
15 stderr=subprocess.PIPE)
16 reason = None
17 try:
18 outs, errs = proc.communicate(timeout=TIMEOUT)
19 success = proc.returncode == 0
20 result = 'PASSED' if success else 'FAILED'
21 if not success:
22 outs = outs.decode()
23 errs = errs.decode()
24 # Do some pattern matching to find out the cause of the failure.
25 if 'Encountered unexpected packet during replay' in errs:
26 reason = 'Unexpected packet'
27 elif 'Assertion failed' in errs:
28 reason = 'Assertion failed'
29 elif 'UNREACHABLE' in errs:
30 reason = 'Unreachable executed'
31 elif 'Segmentation fault' in errs:
32 reason = 'Segmentation fault'
33 elif 'Illegal instruction' in errs:
34 reason = 'Illegal instruction'
35 else:
36 reason = f'Exit code {proc.returncode}'
37 except subprocess.TimeoutExpired:
38 proc.kill()
39 success = False
40 outs, errs = proc.communicate()
41 result = 'TIMEOUT'
43 if not FAILURE_ONLY or not success:
44 reason_str = f' ({reason})' if reason else ''
45 print(f'{result}: {path}{reason_str}')
46 if VERBOSE:
47 if outs:
48 print(outs)
49 if errs:
50 print(errs)
53 def find_reproducers(path):
54 for root, dirs, files in os.walk(path):
55 for dir in dirs:
56 _, extension = os.path.splitext(dir)
57 if dir.startswith('Test') and extension == '.py':
58 yield os.path.join(root, dir)
61 if __name__ == '__main__':
62 parser = argparse.ArgumentParser(
63 description='LLDB API Test Replay Driver. '
64 'Replay one or more reproducers in parallel using the specified LLDB driver. '
65 'The script will look for reproducers generated by the API lit test suite. '
66 'To generate the reproducers, pass --param \'lldb-run-with-repro=capture\' to lit.'
68 parser.add_argument(
69 '-j',
70 '--threads',
71 type=int,
72 default=multiprocessing.cpu_count(),
73 help='Number of threads. The number of CPU threads if not specified.')
74 parser.add_argument(
75 '-t',
76 '--timeout',
77 type=int,
78 default=60,
79 help='Replay timeout in seconds. 60 seconds if not specified.')
80 parser.add_argument(
81 '-p',
82 '--path',
83 type=str,
84 default=os.getcwd(),
85 help=
86 'Path to the directory containing the reproducers. The current working directory if not specified.'
88 parser.add_argument('-l',
89 '--lldb',
90 type=str,
91 required=True,
92 help='Path to the LLDB command line driver')
93 parser.add_argument('-v',
94 '--verbose',
95 help='Print replay output.',
96 action='store_true')
97 parser.add_argument('--failure-only',
98 help='Only log failures.',
99 action='store_true')
100 args = parser.parse_args()
102 global LLDB
103 global TIMEOUT
104 global VERBOSE
105 global FAILURE_ONLY
106 LLDB = args.lldb
107 TIMEOUT = args.timeout
108 VERBOSE = args.verbose
109 FAILURE_ONLY = args.failure_only
111 print(
112 f'Replaying reproducers in {args.path} with {args.threads} threads and a {args.timeout} seconds timeout'
115 try:
116 pool = Pool(args.threads)
117 pool.map(run_reproducer, find_reproducers(args.path))
118 except KeyboardInterrupt:
119 print('Interrupted')