mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 16:36:46 +00:00
122 lines
3.7 KiB
Python
Executable File
122 lines
3.7 KiB
Python
Executable File
#!/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)
|
|
success = proc.returncode == 0
|
|
result = "PASSED" if success else "FAILED"
|
|
if not success:
|
|
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()
|
|
success = False
|
|
outs, errs = proc.communicate()
|
|
result = "TIMEOUT"
|
|
|
|
if not FAILURE_ONLY or not success:
|
|
reason_str = f" ({reason})" if reason else ""
|
|
print(f"{result}: {path}{reason_str}")
|
|
if VERBOSE:
|
|
if outs:
|
|
print(outs)
|
|
if errs:
|
|
print(errs)
|
|
|
|
|
|
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",
|
|
)
|
|
parser.add_argument(
|
|
"-v", "--verbose", help="Print replay output.", action="store_true"
|
|
)
|
|
parser.add_argument(
|
|
"--failure-only", help="Only log failures.", action="store_true"
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
global LLDB
|
|
global TIMEOUT
|
|
global VERBOSE
|
|
global FAILURE_ONLY
|
|
LLDB = args.lldb
|
|
TIMEOUT = args.timeout
|
|
VERBOSE = args.verbose
|
|
FAILURE_ONLY = args.failure_only
|
|
|
|
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")
|