tests: Add argument to trim output to a reasonable size
The output of the "values" tshark glossary has over 1.3M lines. Writing this to stdout with some test failures is problematic in a number of ways. Also it's not helpful because stderr is written after stdout (not interleaved) so there is no output context to the error message. The error/warning message (from stderr, that triggered the test failure) needs to be sufficient to provide a good understaning of the test failure. The output is trimmed to first+last N lines. Some lines are kept as informational and because it may be useful if the program aborts. Fixes #17203.
This commit is contained in:
parent
791d101d4d
commit
ba23c3b316
|
@ -55,6 +55,7 @@ class LoggingPopen(subprocess.Popen):
|
|||
'''
|
||||
def __init__(self, proc_args, *args, **kwargs):
|
||||
self.log_fd = kwargs.pop('log_fd', None)
|
||||
self.max_lines = kwargs.pop('max_lines', None)
|
||||
kwargs['stdout'] = subprocess.PIPE
|
||||
kwargs['stderr'] = subprocess.PIPE
|
||||
# Make sure communicate() gives us bytes.
|
||||
|
@ -63,11 +64,24 @@ class LoggingPopen(subprocess.Popen):
|
|||
super().__init__(proc_args, *args, **kwargs)
|
||||
self.stdout_str = ''
|
||||
self.stderr_str = ''
|
||||
|
||||
@staticmethod
|
||||
def trim_output(out_log, max_lines):
|
||||
lines = out_log.splitlines(True)
|
||||
if not len(lines) > max_lines * 2 + 1:
|
||||
return out_log
|
||||
header = lines[:max_lines]
|
||||
body = lines[max_lines:-max_lines]
|
||||
body = "<<< trimmed {} lines of output >>>\n".format(len(body))
|
||||
footer = lines[-max_lines:]
|
||||
return ''.join(header) + body + ''.join(footer)
|
||||
|
||||
def wait_and_log(self):
|
||||
'''Wait for the process to finish and log its output.'''
|
||||
out_data, err_data = self.communicate(timeout=process_timeout)
|
||||
out_log = out_data.decode('UTF-8', 'replace')
|
||||
if self.max_lines and self.max_lines > 0:
|
||||
out_log = self.trim_output(out_log, self.max_lines)
|
||||
err_log = err_data.decode('UTF-8', 'replace')
|
||||
self.log_fd.flush()
|
||||
self.log_fd.write('-- Begin stdout for {} --\n'.format(self.cmd_str))
|
||||
|
@ -249,7 +263,7 @@ class SubprocessTestCase(unittest.TestCase):
|
|||
return False
|
||||
return True
|
||||
|
||||
def startProcess(self, proc_args, stdin=None, env=None, shell=False, cwd=None):
|
||||
def startProcess(self, proc_args, stdin=None, env=None, shell=False, cwd=None, max_lines=None):
|
||||
'''Start a process in the background. Returns a subprocess.Popen object.
|
||||
|
||||
You typically wait for it using waitProcess() or assertWaitProcess().'''
|
||||
|
@ -261,7 +275,7 @@ class SubprocessTestCase(unittest.TestCase):
|
|||
# fixture (via a test method parameter or class decorator).
|
||||
assert not (env is None and hasattr(self, '_fixture_request')), \
|
||||
"Decorate class with @fixtures.mark_usefixtures('test_env')"
|
||||
proc = LoggingPopen(proc_args, stdin=stdin, env=env, shell=shell, log_fd=self.log_fd, cwd=cwd)
|
||||
proc = LoggingPopen(proc_args, stdin=stdin, env=env, shell=shell, log_fd=self.log_fd, cwd=cwd, max_lines=max_lines)
|
||||
self.processes.append(proc)
|
||||
return proc
|
||||
|
||||
|
@ -278,14 +292,14 @@ class SubprocessTestCase(unittest.TestCase):
|
|||
process.wait_and_log()
|
||||
self.assertEqual(process.returncode, expected_return)
|
||||
|
||||
def runProcess(self, args, env=None, shell=False, cwd=None):
|
||||
def runProcess(self, args, env=None, shell=False, cwd=None, max_lines=None):
|
||||
'''Start a process and wait for it to finish.'''
|
||||
process = self.startProcess(args, env=env, shell=shell, cwd=cwd)
|
||||
process = self.startProcess(args, env=env, shell=shell, cwd=cwd, max_lines=max_lines)
|
||||
process.wait_and_log()
|
||||
return process
|
||||
|
||||
def assertRun(self, args, env=None, shell=False, expected_return=0, cwd=None):
|
||||
def assertRun(self, args, env=None, shell=False, expected_return=0, cwd=None, max_lines=None):
|
||||
'''Start a process and wait for it to finish. Check its return code.'''
|
||||
process = self.runProcess(args, env=env, shell=shell, cwd=cwd)
|
||||
process = self.runProcess(args, env=env, shell=shell, cwd=cwd, max_lines=max_lines)
|
||||
self.assertEqual(process.returncode, expected_return)
|
||||
return process
|
||||
|
|
|
@ -165,7 +165,7 @@ class case_tshark_dump_glossaries(subprocesstest.SubprocessTestCase):
|
|||
self.log_fd.truncate()
|
||||
except Exception:
|
||||
pass
|
||||
self.assertRun((cmd_tshark, '-G', glossary), env=base_env)
|
||||
self.assertRun((cmd_tshark, '-G', glossary), env=base_env, max_lines=20)
|
||||
self.assertEqual(self.countOutput(count_stdout=False, count_stderr=True), 0, 'Found error output while printing glossary ' + glossary)
|
||||
|
||||
def test_tshark_glossary_valid_utf8(self, cmd_tshark, base_env):
|
||||
|
|
Loading…
Reference in New Issue