summaryrefslogtreecommitdiff
path: root/lldb/scripts
diff options
context:
space:
mode:
authorJonas Devlieghere <jonas@devlieghere.com>2020-04-15 10:24:34 -0700
committerJonas Devlieghere <jonas@devlieghere.com>2020-04-15 10:55:41 -0700
commit7ce1a93efd0700770f7c5c368999a44db0d222e8 (patch)
tree8b7e90262e0f61a3a23dea08f244e9f2681a2218 /lldb/scripts
parentbf94c960071d338b7157ac7dee8120df50d5600f (diff)
downloadllvm-7ce1a93efd0700770f7c5c368999a44db0d222e8.tar.gz
[lldb/Scripts] Add script to replay multiple reproducers
Script to replay reproducers in parallel using the command line driver. This is used for active replay (stage 1 as described in the RFC on lldb-dev [1]). [1] http://lists.llvm.org/pipermail/lldb-dev/2020-April/016100.html Differential revision: https://reviews.llvm.org/D77608
Diffstat (limited to 'lldb/scripts')
-rwxr-xr-xlldb/scripts/reproducer-replay.py100
1 files changed, 100 insertions, 0 deletions
diff --git a/lldb/scripts/reproducer-replay.py b/lldb/scripts/reproducer-replay.py
new file mode 100755
index 000000000000..5e9fab176ab6
--- /dev/null
+++ b/lldb/scripts/reproducer-replay.py
@@ -0,0 +1,100 @@
+#! /usr/bin/env python3
+
+from multiprocessing import Pool
+import multiprocessing
+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):
+ for root, dirs, files in os.walk(path):
+ for dir in dirs:
+ _, extension = os.path.splitext(dir)
+ if dir.startswith('Test') and extension == '.py':
+ yield os.path.join(root, dir)
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(
+ description='LLDB API Test Replay Driver. '
+ 'Replay one or more reproducers in parallel using the specified LLDB driver. '
+ 'The script will look for reproducers generated by the API lit test suite. '
+ 'To generate the reproducers, pass --param \'lldb-run-with-repro=capture\' to lit.'
+ )
+ parser.add_argument(
+ '-j',
+ '--threads',
+ type=int,
+ default=multiprocessing.cpu_count(),
+ help='Number of threads. The number of CPU threads if not specified.')
+ parser.add_argument(
+ '-t',
+ '--timeout',
+ type=int,
+ default=60,
+ help='Replay timeout in seconds. 60 seconds if not specified.')
+ parser.add_argument(
+ '-p',
+ '--path',
+ type=str,
+ default=os.getcwd(),
+ help=
+ 'Path to the directory containing the reproducers. The current working directory if not specified.'
+ )
+ parser.add_argument('-l',
+ '--lldb',
+ type=str,
+ required=True,
+ help='Path to the LLDB command line driver')
+ args = parser.parse_args()
+
+ global LLDB
+ global TIMEOUT
+ LLDB = args.lldb
+ TIMEOUT = args.timeout
+
+ print(
+ f'Replaying reproducers in {args.path} with {args.threads} threads and a {args.timeout} seconds timeout'
+ )
+
+ try:
+ pool = Pool(args.threads)
+ pool.map(run_reproducer, find_reproducers(args.path))
+ except KeyboardInterrupt:
+ print('Interrupted')