[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
This commit is contained in:
Jonas Devlieghere 2020-04-15 10:24:34 -07:00
parent bf94c96007
commit 7ce1a93efd
1 changed files with 100 additions and 0 deletions

100
lldb/scripts/reproducer-replay.py Executable file
View File

@ -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')