| OLD | NEW |
| (Empty) |
| 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 | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """MinDistance scorer applies to Suspect objects. | |
| 6 | |
| 7 It represents a heuristic rule: | |
| 8 1. Highest score if the suspect changed the crashed lines. | |
| 9 2. 0 score if changed lines are too far away from crashed lines. | |
| 10 """ | |
| 11 | |
| 12 import logging | |
| 13 | |
| 14 from crash.scorers.scorer import Scorer | |
| 15 | |
| 16 _MAX_DISTANCE = 50 | |
| 17 | |
| 18 | |
| 19 class MinDistance(Scorer): | |
| 20 | |
| 21 def __init__(self, max_distance=_MAX_DISTANCE): | |
| 22 self.max_distance = max_distance | |
| 23 | |
| 24 def GetMetric(self, suspect): | |
| 25 min_distance = float('inf') | |
| 26 for analysis_info in suspect.file_to_analysis_info.itervalues(): | |
| 27 min_distance = min(min_distance, analysis_info.min_distance) | |
| 28 | |
| 29 return min_distance | |
| 30 | |
| 31 def Score(self, min_distance): | |
| 32 if min_distance > self.max_distance: | |
| 33 return 0 | |
| 34 | |
| 35 if min_distance == 0: | |
| 36 return 1 | |
| 37 | |
| 38 # TODO(katesonia): This number is randomly picked from a reasonable range, | |
| 39 # best value to use still needs be experimented out. | |
| 40 return 0.8 | |
| 41 | |
| 42 def Reason(self, min_distance, score): | |
| 43 if score == 0: | |
| 44 return None | |
| 45 | |
| 46 return self.name, score, 'Minimum distance is %d' % min_distance | |
| 47 | |
| 48 def ChangedFiles(self, suspect, score): | |
| 49 """Returns a list of changed file infos related to this scorer. | |
| 50 | |
| 51 For example: | |
| 52 [ | |
| 53 { | |
| 54 "blame_url": "https://chr.com/../render_frame_impl.cc#1586", | |
| 55 "file": "render_frame_impl.cc", | |
| 56 "info": "Minimum distance (LOC) 1, frame #5" | |
| 57 } | |
| 58 ] | |
| 59 """ | |
| 60 if score == 0: | |
| 61 return None | |
| 62 | |
| 63 index_to_changed_files = {} | |
| 64 | |
| 65 for file_path, analysis_info in suspect.file_to_analysis_info.iteritems(): | |
| 66 file_name = file_path.split('/')[-1] | |
| 67 frame = analysis_info.min_distance_frame | |
| 68 | |
| 69 # It is possible that a changelog doesn't show in the blame of a file, | |
| 70 # in this case, treat the changelog as if it didn't change the file. | |
| 71 if analysis_info.min_distance == float('inf'): | |
| 72 continue | |
| 73 | |
| 74 index_to_changed_files[frame.index] = { | |
| 75 'file': file_name, | |
| 76 'blame_url': frame.BlameUrl(suspect.changelog.revision), | |
| 77 'info': 'Minimum distance (LOC) %d, frame #%d' % ( | |
| 78 analysis_info.min_distance, frame.index) | |
| 79 } | |
| 80 | |
| 81 # Sort changed file by frame index. | |
| 82 _, changed_files = zip(*sorted(index_to_changed_files.items(), | |
| 83 key=lambda x: x[0])) | |
| 84 | |
| 85 return list(changed_files) | |
| OLD | NEW |