[lldb] Fix TestLoadUnload.py (#117416)
[llvm-project.git] / lldb / scripts / reproducer-replay.py
blobf44e3cf4935385da6603a55a6b0c08c749c5be43
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(
14 [LLDB, "--replay", path], stdout=subprocess.PIPE, 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.",
75 parser.add_argument(
76 "-t",
77 "--timeout",
78 type=int,
79 default=60,
80 help="Replay timeout in seconds. 60 seconds if not specified.",
82 parser.add_argument(
83 "-p",
84 "--path",
85 type=str,
86 default=os.getcwd(),
87 help="Path to the directory containing the reproducers. The current working directory if not specified.",
89 parser.add_argument(
90 "-l",
91 "--lldb",
92 type=str,
93 required=True,
94 help="Path to the LLDB command line driver",
96 parser.add_argument(
97 "-v", "--verbose", help="Print replay output.", action="store_true"
99 parser.add_argument(
100 "--failure-only", help="Only log failures.", action="store_true"
102 args = parser.parse_args()
104 global LLDB
105 global TIMEOUT
106 global VERBOSE
107 global FAILURE_ONLY
108 LLDB = args.lldb
109 TIMEOUT = args.timeout
110 VERBOSE = args.verbose
111 FAILURE_ONLY = args.failure_only
113 print(
114 f"Replaying reproducers in {args.path} with {args.threads} threads and a {args.timeout} seconds timeout"
117 try:
118 pool = Pool(args.threads)
119 pool.map(run_reproducer, find_reproducers(args.path))
120 except KeyboardInterrupt:
121 print("Interrupted")