diff options
author | Hemmo Nieminen <hemmo.nieminen@iki.fi> | 2016-02-26 21:18:21 +0200 |
---|---|---|
committer | Hemmo Nieminen <hemmo.nieminen@iki.fi> | 2016-04-01 00:51:12 +0300 |
commit | 297749581dd4dcb4e68da4b1d0622d2916fb8db3 (patch) | |
tree | 2f69bc1c3c61fbf1065d1cec51f513a92f23919b /mesonbuild/scripts/meson_test.py | |
parent | f2868420ca13c49ba25d00cd75b490d1629246a2 (diff) | |
download | meson-297749581dd4dcb4e68da4b1d0622d2916fb8db3.zip meson-297749581dd4dcb4e68da4b1d0622d2916fb8db3.tar.gz meson-297749581dd4dcb4e68da4b1d0622d2916fb8db3.tar.bz2 |
meson_test: Add support for --print-errorlogs option.
This option can be used to control whether the logs from failing tests
should be shown to the user after the tests have been executed.
Diffstat (limited to 'mesonbuild/scripts/meson_test.py')
-rw-r--r-- | mesonbuild/scripts/meson_test.py | 83 |
1 files changed, 49 insertions, 34 deletions
diff --git a/mesonbuild/scripts/meson_test.py b/mesonbuild/scripts/meson_test.py index 05c909d..01da9b4 100644 --- a/mesonbuild/scripts/meson_test.py +++ b/mesonbuild/scripts/meson_test.py @@ -25,7 +25,8 @@ def is_windows(): platname = platform.system().lower() return platname == 'windows' or 'mingw' in platname -tests_failed = [] +collected_logs = [] +error_count = 0 options = None parser = argparse.ArgumentParser() @@ -37,6 +38,8 @@ parser.add_argument('--suite', default=None, dest='suite', help='Only run tests belonging to this suite.') parser.add_argument('--no-stdsplit', default=True, dest='split', action='store_false', help='Do not split stderr and stdout in test logs.') +parser.add_argument('--print-errorlogs', default=False, action='store_true', + help="Whether to print faling tests' logs.") parser.add_argument('args', nargs='+') @@ -49,26 +52,31 @@ class TestRun(): self.stde = stde self.cmd = cmd + def get_log(self): + res = '--- command ---\n' + if self.cmd is None: + res += 'NONE\n' + else: + res += ' '.join(self.cmd) + '\n' + if self.stdo: + res += '--- stdout ---\n' + res += self.stdo + if self.stde: + if res[-1:] != '\n': + res += '\n' + res += '--- stderr ---\n' + res += self.stde + if res[-1:] != '\n': + res += '\n' + res += '-------\n\n' + return res + def decode(stream): try: return stream.decode('utf-8') except UnicodeDecodeError: return stream.decode('iso-8859-1', errors='ignore') -def write_log(logfile, test_name, result_str, result): - logfile.write(result_str + '\n\n') - logfile.write('--- command ---\n') - if result.cmd is None: - logfile.write('NONE') - else: - logfile.write(' '.join(result.cmd)) - logfile.write('\n--- "%s" stdout ---\n' % test_name) - logfile.write(result.stdo) - if result.stde: - logfile.write('\n--- "%s" stderr ---\n' % test_name) - logfile.write(result.stde) - logfile.write('\n-------\n\n') - def write_json_log(jsonlogfile, test_name, result): jresult = {'name' : test_name, 'stdout' : result.stdo, @@ -86,7 +94,7 @@ def run_with_mono(fname): return False def run_single_test(wrap, test): - global tests_failed, options + global options if test.fname[0].endswith('.jar'): cmd = ['java', '-jar'] + test.fname elif not test.is_cross and run_with_mono(test.fname[0]): @@ -146,17 +154,16 @@ def run_single_test(wrap, test): stde = decode(stde) if timed_out: res = 'TIMEOUT' - tests_failed.append((test.name, stdo, stde)) elif (not test.should_fail and p.returncode == 0) or \ (test.should_fail and p.returncode != 0): res = 'OK' else: res = 'FAIL' - tests_failed.append((test.name, stdo, stde)) returncode = p.returncode return TestRun(res, returncode, duration, stdo, stde, cmd) def print_stats(numlen, tests, name, result, i, logfile, jsonlogfile): + global collected_logs, error_count, options startpad = ' '*(numlen - len('%d' % (i+1))) num = '%s%d/%d' % (startpad, i+1, len(tests)) padding1 = ' '*(38-len(name)) @@ -164,7 +171,12 @@ def print_stats(numlen, tests, name, result, i, logfile, jsonlogfile): result_str = '%s %s %s%s%s%5.2f s' % \ (num, name, padding1, result.res, padding2, result.duration) print(result_str) - write_log(logfile, name, result_str, result) + result_str += "\n\n" + result.get_log() + if result.returncode != 0: + error_count += 1 + if options.print_errorlogs: + collected_logs.append(result_str) + logfile.write(result_str) write_json_log(jsonlogfile, name, result) def drain_futures(futures): @@ -229,8 +241,9 @@ def run_tests(datafilename): return logfilename def run(args): - global tests_failed, options - tests_failed = [] # To avoid state leaks when invoked multiple times (running tests in-process) + global collected_logs, error_count, options + collected_logs = [] # To avoid state leaks when invoked multiple times (running tests in-process) + error_count = 0 options = parser.parse_args(args) if len(options.args) != 1: print('Test runner for Meson. Do not run on your own, mmm\'kay?') @@ -239,19 +252,21 @@ def run(args): os.chdir(options.wd) datafile = options.args[0] logfilename = run_tests(datafile) - returncode = 0 - if len(tests_failed) > 0: - print('\nOutput of failed tests (max 10):') - for (name, stdo, stde) in tests_failed[:10]: - print("{} stdout:\n".format(name)) - print(stdo) - if stde: - print('\n{} stderr:\n'.format(name)) - print(stde) - print('\n') - returncode = 1 - print('\nFull log written to %s.' % logfilename) - return returncode + if len(collected_logs) > 0: + if len(collected_logs) > 10: + print('\nThe output from 10 first failed tests:\n') + else: + print('\nThe output from the failed tests:\n') + for log in collected_logs[:10]: + lines = log.splitlines() + if len(lines) > 100: + print(line[0]) + print('--- Listing only the last 100 lines from a long log. ---') + lines = lines[-99:] + for line in lines: + print(line) + print('Full log written to %s.' % logfilename) + return error_count if __name__ == '__main__': sys.exit(run(sys.argv[1:])) |