| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import base64 | 5 import base64 |
| 6 import json | 6 import json |
| 7 | 7 |
| 8 from common import constants | 8 from common import constants |
| 9 from common.http_client_appengine import HttpClientAppengine as HttpClient | 9 from common.http_client_appengine import HttpClientAppengine as HttpClient |
| 10 from common.pipeline_wrapper import BasePipeline | 10 from common.pipeline_wrapper import BasePipeline |
| 11 from common.pipeline_wrapper import pipeline | 11 from common.pipeline_wrapper import pipeline |
| 12 from common.waterfall import failure_type | 12 from common.waterfall import failure_type |
| 13 from model.wf_analysis import WfAnalysis | 13 from model.wf_analysis import WfAnalysis |
| 14 from model.wf_step import WfStep | 14 from model.wf_step import WfStep |
| 15 from waterfall import build_util | 15 from waterfall import build_util |
| 16 from waterfall import buildbot | 16 from waterfall import buildbot |
| 17 from waterfall import swarming_util | 17 from waterfall import swarming_util |
| 18 | 18 |
| 19 | 19 |
| 20 _MAX_BUILDS_TO_CHECK = 20 | 20 _MAX_BUILDS_TO_CHECK = 20 |
| 21 _NON_FAILURE_STATUS = ['SUCCESS', 'SKIPPED', 'UNKNOWN'] | 21 _NON_FAILURE_STATUS = ['SUCCESS', 'SKIPPED', 'UNKNOWN'] |
| 22 _PRE_TEST_PREFIX = 'PRE_' |
| 23 |
| 24 |
| 25 def _RemoveAllPrefixes(test): |
| 26 """Remove prefixes from test names. |
| 27 |
| 28 Args: |
| 29 test (str): A test's name, eg: 'suite1.PRE_test1'. |
| 30 |
| 31 Returns: |
| 32 base_test (str): A base test name, eg: 'suite1.test1'. |
| 33 """ |
| 34 test_name_start = max(test.find('.'), 0) |
| 35 if test_name_start == 0: |
| 36 return test |
| 37 |
| 38 test_suite = test[: test_name_start] |
| 39 test_name = test[test_name_start + 1 :] |
| 40 pre_position = test_name.find(_PRE_TEST_PREFIX) |
| 41 while pre_position == 0: |
| 42 test_name = test_name[len(_PRE_TEST_PREFIX):] |
| 43 pre_position = test_name.find(_PRE_TEST_PREFIX) |
| 44 base_test = '%s.%s' % (test_suite, test_name) |
| 45 return base_test |
| 22 | 46 |
| 23 | 47 |
| 24 class DetectFirstFailurePipeline(BasePipeline): | 48 class DetectFirstFailurePipeline(BasePipeline): |
| 25 """A pipeline to detect first failure of each step. | 49 """A pipeline to detect first failure of each step. |
| 26 | 50 |
| 27 TODO(stgao): do test-level detection for gtest. | 51 TODO(stgao): do test-level detection for gtest. |
| 28 """ | 52 """ |
| 29 | 53 |
| 30 def _ExtractBuildInfo(self, master_name, builder_name, build_number): | 54 def _ExtractBuildInfo(self, master_name, builder_name, build_number): |
| 31 """Returns a BuildInfo instance for the specified build.""" | 55 """Returns a BuildInfo instance for the specified build.""" |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 # If a test is skipped, that means it was not run at all. | 212 # If a test is skipped, that means it was not run at all. |
| 189 # Treats it as success since the status cannot be determined. | 213 # Treats it as success since the status cannot be determined. |
| 190 is_reliable_failure = False | 214 is_reliable_failure = False |
| 191 | 215 |
| 192 if is_reliable_failure: | 216 if is_reliable_failure: |
| 193 if failed_step: | 217 if failed_step: |
| 194 # Adds the test to failed_step. | 218 # Adds the test to failed_step. |
| 195 failed_step['tests'][test_name] = { | 219 failed_step['tests'][test_name] = { |
| 196 'current_failure': failed_step['current_failure'], | 220 'current_failure': failed_step['current_failure'], |
| 197 'first_failure': failed_step['current_failure'], | 221 'first_failure': failed_step['current_failure'], |
| 222 'base_test_name': _RemoveAllPrefixes(test_name) |
| 198 } | 223 } |
| 199 if failed_step.get('last_pass'): | 224 if failed_step.get('last_pass'): |
| 200 failed_step['tests'][test_name]['last_pass'] = ( | 225 failed_step['tests'][test_name]['last_pass'] = ( |
| 201 failed_step['last_pass']) | 226 failed_step['last_pass']) |
| 202 # Stores the output to the step's log_data later. | 227 # Stores the output to the step's log_data later. |
| 203 failed_test_log[test_name] = '' | 228 failed_test_log[test_name] = '' |
| 204 for test in iteration[test_name]: | 229 for test in iteration[test_name]: |
| 205 failed_test_log[test_name] = self._ConcatenateTestLog( | 230 failed_test_log[test_name] = self._ConcatenateTestLog( |
| 206 failed_test_log[test_name], test.get( | 231 failed_test_log[test_name], test.get( |
| 207 'output_snippet_base64', '')) | 232 'output_snippet_base64', '')) |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 | 491 |
| 467 failure_info['builds'] = builds | 492 failure_info['builds'] = builds |
| 468 failure_info['failed_steps'] = failed_steps | 493 failure_info['failed_steps'] = failed_steps |
| 469 | 494 |
| 470 analysis = WfAnalysis.Get(master_name, builder_name, build_number) | 495 analysis = WfAnalysis.Get(master_name, builder_name, build_number) |
| 471 analysis.not_passed_steps = build_info.not_passed_steps | 496 analysis.not_passed_steps = build_info.not_passed_steps |
| 472 analysis.build_failure_type = build_failure_type | 497 analysis.build_failure_type = build_failure_type |
| 473 analysis.put() | 498 analysis.put() |
| 474 | 499 |
| 475 return failure_info | 500 return failure_info |
| OLD | NEW |