mesontest: Add a 'verbose' mode which does not capture stdout/err

And reuse that mode when running inside gdb instead of reimplementing
running test for that particular use case.
pull/1087/head
Thibault Saunier 8 years ago
parent 2584a9f27d
commit 5d866bb4f3
  1. 99
      mesontest.py

@ -18,11 +18,10 @@
import subprocess, sys, os, argparse import subprocess, sys, os, argparse
import pickle import pickle
import mesonbuild
from mesonbuild import build from mesonbuild import build
from mesonbuild import environment from mesonbuild import environment
import time, datetime, pickle, multiprocessing, json import time, datetime, multiprocessing, json
import concurrent.futures as conc import concurrent.futures as conc
import platform import platform
import signal import signal
@ -71,6 +70,8 @@ parser.add_argument('--logbase', default='testlog',
help="Base name for log file.") help="Base name for log file.")
parser.add_argument('--num-processes', default=determine_worker_count(), type=int, parser.add_argument('--num-processes', default=determine_worker_count(), type=int,
help='How many parallel processes to use.') help='How many parallel processes to use.')
parser.add_argument('-v', '--verbose', default=False, action='store_true',
help='Do not redirect stdout and stderr')
parser.add_argument('args', nargs='*') parser.add_argument('args', nargs='*')
class TestRun(): class TestRun():
@ -107,6 +108,8 @@ class TestRun():
return res return res
def decode(stream): def decode(stream):
if stream is None:
return ''
try: try:
return stream.decode('utf-8') return stream.decode('utf-8')
except UnicodeDecodeError: except UnicodeDecodeError:
@ -156,6 +159,7 @@ class TestHarness:
cmd = [test.exe_runner] + test.fname cmd = [test.exe_runner] + test.fname
else: else:
cmd = test.fname cmd = test.fname
if cmd is None: if cmd is None:
res = 'SKIP' res = 'SKIP'
duration = 0.0 duration = 0.0
@ -172,13 +176,20 @@ class TestHarness:
child_env.update(test.env) child_env.update(test.env)
if len(test.extra_paths) > 0: if len(test.extra_paths) > 0:
child_env['PATH'] = child_env['PATH'] + ';'.join([''] + test.extra_paths) child_env['PATH'] = child_env['PATH'] + ';'.join([''] + test.extra_paths)
if is_windows():
setsid = None setsid = None
else: stdout = None
setsid = os.setsid stderr = None
if not self.options.verbose:
stdout = subprocess.PIPE
stderr = subprocess.PIPE if self.options and self.options.split else subprocess.STDOUT
if not is_windows():
setsid = os.setsid
p = subprocess.Popen(cmd, p = subprocess.Popen(cmd,
stdout=subprocess.PIPE, stdout=stdout,
stderr=subprocess.PIPE if self.options and self.options.split else subprocess.STDOUT, stderr=stderr,
env=child_env, env=child_env,
cwd=test.workdir, cwd=test.workdir,
preexec_fn=setsid) preexec_fn=setsid)
@ -271,10 +282,15 @@ class TestHarness:
futures = [] futures = []
filtered_tests = filter_tests(self.options.suite, tests) filtered_tests = filter_tests(self.options.suite, tests)
with open(jsonlogfilename, 'w') as jsonlogfile, \ jsonlogfile = None
open(logfilename, 'w') as logfile: logfile = None
logfile.write('Log of Meson test suite run on %s.\n\n' % try:
datetime.datetime.now().isoformat()) if not self.options.verbose:
jsonlogfile = open(jsonlogfilename, 'w')
logfile = open(logfilename, 'w')
logfile.write('Log of Meson test suite run on %s.\n\n' %
datetime.datetime.now().isoformat())
for i, test in enumerate(filtered_tests): for i, test in enumerate(filtered_tests):
if test.suite[0] == '': if test.suite[0] == '':
visible_name = test.name visible_name = test.name
@ -288,20 +304,29 @@ class TestHarness:
self.drain_futures(futures) self.drain_futures(futures)
futures = [] futures = []
res = self.run_single_test(wrap, test) res = self.run_single_test(wrap, test)
self.print_stats(numlen, filtered_tests, visible_name, res, i, if not self.options.verbose:
logfile, jsonlogfile) self.print_stats(numlen, filtered_tests, visible_name, res, i,
logfile, jsonlogfile)
else: else:
f = executor.submit(self.run_single_test, wrap, test) f = executor.submit(self.run_single_test, wrap, test)
futures.append((f, numlen, filtered_tests, visible_name, i, if not self.options.verbose:
logfile, jsonlogfile)) futures.append((f, numlen, filtered_tests, visible_name, i,
self.drain_futures(futures) logfile, jsonlogfile))
self.drain_futures(futures, logfile, jsonlogfile)
finally:
if jsonlogfile:
jsonlogfile.close()
if logfile:
logfile.close()
return logfilename return logfilename
def drain_futures(self, futures): def drain_futures(self, futures, logfile, jsonlogfile):
for i in futures: for i in futures:
(result, numlen, tests, name, i, logfile, jsonlogfile) = i (result, numlen, tests, name, i, logfile, jsonlogfile) = i
self.print_stats(numlen, tests, name, result.result(), i, logfile, jsonlogfile) if not self.options.verbose:
self.print_stats(numlen, tests, name, result.result(), i, logfile, jsonlogfile)
def run_special(self): def run_special(self):
'Tests run by the user, usually something like "under gdb 1000 times".' 'Tests run by the user, usually something like "under gdb 1000 times".'
@ -326,11 +351,16 @@ class TestHarness:
for i in range(self.options.repeat): for i in range(self.options.repeat):
print('Running: %s %d/%d' % (t.name, i+1, self.options.repeat)) print('Running: %s %d/%d' % (t.name, i+1, self.options.repeat))
if self.options.gdb: if self.options.gdb:
gdbrun(t) wrap = ['gdb', '--quiet', '-ex', 'run', '-ex', 'quit']
if len(t.cmd_args) > 0:
wrap.append('--args')
res = self.run_single_test(wrap, t)
else: else:
res = self.run_single_test(wrap, t) res = self.run_single_test(wrap, t)
if (res.returncode == 0 and res.should_fail) or \ if (res.returncode == 0 and res.should_fail) or \
(res.returncode != 0 and not res.should_fail): (res.returncode != 0 and not res.should_fail) and \
not self.options.verbose:
print('Test failed:\n\n-- stdout --\n') print('Test failed:\n\n-- stdout --\n')
print(res.stdo) print(res.stdo)
print('\n-- stderr --\n') print('\n-- stderr --\n')
@ -343,34 +373,15 @@ def filter_tests(suite, tests):
return tests return tests
return [x for x in tests if suite in x.suite] return [x for x in tests if suite in x.suite]
def gdbrun(test):
child_env = os.environ.copy()
if isinstance(test.env, build.EnvironmentVariables):
test.env = test.env.get_env(child_env)
child_env.update(test.env)
# On success will exit cleanly. On failure gdb will ask user
# if they really want to exit.
exe = test.fname
args = test.cmd_args
if len(args) > 0:
argset = ['-ex', 'set args ' + ' '.join(args)]
else:
argset = []
cmd = ['gdb', '--quiet'] + argset + ['-ex', 'run', '-ex', 'quit'] + exe
# FIXME a ton of stuff. run_single_test grabs stdout & co,
# which we do not want to do when running under gdb.
p = subprocess.Popen(cmd,
env=child_env,
cwd=test.workdir,
)
p.communicate()
def run(args): def run(args):
options = parser.parse_args(args) options = parser.parse_args(args)
if options.benchmark: if options.benchmark:
options.num_processes = 1 options.num_processes = 1
if options.gdb:
options.verbose = True
th = TestHarness(options) th = TestHarness(options)
if options.list: if options.list:
return th.run_special() return th.run_special()

Loading…
Cancel
Save