| OLD | NEW |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 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 from collections import defaultdict | 5 from collections import defaultdict |
| 6 import copy | 6 import copy |
| 7 | 7 |
| 8 from model import wf_analysis_status | 8 from model import wf_analysis_status |
| 9 from model.wf_analysis import WfAnalysis | 9 from model.wf_analysis import WfAnalysis |
| 10 from model.wf_swarming_task import WfSwarmingTask | 10 from model.wf_swarming_task import WfSwarmingTask |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 wf_analysis_status.TRY_JOB_STATUS_TO_DESCRIPTION[try_job.status] | 139 wf_analysis_status.TRY_JOB_STATUS_TO_DESCRIPTION[try_job.status] |
| 140 if not culprit_info.get('status') else culprit_info['status']) | 140 if not culprit_info.get('status') else culprit_info['status']) |
| 141 | 141 |
| 142 if try_job_result and culprit_info['status'] != FLAKY: | 142 if try_job_result and culprit_info['status'] != FLAKY: |
| 143 if try_job_result.get('url'): | 143 if try_job_result.get('url'): |
| 144 culprit_info['try_job_url'] = try_job_result['url'] | 144 culprit_info['try_job_url'] = try_job_result['url'] |
| 145 culprit_info['try_job_build_number'] = ( | 145 culprit_info['try_job_build_number'] = ( |
| 146 _GetTryJobBuildNumber(try_job_result['url'])) | 146 _GetTryJobBuildNumber(try_job_result['url'])) |
| 147 if try_job_result.get('culprit'): | 147 if try_job_result.get('culprit'): |
| 148 try_job_culprits = try_job_result['culprit'] | 148 try_job_culprits = try_job_result['culprit'] |
| 149 step = culprit_info['step'] | 149 step = culprit_info.get('step_no_platform', culprit_info['step_name']) |
| 150 test = culprit_info['test'] | 150 test = culprit_info['test_name'] |
| 151 | 151 |
| 152 if test == 'N/A': # Only step level. | 152 if test == 'N/A': # Only step level. |
| 153 if try_job_culprits.get(step, {}).get('tests'): | 153 if try_job_culprits.get(step, {}).get('tests'): |
| 154 # try job results has specified tests. | 154 # try job results has specified tests. |
| 155 step_culprits = try_job_culprits[step]['tests'] | 155 step_culprits = try_job_culprits[step]['tests'] |
| 156 for test_name, try_job_culprit in step_culprits.iteritems(): | 156 for test_name, try_job_culprit in step_culprits.iteritems(): |
| 157 additional_test_key = '%s-%s' % (step, test_name) | 157 additional_test_key = '%s-%s' % (step, test_name) |
| 158 additional_tests_culprit_info[additional_test_key] = { | 158 additional_tests_culprit_info[additional_test_key] = { |
| 159 'step': step, | 159 'step_name': step, |
| 160 'test': test_name, | 160 'test_name': test_name, |
| 161 'try_job_key': try_job_key, | 161 'try_job_key': try_job_key, |
| 162 'status': culprit_info['status'], | 162 'status': culprit_info['status'], |
| 163 'try_job_url': culprit_info['try_job_url'], | 163 'try_job_url': culprit_info['try_job_url'], |
| 164 'try_job_build_number': culprit_info['try_job_build_number'], | 164 'try_job_build_number': culprit_info['try_job_build_number'], |
| 165 'revision': try_job_culprit.get('revision'), | 165 'revision': try_job_culprit.get('revision'), |
| 166 'commit_position': try_job_culprit.get('commit_position'), | 166 'commit_position': try_job_culprit.get('commit_position'), |
| 167 'review_url': try_job_culprit.get('review_url') | 167 'review_url': try_job_culprit.get('review_url') |
| 168 } | 168 } |
| 169 continue | 169 continue |
| 170 else: | 170 else: |
| 171 # For historical culprit found by try job for compile, | 171 # For historical culprit found by try job for compile, |
| 172 # step name is not recorded. | 172 # step name is not recorded. |
| 173 culprit = try_job_culprits.get(step) or try_job_culprits | 173 culprit = try_job_culprits.get(step) or try_job_culprits |
| 174 elif test in try_job_culprits.get(step, {}).get('tests'): | 174 elif test in try_job_culprits.get(step, {}).get('tests'): |
| 175 culprit = try_job_culprits[step]['tests'][test] | 175 culprit = try_job_culprits[step]['tests'][test] |
| 176 else: # pragma: no cover | 176 else: # pragma: no cover |
| 177 continue # No culprit for test found. | 177 continue # No culprit for test found. |
| 178 | 178 |
| 179 culprit_info['revision'] = culprit.get('revision') | 179 culprit_info['revision'] = culprit.get('revision') |
| 180 culprit_info['commit_position'] = culprit.get('commit_position') | 180 culprit_info['commit_position'] = culprit.get('commit_position') |
| 181 culprit_info['review_url'] = culprit.get('review_url') | 181 culprit_info['review_url'] = culprit.get('review_url') |
| 182 | 182 |
| 183 if additional_tests_culprit_info: | 183 if additional_tests_culprit_info: |
| 184 for key, test_culprit_info in additional_tests_culprit_info.iteritems(): | 184 for key, test_culprit_info in additional_tests_culprit_info.iteritems(): |
| 185 culprits_info.pop(test_culprit_info['step'], None) | 185 culprits_info.pop(test_culprit_info['step_name'], None) |
| 186 culprits_info[key] = test_culprit_info | 186 culprits_info[key] = test_culprit_info |
| 187 | 187 |
| 188 | 188 |
| 189 def _UpdateFlakiness(step_name, failure_key_set, culprits_info): | 189 def _UpdateTryJobCulpritUsingSwarmingTask( |
| 190 step_name, failure_key_set, culprits_info): |
| 190 for failure_key in failure_key_set: | 191 for failure_key in failure_key_set: |
| 191 build_keys = failure_key.split('/') | 192 build_keys = failure_key.split('/') |
| 192 task = WfSwarmingTask.Get(*build_keys, step_name=step_name) | 193 task = WfSwarmingTask.Get(*build_keys, step_name=step_name) |
| 193 if not task: | 194 if not task: |
| 194 continue | 195 continue |
| 195 classified_tests = task.classified_tests | 196 classified_tests = task.classified_tests |
| 197 step_no_platform = task.parameters.get( |
| 198 'ref_name', step_name.split()[0]) |
| 196 for culprit_info in culprits_info.values(): | 199 for culprit_info in culprits_info.values(): |
| 197 if (culprit_info['try_job_key'] == failure_key and | 200 if (culprit_info['try_job_key'] == failure_key and |
| 198 culprit_info['test'] in classified_tests.get('flaky_tests', [])): | 201 step_name == culprit_info['step_name']): |
| 199 culprit_info['status'] = FLAKY | 202 culprit_info['step_no_platform'] = step_no_platform |
| 203 if culprit_info['test_name'] in classified_tests.get('flaky_tests', []): |
| 204 culprit_info['status'] = FLAKY |
| 200 | 205 |
| 201 | 206 |
| 202 def GetAllTryJobResults(master_name, builder_name, build_number): | 207 def GetAllTryJobResults(master_name, builder_name, build_number): |
| 203 culprits_info = {} | 208 culprits_info = {} |
| 204 try_job_keys = set() | 209 try_job_keys = set() |
| 205 | 210 |
| 206 analysis = WfAnalysis.Get(master_name, builder_name, build_number) | 211 analysis = WfAnalysis.Get(master_name, builder_name, build_number) |
| 207 if not analysis: | 212 if not analysis: |
| 208 return culprits_info | 213 return culprits_info |
| 209 | 214 |
| 210 failure_result_map = analysis.failure_result_map | 215 failure_result_map = analysis.failure_result_map |
| 211 if failure_result_map: | 216 if failure_result_map: |
| 212 # failure_result_map uses step_names as keys and saves referred try_job_keys | 217 # failure_result_map uses step_names as keys and saves referred try_job_keys |
| 213 # If non-swarming, step_name and referred_try_job_key match directly as: | 218 # If non-swarming, step_name and referred_try_job_key match directly as: |
| 214 # step_name: try_job_key | 219 # step_name: try_job_key |
| 215 # If swarming, add one more layer of tests, so the format would be: | 220 # If swarming, add one more layer of tests, so the format would be: |
| 216 # step_name: { | 221 # step_name: { |
| 217 # test_name1: try_job_key1, | 222 # test_name1: try_job_key1, |
| 218 # test_name2: try_job_key2, | 223 # test_name2: try_job_key2, |
| 219 # ... | 224 # ... |
| 220 # } | 225 # } |
| 221 for step_name, step_failure_result_map in failure_result_map.iteritems(): | 226 for step_name, step_failure_result_map in failure_result_map.iteritems(): |
| 222 if isinstance(step_failure_result_map, dict): | 227 if isinstance(step_failure_result_map, dict): |
| 223 step_refering_keys = set() | 228 step_refering_keys = set() |
| 224 for failed_test, try_job_key in step_failure_result_map.iteritems(): | 229 for failed_test, try_job_key in step_failure_result_map.iteritems(): |
| 225 step_test_key = '%s-%s' % (step_name, failed_test) | 230 step_test_key = '%s-%s' % (step_name, failed_test) |
| 226 culprits_info[step_test_key] = { | 231 culprits_info[step_test_key] = { |
| 227 'step': step_name, | 232 'step_name': step_name, |
| 228 'test': failed_test, | 233 'test_name': failed_test, |
| 229 'try_job_key': try_job_key | 234 'try_job_key': try_job_key |
| 230 } | 235 } |
| 231 step_refering_keys.add(try_job_key) | 236 step_refering_keys.add(try_job_key) |
| 232 | 237 |
| 233 _UpdateFlakiness(step_name, step_refering_keys, culprits_info) | 238 _UpdateTryJobCulpritUsingSwarmingTask( |
| 239 step_name, step_refering_keys, culprits_info) |
| 234 try_job_keys.update(step_refering_keys) | 240 try_job_keys.update(step_refering_keys) |
| 235 else: | 241 else: |
| 236 culprits_info[step_name] = { | 242 culprits_info[step_name] = { |
| 237 'step': step_name, | 243 'step_name': step_name, |
| 238 'test': 'N/A', | 244 'test_name': 'N/A', |
| 239 'try_job_key': step_failure_result_map | 245 'try_job_key': step_failure_result_map |
| 240 } | 246 } |
| 241 try_job_keys.add(step_failure_result_map) | 247 try_job_keys.add(step_failure_result_map) |
| 242 | 248 |
| 243 for try_job_key in try_job_keys: | 249 for try_job_key in try_job_keys: |
| 244 _GetCulpritInfoForTryJobResult(try_job_key, culprits_info) | 250 _GetCulpritInfoForTryJobResult(try_job_key, culprits_info) |
| 245 | 251 |
| 246 return culprits_info | 252 return culprits_info |
| OLD | NEW |