| 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 from collections import defaultdict | 5 from collections import defaultdict |
| 6 import copy | 6 import copy |
| 7 from datetime import datetime | 7 from datetime import datetime |
| 8 | 8 |
| 9 from google.appengine.api import users | 9 from google.appengine.api import users |
| 10 | 10 |
| 11 from common import constants | 11 from common import constants |
| 12 from common.base_handler import BaseHandler | 12 from common.base_handler import BaseHandler |
| 13 from common.base_handler import Permission | 13 from common.base_handler import Permission |
| 14 from common.waterfall import failure_type | 14 from common.waterfall import failure_type |
| 15 from handlers import handlers_util | 15 from handlers import handlers_util |
| 16 from handlers import result_status | 16 from handlers import result_status |
| 17 from handlers.result_status import NO_TRY_JOB_REASON_MAP | 17 from handlers.result_status import NO_TRY_JOB_REASON_MAP |
| 18 from model import analysis_approach_type |
| 18 from model import analysis_status | 19 from model import analysis_status |
| 20 from model.suspected_cl_confidence import SuspectedCLConfidence |
| 19 from model import result_status as analysis_result_status | 21 from model import result_status as analysis_result_status |
| 20 from model import suspected_cl_status | 22 from model import suspected_cl_status |
| 21 from model.base_build_model import BaseBuildModel | 23 from model.base_build_model import BaseBuildModel |
| 22 from model.result_status import RESULT_STATUS_TO_DESCRIPTION | 24 from model.result_status import RESULT_STATUS_TO_DESCRIPTION |
| 23 from model.suspected_cl_status import CL_STATUS_TO_DESCRIPTION | 25 from model.suspected_cl_status import CL_STATUS_TO_DESCRIPTION |
| 24 from model.wf_analysis import WfAnalysis | 26 from model.wf_analysis import WfAnalysis |
| 25 from model.wf_suspected_cl import WfSuspectedCL | 27 from model.wf_suspected_cl import WfSuspectedCL |
| 26 from model.wf_try_job import WfTryJob | 28 from model.wf_try_job import WfTryJob |
| 27 from waterfall import build_failure_analysis_pipelines | 29 from waterfall import build_failure_analysis_pipelines |
| 28 from waterfall import buildbot | 30 from waterfall import buildbot |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 compile_failure = None | 324 compile_failure = None |
| 323 for failure in analysis.result.get('failures', []): | 325 for failure in analysis.result.get('failures', []): |
| 324 if failure['step_name'] == constants.COMPILE_STEP_NAME: | 326 if failure['step_name'] == constants.COMPILE_STEP_NAME: |
| 325 compile_failure = failure | 327 compile_failure = failure |
| 326 if compile_failure: # pragma: no branch. | 328 if compile_failure: # pragma: no branch. |
| 327 data['first_failure'] = compile_failure['first_failure'] | 329 data['first_failure'] = compile_failure['first_failure'] |
| 328 data['last_pass'] = compile_failure['last_pass'] | 330 data['last_pass'] = compile_failure['last_pass'] |
| 329 data['suspected_cls_by_heuristic'] = compile_failure['suspected_cls'] | 331 data['suspected_cls_by_heuristic'] = compile_failure['suspected_cls'] |
| 330 | 332 |
| 331 | 333 |
| 334 def _PercentFormat(float_number): |
| 335 if not float_number or not isinstance(float_number, float): |
| 336 return None |
| 337 return '%d%%' % (round(float_number * 100)) |
| 338 |
| 339 |
| 340 def _GetConfidenceScore(confidence, cl_build): |
| 341 |
| 342 if not confidence: |
| 343 return None |
| 344 |
| 345 if cl_build['failure_type'] == failure_type.COMPILE: |
| 346 if cl_build['approaches'] == [ |
| 347 analysis_approach_type.HEURISTIC, analysis_approach_type.TRY_JOB]: |
| 348 return _PercentFormat(confidence.compile_heuristic_try_job.confidence) |
| 349 elif cl_build['approaches'] == [analysis_approach_type.TRY_JOB]: |
| 350 return _PercentFormat(confidence.compile_try_job.confidence) |
| 351 elif (cl_build['approaches'] == [analysis_approach_type.HEURISTIC] and |
| 352 cl_build['top_score']): |
| 353 for confidence_info in confidence.compile_heuristic: |
| 354 if confidence_info.score == cl_build['top_score']: |
| 355 return _PercentFormat(confidence_info.confidence) |
| 356 return None |
| 357 else: |
| 358 if cl_build['approaches'] == [ |
| 359 analysis_approach_type.HEURISTIC, analysis_approach_type.TRY_JOB]: |
| 360 return _PercentFormat(confidence.test_heuristic_try_job.confidence) |
| 361 elif cl_build['approaches'] == [analysis_approach_type.TRY_JOB]: |
| 362 return _PercentFormat(confidence.test_try_job.confidence) |
| 363 elif (cl_build['approaches'] == [analysis_approach_type.HEURISTIC] and |
| 364 cl_build['top_score']): |
| 365 for confidence_info in confidence.test_heuristic: |
| 366 if confidence_info.score == cl_build['top_score']: |
| 367 return _PercentFormat(confidence_info.confidence) |
| 368 return None |
| 369 |
| 370 |
| 332 def _GetAllSuspectedCLsAndCheckStatus( | 371 def _GetAllSuspectedCLsAndCheckStatus( |
| 333 master_name, builder_name, build_number, analysis): | 372 master_name, builder_name, build_number, analysis): |
| 334 build_key = BaseBuildModel.CreateBuildId( | 373 build_key = BaseBuildModel.CreateBuildId( |
| 335 master_name, builder_name, build_number) | 374 master_name, builder_name, build_number) |
| 336 suspected_cls = copy.deepcopy(analysis.suspected_cls) | 375 suspected_cls = copy.deepcopy(analysis.suspected_cls) |
| 337 if not suspected_cls: | 376 if not suspected_cls: |
| 338 return [] | 377 return [] |
| 339 | 378 |
| 379 cl_confidences = SuspectedCLConfidence.Get() |
| 380 |
| 340 for cl in suspected_cls: | 381 for cl in suspected_cls: |
| 341 cl['status'] = _ANALYSIS_CL_STATUS_MAP.get(analysis.result_status, None) | 382 cl['status'] = _ANALYSIS_CL_STATUS_MAP.get(analysis.result_status, None) |
| 383 cl['confidence'] = None |
| 384 |
| 342 suspected_cl = WfSuspectedCL.Get(cl['repo_name'], cl['revision']) | 385 suspected_cl = WfSuspectedCL.Get(cl['repo_name'], cl['revision']) |
| 343 if not suspected_cl: | 386 if not suspected_cl: |
| 344 continue | 387 continue |
| 345 | 388 |
| 346 build = suspected_cl.builds.get(build_key) | 389 build = suspected_cl.builds.get(build_key) |
| 347 if build: | 390 if build: |
| 348 cl['status'] = build['status'] | 391 cl['status'] = build['status'] |
| 392 cl['confidence'] = _GetConfidenceScore(cl_confidences, build) |
| 349 | 393 |
| 350 return suspected_cls | 394 return suspected_cls |
| 351 | 395 |
| 352 | 396 |
| 353 class BuildFailure(BaseHandler): | 397 class BuildFailure(BaseHandler): |
| 354 PERMISSION_LEVEL = Permission.ANYONE | 398 PERMISSION_LEVEL = Permission.ANYONE |
| 355 | 399 |
| 356 def _ShowDebugInfo(self): | 400 def _ShowDebugInfo(self): |
| 357 # Show debug info only if the app is run locally during development, if the | 401 # Show debug info only if the app is run locally during development, if the |
| 358 # currently logged-in user is an admin, or if it is explicitly requested | 402 # currently logged-in user is an admin, or if it is explicitly requested |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 else: | 504 else: |
| 461 self._PrepareDataForTestFailures( | 505 self._PrepareDataForTestFailures( |
| 462 analysis, build_info, data, self._ShowDebugInfo()) | 506 analysis, build_info, data, self._ShowDebugInfo()) |
| 463 return { | 507 return { |
| 464 'template': 'waterfall/test_failure.html', | 508 'template': 'waterfall/test_failure.html', |
| 465 'data': data | 509 'data': data |
| 466 } | 510 } |
| 467 | 511 |
| 468 def HandlePost(self): # pragma: no cover | 512 def HandlePost(self): # pragma: no cover |
| 469 return self.HandleGet() | 513 return self.HandleGet() |
| OLD | NEW |