llvm-project
86 строк · 2.6 Кб
1#!/usr/bin/env python
2"""lldb-repro
3
4lldb-repro is a utility to transparently capture and replay debugger sessions
5through the command line driver. Its used to test the reproducers by running
6the test suite twice.
7
8During the first run, with 'capture' as its first argument, it captures a
9reproducer for every lldb invocation and saves it to a well-know location
10derived from the arguments and current working directory.
11
12During the second run, with 'replay' as its first argument, the test suite is
13run again but this time every invocation of lldb replays the previously
14recorded session.
15"""
16
17import hashlib18import os19import shutil20import subprocess21import sys22import tempfile23
24
25def help():26print("usage: {} capture|replay [args]".format(sys.argv[0]))27
28
29def main():30if len(sys.argv) < 2:31help()32return 133
34# Compute an MD5 hash based on the input arguments and the current working35# directory.36h = hashlib.md5()37h.update(" ".join(sys.argv[2:]).encode("utf-8"))38h.update(os.getcwd().encode("utf-8"))39input_hash = h.hexdigest()40
41# Use the hash to "uniquely" identify a reproducer path.42reproducer_path = os.path.join(tempfile.gettempdir(), input_hash)43
44# Create a new lldb invocation with capture or replay enabled.45lldb = os.path.join(os.path.dirname(sys.argv[0]), "lldb")46new_args = [lldb]47if sys.argv[1] == "replay":48new_args.extend(["--replay", reproducer_path])49elif sys.argv[1] == "capture":50new_args.extend(51[52"--capture",53"--capture-path",54reproducer_path,55"--reproducer-generate-on-exit",56]57)58new_args.extend(sys.argv[2:])59else:60help()61return 162
63exit_code = subprocess.call(new_args)64
65# The driver always exists with a zero exit code during replay. Store the66# exit code and return that for tests that expect a non-zero exit code.67exit_code_path = os.path.join(reproducer_path, "exit_code.txt")68if sys.argv[1] == "replay":69replay_exit_code = exit_code70with open(exit_code_path, "r") as f:71exit_code = int(f.read())72if replay_exit_code != 0:73print("error: replay failed with exit code {}".format(replay_exit_code))74print("invocation: " + " ".join(new_args))75# Return 1 if the expected exit code is 0 or vice versa.76return 1 if (exit_code == 0) else 077shutil.rmtree(reproducer_path, True)78elif sys.argv[1] == "capture":79with open(exit_code_path, "w") as f:80f.write("%d" % exit_code)81
82return exit_code83
84
85if __name__ == "__main__":86exit(main())87