| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 import logging | 6 import logging |
| 7 import os | 7 import os |
| 8 import re | |
| 9 import sys | 8 import sys |
| 10 | 9 |
| 11 from xml.dom import minidom | 10 from xml.dom import minidom |
| 12 from slave.gtest.json_results_generator import JSONResultsGenerator | 11 from slave.gtest.json_results_generator import JSONResultsGenerator |
| 13 from slave.gtest.test_result import TestResult | 12 from slave.gtest.test_result import TestResult |
| 14 from slave.gtest.test_result import canonical_name | 13 from slave.gtest.test_result import canonical_name |
| 15 | 14 |
| 16 | 15 |
| 17 GENERATE_JSON_RESULTS_OPTIONS = [ | 16 GENERATE_JSON_RESULTS_OPTIONS = [ |
| 18 'builder_name', 'build_name', 'build_number', 'results_directory', | 17 'builder_name', 'build_name', 'build_number', 'results_directory', |
| 19 'builder_base_url', 'webkit_dir', 'chrome_dir', 'test_results_server', | 18 'builder_base_url', 'webkit_dir', 'chrome_dir', 'test_results_server', |
| 20 'test_type', 'master_name'] | 19 'test_type', 'master_name'] |
| 21 | 20 |
| 22 INCREMENTAL_RESULTS_FILENAME = "incremental_results.json" | 21 INCREMENTAL_RESULTS_FILENAME = "incremental_results.json" |
| 23 TIMES_MS_FILENAME = "times_ms.json" | 22 TIMES_MS_FILENAME = "times_ms.json" |
| 24 | 23 |
| 25 | 24 |
| 26 class GTestUnexpectedDeathTracker(object): | 25 def GetResultsMap(observer): |
| 27 """A lightweight version of log parser that keeps track of running tests | 26 """Returns a map of TestResults. Returns an empty map if no current test |
| 28 for unexpected timeout or crash.""" | 27 has been recorded.""" |
| 29 | 28 |
| 30 def __init__(self): | 29 if not observer.GetCurrentTest(): |
| 31 self._current_test = None | 30 return dict() |
| 32 self._completed = False | |
| 33 self._test_start = re.compile('\[\s+RUN\s+\] (\w+\.\w+)') | |
| 34 self._test_ok = re.compile('\[\s+OK\s+\] (\w+\.\w+)') | |
| 35 self._test_fail = re.compile('\[\s+FAILED\s+\] (\w+\.\w+)') | |
| 36 self._test_passed = re.compile('\[\s+PASSED\s+\] \d+ tests?.') | |
| 37 | 31 |
| 38 self._failed_tests = set() | 32 test_results_map = dict() |
| 33 for test in observer.FailedTests(include_fails=True, include_flaky=True): |
| 34 test_results_map[canonical_name(test)] = TestResult(test, failed=True) |
| 39 | 35 |
| 40 def OnReceiveLine(self, line): | 36 return test_results_map |
| 41 results = self._test_start.search(line) | |
| 42 if results: | |
| 43 self._current_test = results.group(1) | |
| 44 return | |
| 45 | |
| 46 results = self._test_ok.search(line) | |
| 47 if results: | |
| 48 self._current_test = '' | |
| 49 return | |
| 50 | |
| 51 results = self._test_fail.search(line) | |
| 52 if results: | |
| 53 self._failed_tests.add(results.group(1)) | |
| 54 self._current_test = '' | |
| 55 return | |
| 56 | |
| 57 results = self._test_passed.search(line) | |
| 58 if results: | |
| 59 self._completed = True | |
| 60 self._current_test = '' | |
| 61 return | |
| 62 | |
| 63 def GetResultsMap(self): | |
| 64 """Returns a map of TestResults. Returns an empty map if no current test | |
| 65 has been recorded.""" | |
| 66 | |
| 67 if not self._current_test: | |
| 68 return dict() | |
| 69 | |
| 70 self._failed_tests.add(self._current_test) | |
| 71 | |
| 72 test_results_map = dict() | |
| 73 for test in self._failed_tests: | |
| 74 test_results_map[canonical_name(test)] = TestResult(test, failed=True) | |
| 75 | |
| 76 return test_results_map | |
| 77 | |
| 78 def CompletedWithoutFailure(self): | |
| 79 """Returns True if all tests completed and no tests failed unexpectedly.""" | |
| 80 | |
| 81 if not self._completed: | |
| 82 return False | |
| 83 | |
| 84 for test in self._failed_tests: | |
| 85 test_modifier = TestResult(test, failed=True).modifier | |
| 86 if test_modifier not in (TestResult.FAILS, TestResult.FLAKY): | |
| 87 return False | |
| 88 | |
| 89 return True | |
| 90 | |
| 91 | 37 |
| 92 def GetResultsMapFromXML(results_xml): | 38 def GetResultsMapFromXML(results_xml): |
| 93 """Parse the given results XML file and returns a map of TestResults.""" | 39 """Parse the given results XML file and returns a map of TestResults.""" |
| 94 | 40 |
| 95 results_xml_file = None | 41 results_xml_file = None |
| 96 try: | 42 try: |
| 97 results_xml_file = open(results_xml) | 43 results_xml_file = open(results_xml) |
| 98 except IOError: | 44 except IOError: |
| 99 logging.error("Cannot open file %s", results_xml) | 45 logging.error("Cannot open file %s", results_xml) |
| 100 return dict() | 46 return dict() |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 | 189 |
| 244 if not options.chrome_dir: | 190 if not options.chrome_dir: |
| 245 options.chrome_dir = os.path.join(options.webkit_dir, "WebKit", "chromium") | 191 options.chrome_dir = os.path.join(options.webkit_dir, "WebKit", "chromium") |
| 246 | 192 |
| 247 results_map = GetResultsMapFromXML(options.input_results_xml) | 193 results_map = GetResultsMapFromXML(options.input_results_xml) |
| 248 GenerateAndUploadJSONResults(results_map, options) | 194 GenerateAndUploadJSONResults(results_map, options) |
| 249 | 195 |
| 250 | 196 |
| 251 if '__main__' == __name__: | 197 if '__main__' == __name__: |
| 252 main() | 198 main() |
| OLD | NEW |