Chromium Code Reviews| Index: scripts/common/gtest_utils.py |
| =================================================================== |
| --- scripts/common/gtest_utils.py (revision 240792) |
| +++ scripts/common/gtest_utils.py (working copy) |
| @@ -3,7 +3,9 @@ |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| +import json |
| import re |
| +import tempfile |
| class GTestLogParser(object): |
| @@ -388,3 +390,92 @@ |
| self._parsing_failures = False |
| elif line.startswith('Failing tests:'): |
| self._parsing_failures = True |
| + |
| + |
| +class GTestJSONParser(object): |
| + def __init__(self): |
| + self.json_file = None |
| + |
| + self.passed_tests = set() |
| + self.failed_tests = set() |
| + self.flaky_tests = set() |
| + self.test_logs = {} |
| + |
| + self.parsing_errors = [] |
| + |
| + self.master_name = None |
| + |
| + def ProcessLine(self, line): |
| + # Deliberately do nothing - we parse out-of-band JSON summary |
| + # instead of in-band stdout. |
| + pass |
| + |
| + def PassedTests(self): |
| + return sorted(self.passed_tests) |
| + |
| + def FailedTests(self, include_fails=False, include_flaky=False): |
| + return sorted(self.failed_tests) |
| + |
| + def FailureDescription(self, test): |
| + return self.test_logs.get(test, []) |
| + |
| + @staticmethod |
| + def SuppressionHashes(): |
| + return [] |
| + |
| + def ParsingErrors(self): |
| + return self.parsing_errors |
| + |
| + def ClearParsingErrors(self): |
| + self.parsing_errors = ['Cleared.'] |
| + |
| + @staticmethod |
| + def DisabledTests(): |
| + # TODO(phajdan.jr): Count disabled tests when JSON summary includes them. |
| + return 0 |
| + |
| + def FlakyTests(self): |
| + return len(self.flaky_tests) |
| + |
| + @staticmethod |
| + def RunningTests(): |
| + return [] |
| + |
| + def OpenJSONFile(self, cmdline_path): |
| + if cmdline_path: |
| + self.json_file = open(cmdline_path, 'rw') |
| + return cmdline_path |
| + else: |
| + self.json_file = tempfile.NamedTemporaryFile(mode='r') |
| + return self.json_file.name |
| + |
| + def ProcessAndCloseJSONFile(self): |
| + if not self.json_file: |
| + return |
| + |
| + try: |
| + json_output = self.json_file.read() |
| + json_data = json.loads(json_output) |
|
ghost stip (do not use)
2013/12/16 21:18:50
I'm assuming you're not using json.load() because
Paweł Hajdan Jr.
2013/12/17 16:51:56
Yes.
|
| + except ValueError: |
| + self.parsing_errors = json_output.split('\n') |
| + else: |
|
ghost stip (do not use)
2013/12/16 21:18:50
didn't know you could do that
|
| + for iteration_data in json_data['per_iteration_data']: |
| + for test_name, test_runs in iteration_data.iteritems(): |
| + if test_runs[-1]['status'] == 'SUCCESS': |
| + self.passed_tests.add(test_name) |
| + else: |
| + self.failed_tests.add(test_name) |
| + |
| + if len(test_runs) > 1: |
| + self.flaky_tests.add(test_name) |
| + |
| + if test_name not in self.test_logs: |
| + self.test_logs[test_name] = [] |
|
ghost stip (do not use)
2013/12/16 21:18:50
remove line 472, make this self.test_logs.setdefau
Paweł Hajdan Jr.
2013/12/17 16:51:56
Done.
|
| + for run_index, run_data in enumerate(test_runs, start=1): |
| + run_lines = ['%s (run #%d):' % (test_name, run_index)] |
| + decoded_lines = run_data['output_snippet'].decode('string_escape') |
| + run_lines.extend(decoded_lines.split('\n')) |
| + self.test_logs[test_name].extend(run_lines) |
| + finally: |
| + self.json_file.close() |
| + self.json_file = None |