Split SingleTestRunner.run()

pull/3322/head
Aleksey Filippov 7 years ago
parent 0e8c69b796
commit 827d33c8b6
  1. 196
      mesonbuild/mtest.py

@ -219,112 +219,110 @@ class SingleTestRunner:
def run(self): def run(self):
cmd = self._get_cmd() cmd = self._get_cmd()
if cmd is None: if cmd is None:
res = TestResult.SKIP skip_stdout = 'Not run because can not execute cross compiled binaries.'
duration = 0.0 return TestRun(res=TestResult.SKIP, returncode=GNU_SKIP_RETURNCODE,
stdo = 'Not run because can not execute cross compiled binaries.' should_fail=self.test.should_fail, duration=0.0,
stde = None stdo=skip_stdout, stde=None, cmd=None, env=self.test.env)
returncode = GNU_SKIP_RETURNCODE
else: else:
wrap = TestHarness.get_wrapper(self.options) wrap = TestHarness.get_wrapper(self.options)
if self.options.gdb: if self.options.gdb:
self.test.timeout = None self.test.timeout = None
return self._run_cmd(wrap + cmd + self.test.cmd_args + self.options.test_args)
cmd = wrap + cmd + self.test.cmd_args + self.options.test_args
starttime = time.time() def _run_cmd(self, cmd):
starttime = time.time()
if len(self.test.extra_paths) > 0:
self.env['PATH'] = os.pathsep.join(self.test.extra_paths + ['']) + self.env['PATH'] if len(self.test.extra_paths) > 0:
self.env['PATH'] = os.pathsep.join(self.test.extra_paths + ['']) + self.env['PATH']
# If MALLOC_PERTURB_ is not set, or if it is set to an empty value,
# (i.e., the test or the environment don't explicitly set it), set # If MALLOC_PERTURB_ is not set, or if it is set to an empty value,
# it ourselves. We do this unconditionally for regular tests # (i.e., the test or the environment don't explicitly set it), set
# because it is extremely useful to have. # it ourselves. We do this unconditionally for regular tests
# Setting MALLOC_PERTURB_="0" will completely disable this feature. # because it is extremely useful to have.
if ('MALLOC_PERTURB_' not in self.env or not self.env['MALLOC_PERTURB_']) and not self.options.benchmark: # Setting MALLOC_PERTURB_="0" will completely disable this feature.
self.env['MALLOC_PERTURB_'] = str(random.randint(1, 255)) if ('MALLOC_PERTURB_' not in self.env or not self.env['MALLOC_PERTURB_']) and not self.options.benchmark:
self.env['MALLOC_PERTURB_'] = str(random.randint(1, 255))
stdout = None
stderr = None stdout = None
if not self.options.verbose: stderr = None
stdout = subprocess.PIPE if not self.options.verbose:
stderr = subprocess.PIPE if self.options and self.options.split else subprocess.STDOUT stdout = subprocess.PIPE
stderr = subprocess.PIPE if self.options and self.options.split else subprocess.STDOUT
# Let gdb handle ^C instead of us
# Let gdb handle ^C instead of us
if self.options.gdb:
previous_sigint_handler = signal.getsignal(signal.SIGINT)
# Make the meson executable ignore SIGINT while gdb is running.
signal.signal(signal.SIGINT, signal.SIG_IGN)
def preexec_fn():
if self.options.gdb: if self.options.gdb:
previous_sigint_handler = signal.getsignal(signal.SIGINT) # Restore the SIGINT handler for the child process to
# Make the meson executable ignore SIGINT while gdb is running. # ensure it can handle it.
signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGINT, signal.SIG_DFL)
def preexec_fn():
if self.options.gdb:
# Restore the SIGINT handler for the child process to
# ensure it can handle it.
signal.signal(signal.SIGINT, signal.SIG_DFL)
else:
# We don't want setsid() in gdb because gdb needs the
# terminal in order to handle ^C and not show tcsetpgrp()
# errors avoid not being able to use the terminal.
os.setsid()
p = subprocess.Popen(cmd,
stdout=stdout,
stderr=stderr,
env=self.env,
cwd=self.test.workdir,
preexec_fn=preexec_fn if not is_windows() else None)
timed_out = False
kill_test = False
if self.test.timeout is None:
timeout = None
elif self.options.timeout_multiplier is not None:
timeout = self.test.timeout * self.options.timeout_multiplier
else: else:
timeout = self.test.timeout # We don't want setsid() in gdb because gdb needs the
try: # terminal in order to handle ^C and not show tcsetpgrp()
(stdo, stde) = p.communicate(timeout=timeout) # errors avoid not being able to use the terminal.
except subprocess.TimeoutExpired: os.setsid()
if self.options.verbose:
print("%s time out (After %d seconds)" % (self.test.name, timeout)) p = subprocess.Popen(cmd,
timed_out = True stdout=stdout,
except KeyboardInterrupt: stderr=stderr,
mlog.warning("CTRL-C detected while running %s" % (self.test.name)) env=self.env,
kill_test = True cwd=self.test.workdir,
finally: preexec_fn=preexec_fn if not is_windows() else None)
if self.options.gdb: timed_out = False
# Let us accept ^C again kill_test = False
signal.signal(signal.SIGINT, previous_sigint_handler) if self.test.timeout is None:
timeout = None
if kill_test or timed_out: elif self.options.timeout_multiplier is not None:
# Python does not provide multiplatform support for timeout = self.test.timeout * self.options.timeout_multiplier
# killing a process and all its children so we need else:
# to roll our own. timeout = self.test.timeout
if is_windows(): try:
subprocess.call(['taskkill', '/F', '/T', '/PID', str(p.pid)]) (stdo, stde) = p.communicate(timeout=timeout)
else: except subprocess.TimeoutExpired:
try: if self.options.verbose:
os.killpg(os.getpgid(p.pid), signal.SIGKILL) print("%s time out (After %d seconds)" % (self.test.name, timeout))
except ProcessLookupError: timed_out = True
# Sometimes (e.g. with Wine) this happens. except KeyboardInterrupt:
# There's nothing we can do (maybe the process mlog.warning("CTRL-C detected while running %s" % (self.test.name))
# already died) so carry on. kill_test = True
pass finally:
(stdo, stde) = p.communicate() if self.options.gdb:
endtime = time.time() # Let us accept ^C again
duration = endtime - starttime signal.signal(signal.SIGINT, previous_sigint_handler)
stdo = decode(stdo)
if stde: if kill_test or timed_out:
stde = decode(stde) # Python does not provide multiplatform support for
if timed_out: # killing a process and all its children so we need
res = TestResult.TIMEOUT # to roll our own.
elif p.returncode == GNU_SKIP_RETURNCODE: if is_windows():
res = TestResult.SKIP subprocess.call(['taskkill', '/F', '/T', '/PID', str(p.pid)])
elif self.test.should_fail == bool(p.returncode):
res = TestResult.OK
else: else:
res = TestResult.FAIL try:
returncode = p.returncode os.killpg(os.getpgid(p.pid), signal.SIGKILL)
return TestRun(res, returncode, self.test.should_fail, duration, stdo, stde, cmd, self.test.env) except ProcessLookupError:
# Sometimes (e.g. with Wine) this happens.
# There's nothing we can do (maybe the process
# already died) so carry on.
pass
(stdo, stde) = p.communicate()
endtime = time.time()
duration = endtime - starttime
stdo = decode(stdo)
if stde:
stde = decode(stde)
if timed_out:
res = TestResult.TIMEOUT
elif p.returncode == GNU_SKIP_RETURNCODE:
res = TestResult.SKIP
elif self.test.should_fail == bool(p.returncode):
res = TestResult.OK
else:
res = TestResult.FAIL
return TestRun(res, p.returncode, self.test.should_fail, duration, stdo, stde, cmd, self.test.env)
class TestHarness: class TestHarness:

Loading…
Cancel
Save