| 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 """This file contains printing-related functionality of the bisect.""" | 5 """This file contains printing-related functionality of the bisect.""" |
| 6 | 6 |
| 7 import datetime | 7 import datetime |
| 8 import re | 8 import re |
| 9 | 9 |
| 10 from bisect_results import BisectResults | 10 from bisect_results import BisectResults |
| 11 import bisect_utils | 11 import bisect_utils |
| 12 import source_control | 12 import source_control |
| 13 | 13 |
| 14 | 14 |
| 15 # The perf dashboard looks for a string like "Estimated Confidence: 95%" | 15 # The perf dashboard looks for a string like "Estimated Confidence: 95%" |
| 16 # to decide whether or not to cc the author(s). If you change this, please | 16 # to decide whether or not to cc the author(s). If you change this, please |
| 17 # update the perf dashboard as well. | 17 # update the perf dashboard as well. |
| 18 RESULTS_BANNER = """ | 18 RESULTS_BANNER = """ |
| 19 ===== BISECT JOB RESULTS ===== | 19 ===== BISECT JOB RESULTS ===== |
| 20 Status: %(status)s | 20 Status: %(status)s |
| 21 | 21 |
| 22 Test Command: %(command)s | 22 Test Command: %(command)s |
| 23 Test Metric: %(metrics)s | 23 Test Metric: %(metric)s |
| 24 Relative Change: %(change)s | 24 Relative Change: %(change)s |
| 25 Estimated Confidence: %(confidence).02f%% | 25 Estimated Confidence: %(confidence).02f%% |
| 26 Retested CL with revert: %(retest)s""" | 26 Retested CL with revert: %(retest)s""" |
| 27 | 27 |
| 28 # When the bisect was aborted without a bisect failure the following template | 28 # When the bisect was aborted without a bisect failure the following template |
| 29 # is used. | 29 # is used. |
| 30 ABORT_REASON_TEMPLATE = """ | 30 ABORT_REASON_TEMPLATE = """ |
| 31 ===== BISECTION ABORTED ===== | 31 ===== BISECTION ABORTED ===== |
| 32 The bisect was aborted because %(abort_reason)s | 32 The bisect was aborted because %(abort_reason)s |
| 33 Please contact the the team (see below) if you believe this is in error. | 33 Please contact the the team (see below) if you believe this is in error. |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 if (not bisect_results.retest_results_tot or | 289 if (not bisect_results.retest_results_tot or |
| 290 not bisect_results.retest_results_reverted): | 290 not bisect_results.retest_results_reverted): |
| 291 return | 291 return |
| 292 print | 292 print |
| 293 print '===== RETEST RESULTS =====' | 293 print '===== RETEST RESULTS =====' |
| 294 self._PrintTestedCommitsEntry( | 294 self._PrintTestedCommitsEntry( |
| 295 bisect_results.retest_results_tot, '', '', '') | 295 bisect_results.retest_results_tot, '', '', '') |
| 296 self._PrintTestedCommitsEntry( | 296 self._PrintTestedCommitsEntry( |
| 297 bisect_results.retest_results_reverted, '', '', '') | 297 bisect_results.retest_results_reverted, '', '', '') |
| 298 | 298 |
| 299 @staticmethod | |
| 300 def _ConfidenceLevelStatus(bisect_results): | |
| 301 if not bisect_results.confidence: | |
| 302 return None | |
| 303 confidence_status = 'Successful with %(level)s confidence%(warning)s.' | |
| 304 if bisect_results.confidence >= bisect_utils.HIGH_CONFIDENCE: | |
| 305 level = 'high' | |
| 306 else: | |
| 307 level = 'low' | |
| 308 warning = ' and warnings' | |
| 309 if not bisect_results.warnings: | |
| 310 warning = '' | |
| 311 return confidence_status % {'level': level, 'warning': warning} | |
| 312 | |
| 313 def _PrintBanner(self, bisect_results): | 299 def _PrintBanner(self, bisect_results): |
| 314 if self.opts.bisect_mode == bisect_utils.BISECT_MODE_RETURN_CODE: | 300 if self.opts.bisect_mode == bisect_utils.BISECT_MODE_RETURN_CODE: |
| 315 metrics = 'N/A' | 301 metric = 'N/A' |
| 316 change = 'Yes' | 302 change = 'Yes' |
| 317 else: | 303 else: |
| 318 metrics = '/'.join(self.opts.metric) | 304 metric = '/'.join(self.opts.metric) |
| 319 change = '%.02f%% (+/-%.02f%%)' % ( | 305 change = '%.02f%% (+/-%.02f%%)' % ( |
| 320 bisect_results.regression_size, bisect_results.regression_std_err) | 306 bisect_results.regression_size, bisect_results.regression_std_err) |
| 321 | 307 if not bisect_results.culprit_revisions: |
| 322 if bisect_results.culprit_revisions and bisect_results.confidence: | 308 change = 'No significant change reproduced.' |
| 323 status = self._ConfidenceLevelStatus(bisect_results) | |
| 324 else: | |
| 325 status = 'Failure, could not reproduce.' | |
| 326 change = 'Bisect could not reproduce a change.' | |
| 327 | |
| 328 retest_text = 'Yes' if bisect_results.retest_results_tot else 'No' | |
| 329 | 309 |
| 330 print RESULTS_BANNER % { | 310 print RESULTS_BANNER % { |
| 331 'status': status, | 311 'status': self._StatusMessage(bisect_results), |
| 332 'command': self.opts.command, | 312 'command': self.opts.command, |
| 333 'metrics': metrics, | 313 'metric': metric, |
| 334 'change': change, | 314 'change': change, |
| 335 'confidence': bisect_results.confidence, | 315 'confidence': bisect_results.confidence, |
| 336 'retest': retest_text, | 316 'retest': 'Yes' if bisect_results.retest_results_tot else 'No', |
| 337 } | 317 } |
| 338 | 318 |
| 339 @staticmethod | 319 @staticmethod |
| 320 def _StatusMessage(bisect_results): |
| 321 if bisect_results.confidence >= bisect_utils.HIGH_CONFIDENCE: |
| 322 return 'Positive: Reproduced a change.' |
| 323 elif bisect_results.culprit_revisions: |
| 324 return 'Negative: Found possible suspect(s), but with low confidence.' |
| 325 return 'Negative: Did not reproduce a change.' |
| 326 |
| 327 @staticmethod |
| 340 def _PrintWarnings(warnings): | 328 def _PrintWarnings(warnings): |
| 341 """Prints a list of warning strings if there are any.""" | 329 """Prints a list of warning strings if there are any.""" |
| 342 if not warnings: | 330 if not warnings: |
| 343 return | 331 return |
| 344 print | 332 print |
| 345 print 'WARNINGS:' | 333 print 'WARNINGS:' |
| 346 for w in set(warnings): | 334 for w in set(warnings): |
| 347 print ' ! %s' % w | 335 print ' ! %s' % w |
| OLD | NEW |