| Index: build/android/pylib/test_result.py
|
| diff --git a/build/android/pylib/test_result.py b/build/android/pylib/test_result.py
|
| index 7d9b21600c44cb1a34f49b7ceb7fa561d07674cc..5e06804e0a05456fafb77c83fc5fbce8f0a68c51 100644
|
| --- a/build/android/pylib/test_result.py
|
| +++ b/build/android/pylib/test_result.py
|
| @@ -3,7 +3,13 @@
|
| # found in the LICENSE file.
|
|
|
|
|
| +import json
|
| import logging
|
| +import os
|
| +import time
|
| +import traceback
|
| +
|
| +import constants
|
|
|
|
|
| # Language values match constants in Sponge protocol buffer (sponge.proto).
|
| @@ -35,7 +41,7 @@ class SingleTestResult(BaseTestResult):
|
| def __init__(self, full_name, start_date, dur, lang, log='', error=()):
|
| BaseTestResult.__init__(self, full_name, log)
|
| name_pieces = full_name.rsplit('#')
|
| - if len(name_pieces) > 0:
|
| + if len(name_pieces) > 1:
|
| self.test_name = name_pieces[1]
|
| self.class_name = name_pieces[0]
|
| else:
|
| @@ -55,8 +61,6 @@ class TestResults(object):
|
| self.failed = []
|
| self.crashed = []
|
| self.unknown = []
|
| - self.disabled = []
|
| - self.unexpected_pass = []
|
| self.timed_out = False
|
| self.overall_fail = False
|
|
|
| @@ -80,14 +84,42 @@ class TestResults(object):
|
| ret.failed += t.failed
|
| ret.crashed += t.crashed
|
| ret.unknown += t.unknown
|
| - ret.disabled += t.disabled
|
| - ret.unexpected_pass += t.unexpected_pass
|
| if t.timed_out:
|
| ret.timed_out = True
|
| if t.overall_fail:
|
| ret.overall_fail = True
|
| return ret
|
|
|
| + @staticmethod
|
| + def FromPythonException(test_name, start_date_ms, exc_info):
|
| + """Constructs a TestResults with exception information for the given test.
|
| +
|
| + Args:
|
| + test_name: name of the test which raised an exception.
|
| + start_date_ms: the starting time for the test.
|
| + exc_info: exception info, ostensibly from sys.exc_info().
|
| +
|
| + Returns:
|
| + A TestResults object with a SingleTestResult in the failed list.
|
| + """
|
| + exc_type, exc_value, exc_traceback = exc_info
|
| + trace_info = ''.join(traceback.format_exception(exc_type, exc_value,
|
| + exc_traceback))
|
| + log_msg = 'Exception:\n' + trace_info
|
| + duration_ms = (int(time.time()) * 1000) - start_date_ms
|
| +
|
| + exc_result = SingleTestResult(
|
| + full_name='PythonWrapper#' + test_name,
|
| + start_date=start_date_ms,
|
| + dur=duration_ms,
|
| + lang=PYTHON,
|
| + log=log_msg,
|
| + error=(str(exc_type), log_msg))
|
| +
|
| + results = TestResults()
|
| + results.failed.append(exc_result)
|
| + return results
|
| +
|
| def _Log(self, sorted_list):
|
| for t in sorted_list:
|
| logging.critical(t.name)
|
| @@ -98,8 +130,9 @@ class TestResults(object):
|
| """Returns the all broken tests including failed, crashed, unknown."""
|
| return self.failed + self.crashed + self.unknown
|
|
|
| - def LogFull(self):
|
| - """Output all broken tests or 'passed' if none broken"""
|
| + def LogFull(self, test_group, test_suite):
|
| + """Output broken test logs, summarize in a log file and the test output."""
|
| + # Output all broken tests or 'passed' if none broken.
|
| logging.critical('*' * 80)
|
| logging.critical('Final result')
|
| if self.failed:
|
| @@ -115,6 +148,38 @@ class TestResults(object):
|
| logging.critical('Passed')
|
| logging.critical('*' * 80)
|
|
|
| + # Summarize in a log file, if tests are running on bots.
|
| + if test_group and test_suite and os.environ.get('BUILDBOT_BUILDERNAME'):
|
| + log_file_path = os.path.join(constants.CHROME_DIR, 'out',
|
| + 'Release', 'test_logs')
|
| + if not os.path.exists(log_file_path):
|
| + os.mkdir(log_file_path)
|
| + full_file_name = os.path.join(log_file_path, test_group)
|
| + if not os.path.exists(full_file_name):
|
| + with open(full_file_name, 'w') as log_file:
|
| + print >> log_file, '\n%s results for %s build %s:' % (
|
| + test_group, os.environ.get('BUILDBOT_BUILDERNAME'),
|
| + os.environ.get('BUILDBOT_BUILDNUMBER'))
|
| + log_contents = [' %s result : %d tests ran' % (test_suite,
|
| + len(self.ok) +
|
| + len(self.failed) +
|
| + len(self.crashed) +
|
| + len(self.unknown))]
|
| + content_pairs = [('passed', len(self.ok)), ('failed', len(self.failed)),
|
| + ('crashed', len(self.crashed))]
|
| + for (result, count) in content_pairs:
|
| + if count:
|
| + log_contents.append(', %d tests %s' % (count, result))
|
| + with open(full_file_name, 'a') as log_file:
|
| + print >> log_file, ''.join(log_contents)
|
| + content = {'test_group': test_group,
|
| + 'ok': [t.name for t in self.ok],
|
| + 'failed': [t.name for t in self.failed],
|
| + 'crashed': [t.name for t in self.failed],
|
| + 'unknown': [t.name for t in self.unknown],}
|
| + with open(os.path.join(log_file_path, 'results.json'), 'a') as json_file:
|
| + print >> json_file, json.dumps(content)
|
| +
|
| # Summarize in the test output.
|
| summary_string = 'Summary:\n'
|
| summary_string += 'RAN=%d\n' % (len(self.ok) + len(self.failed) +
|
|
|