Add result logging to run_script, make returns DRY

This commit is contained in:
Erik Johnson 2018-06-04 00:17:41 -05:00
parent 0b85d1273f
commit af02d5ba7b
No known key found for this signature in database
GPG key ID: 5E5583C437808F3F

View file

@ -247,9 +247,15 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
with_retcode=False,
# FIXME A timeout of zero or disabling timeouts may not return results!
timeout=15,
raw=False):
raw=False,
log_output=None):
'''
Execute a script with the given argument string
The ``log_output`` argument is ternary, it can be True, False, or None.
If the value is boolean, then it forces the results to either be logged
or not logged. If it is None, then the return code of the subprocess
determines whether or not to log results.
'''
script_path = self.get_script_path(script)
if not os.path.isfile(script_path):
@ -293,6 +299,46 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
popen_kwargs['preexec_fn'] = detach_from_parent_group
def format_return(retcode, stdout, stderr=None):
'''
DRY helper to log script result if it failed, and then return the
desired output based on whether or not stderr was desired, and
wither or not a retcode was desired.
'''
if log_output is True or \
(log_output is None and (retcode is None or retcode != 0)):
if stderr is not None:
log.debug(
'run_script results for: %s %s\n'
'return code: %s\n'
'stdout:\n'
'%s\n\n'
'stderr:\n'
'%s',
script, arg_str, retcode, stdout, stderr
)
else:
log.debug(
'run_script results for: %s %s\n'
'return code: %s\n'
'stdout:\n'
'%s',
script, arg_str, retcode, stdout
)
if not raw:
stdout = stdout.splitlines()
if stderr is not None:
stderr = stderr.splitlines()
ret = [stdout]
if catch_stderr:
ret.append(stderr)
if with_retcode:
ret.append(retcode)
return ret[0] if len(ret) == 1 else tuple(ret)
process = subprocess.Popen(cmd, **popen_kwargs)
# Late import
@ -304,7 +350,12 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
while True:
process.poll()
time.sleep(0.1)
if datetime.now() > stop_at:
if datetime.now() <= stop_at:
# We haven't reached the timeout yet
if process.returncode is not None:
break
else:
# We've reached the timeout
if term_sent is False:
# Kill the process group since sending the term signal
# would only terminate the shell, not the command
@ -331,23 +382,13 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
# If errno is not "no such process", raise
raise
out = [
return format_return(
process.returncode,
'Process took more than {0} seconds to complete. '
'Process Killed!'.format(timeout)
]
if catch_stderr:
err = ['Process killed, unable to catch stderr output']
if with_retcode:
return out, err, process.returncode
else:
return out, err
if with_retcode:
return out, process.returncode
else:
return out
'Process Killed!'.format(timeout),
'Process killed, unable to catch stderr output'
)
if process.returncode is not None:
break
tmp_file.seek(0)
if sys.version_info >= (3,):
@ -382,25 +423,10 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
process.stdout.close()
if process.stderr is not None:
process.stderr.close()
# pylint: disable=maybe-no-member
try:
if with_retcode:
if out is not None and err is not None:
if not raw:
return out.splitlines(), err.splitlines(), process.returncode
else:
return out, err, process.returncode
return out.splitlines(), [], process.returncode
else:
if out is not None and err is not None:
if not raw:
return out.splitlines(), err.splitlines()
else:
return out, err
if not raw:
return out.splitlines(), []
else:
return out, []
return format_return(process.returncode, out, err or '')
finally:
try:
if os.path.exists(tmp_file.name):
@ -423,16 +449,7 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
process.stdout.close()
try:
if with_retcode:
if not raw:
return out.splitlines(), process.returncode
else:
return out, process.returncode
else:
if not raw:
return out.splitlines()
else:
return out
return format_return(process.returncode, out)
finally:
try:
if os.path.exists(tmp_file.name):