import shlex
import subprocess
import sys
+import threading
SCRUBBER = 'SCRUBBER: '
ERROR_SCRUBBER = 'ERROR-SCRUBBER: '
COMMAND_LINE = 'COMMAND-LINE: '
+def run_process(args, cwd, timeout, s_input=None):
+ """Runs a process with a timeout `timeout` in seconds. `args` are the
+ arguments to execute, `cwd` is the working directory and `s_input` is the
+ input to be sent to the process over stdin. Returns the output, the error
+ output and the exit code of the process. If the process times out, the
+ output and the error output are empty and the exit code is 124."""
+
+ proc = subprocess.Popen(
+ args,
+ cwd=cwd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ out = ''
+ err = ''
+ exit_status = 124
+ timer = threading.Timer(timeout, lambda p: p.kill(), [proc])
+ try:
+ timer.start()
+ out, err = proc.communicate(input=s_input)
+ exit_status = proc.returncode
+ finally:
+ timer.cancel()
+
+ return out, err, exit_status
+
+
def run_benchmark(dump, wrapper, scrubber, error_scrubber, cvc4_binary,
- command_line, benchmark_dir, benchmark_filename):
+ command_line, benchmark_dir, benchmark_filename, timeout):
"""Runs CVC4 on the file `benchmark_filename` in the directory
`benchmark_dir` using the binary `cvc4_binary` with the command line
options `command_line`. The output is scrubbed using `scrubber` and
'--preprocess-only', '--dump', 'raw-benchmark',
'--output-lang=smt2', '-qq'
]
- dump_process = subprocess.Popen(
+ dump_output, _, _ = run_process(
bin_args + command_line + dump_args + [benchmark_filename],
- cwd=benchmark_dir,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- dump_output, _ = dump_process.communicate()
- process = subprocess.Popen(
- bin_args + command_line + ['--lang=smt2', '-'],
- cwd=benchmark_dir,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- output, error = process.communicate(input=dump_output)
- exit_status = process.returncode
+ benchmark_dir, timeout)
+ output, error, exit_status = run_process(
+ bin_args + command_line + ['--lang=smt2', '-'], benchmark_dir,
+ timeout, dump_output)
else:
- process = subprocess.Popen(
- bin_args + command_line + [benchmark_filename],
- cwd=benchmark_dir,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- output, error = process.communicate()
- exit_status = process.returncode
+ output, error, exit_status = run_process(
+ bin_args + command_line + [benchmark_filename], benchmark_dir,
+ timeout)
# If a scrubber command has been specified then apply it to the output.
if scrubber:
- scrubber_process = subprocess.Popen(
- shlex.split(scrubber),
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- output, _ = scrubber_process.communicate(input=output)
+ output, _, _ = run_process(
+ shlex.split(scrubber), benchmark_dir, timeout, output)
if error_scrubber:
- error_scrubber_process = subprocess.Popen(
- shlex.split(error_scrubber),
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- error, _ = error_scrubber_process.communicate(input=error)
+ error, _, _ = run_process(
+ shlex.split(error_scrubber), benchmark_dir, timeout, error)
# Popen in Python 3 returns a bytes object instead of a string for
# stdout/stderr.
return (output.strip(), error.strip(), exit_status)
-def run_regression(proof, dump, wrapper, cvc4_binary, benchmark_path):
+def run_regression(proof, dump, wrapper, cvc4_binary, benchmark_path, timeout):
"""Determines the expected output for a benchmark, runs CVC4 on it and then
checks whether the output corresponds to the expected output. Optionally
uses a wrapper `wrapper`, tests proof generation (if proof is true), or
for command_line_args in command_line_args_configs:
output, error, exit_status = run_benchmark(
dump, wrapper, scrubber, error_scrubber, cvc4_binary,
- command_line_args, benchmark_dir, benchmark_basename)
+ command_line_args, benchmark_dir, benchmark_basename, timeout)
if output != expected_output:
print(
'not ok - Differences between expected and actual output on stdout - Flags: {}'.
if os.environ.get('VALGRIND') == '1' and not wrapper:
wrapper = ['libtool', '--mode=execute', 'valgrind']
- run_regression(args.proof, args.dump, wrapper, cvc4_binary, args.benchmark)
+ timeout = float(os.getenv('TEST_TIMEOUT', 600.0))
+
+ run_regression(args.proof, args.dump, wrapper, cvc4_binary, args.benchmark,
+ timeout)
if __name__ == "__main__":