| 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 | 6 |
| 7 from crash.crash_match import CrashMatch |
| 8 from crash.crash_match import FrameInfo |
| 9 |
| 7 | 10 |
| 8 def IsSameFilePath(path_1, path_2): | 11 def IsSameFilePath(path_1, path_2): |
| 9 """Determines if two paths represent same path. | 12 """Determines if two paths represent same path. |
| 10 | 13 |
| 11 First we split each path into a list of directories (via split('/')), | 14 First we split each path into a list of directories (via split('/')), |
| 12 then we treat those lists as multisets (i.e., ignore the order of | 15 then we treat those lists as multisets (i.e., ignore the order of |
| 13 directories, but keep track of their multiplicities) and take the | 16 directories, but keep track of their multiplicities) and take the |
| 14 multiset intersection. Finally, we return whether the number of elements | 17 multiset intersection. Finally, we return whether the number of elements |
| 15 in the intersection is at least 3 (or, when one of the paths has | 18 in the intersection is at least 3 (or, when one of the paths has |
| 16 fewer than 3 parts, we return whether all those parts are also in the | 19 fewer than 3 parts, we return whether all those parts are also in the |
| (...skipping 29 matching lines...) Expand all Loading... |
| 46 return path_parts_count | 49 return path_parts_count |
| 47 | 50 |
| 48 parts_count_1 = _GetPathPartsCount(path_parts_1) | 51 parts_count_1 = _GetPathPartsCount(path_parts_1) |
| 49 parts_count_2 = _GetPathPartsCount(path_parts_2) | 52 parts_count_2 = _GetPathPartsCount(path_parts_2) |
| 50 | 53 |
| 51 # Get number of same path parts between path_1 and path_2. For example: | 54 # Get number of same path parts between path_1 and path_2. For example: |
| 52 # a/b/b/b/f.cc and a/b/b/c/d/f.cc have 4 path parts the same in total. | 55 # a/b/b/b/f.cc and a/b/b/c/d/f.cc have 4 path parts the same in total. |
| 53 total_same_parts = sum([min(parts_count_1[part], parts_count_2[part]) for | 56 total_same_parts = sum([min(parts_count_1[part], parts_count_2[part]) for |
| 54 part in parts_count_1 if part in path_parts_2]) | 57 part in parts_count_1 if part in path_parts_2]) |
| 55 | 58 |
| 56 return total_same_parts >= (min(3, min(len(path_parts_1), len(path_parts_2)))) | 59 return total_same_parts >= min(3, min(len(path_parts_1), len(path_parts_2))) |
| 60 |
| 61 |
| 62 def IndexFramesWithCrashedGroup(stacktrace, crashed_group_factory, |
| 63 dependencies): |
| 64 """Index frames in stacktrace by dep_path and crashed_groups. |
| 65 |
| 66 Args: |
| 67 stacktrace (Stacktrace): The stacktrace to parse. |
| 68 crashed_group_factory (callable): A callable to factory crashed_group. |
| 69 N.B. So as to be used a key in a dict, the ``crashed_group`` should be |
| 70 able to be hashed. |
| 71 dependencies (dict of Dependency): Dict mapping dep path to ``Dependency``s. |
| 72 The ``dependencies`` is used to filter those frames whose dep path are |
| 73 not in ``dependencies``. |
| 74 |
| 75 Returns: |
| 76 A dict mapping dep_path to crashed_group to list of ``FrameInfo``s. |
| 77 For example: |
| 78 { |
| 79 'src/': { |
| 80 'a.cc': [ |
| 81 FrameInfo(StackFrame(0, 'src/', '', 'func', 'a.cc', [1]), 0), |
| 82 FrameInfo(StackFrame(2, 'src/', '', 'func', 'a.cc', [33]), 0), |
| 83 ] |
| 84 } |
| 85 } |
| 86 """ |
| 87 frame_infos = defaultdict(lambda: defaultdict(list)) |
| 88 |
| 89 for stack in stacktrace.stacks: |
| 90 for frame in stack.frames: |
| 91 if frame.dep_path not in dependencies: |
| 92 continue |
| 93 |
| 94 frame_infos[frame.dep_path][crashed_group_factory(frame)].append( |
| 95 FrameInfo(frame, stack.priority)) |
| 96 |
| 97 return frame_infos |
| 98 |
| 99 |
| 100 def MatchSuspectWithFrameInfos(suspect, grouped_frame_infos): |
| 101 """Matches touched files of suspect with frames in stacktrace. |
| 102 |
| 103 Args: |
| 104 suspect (Suspect): The suspect to match with frames. |
| 105 grouped_frame_infos (dict of FrameInfo): Dict mapping a crashed group ( |
| 106 For example, CrashedFile('f.cc'), CrashedDirectory('dir/'). |
| 107 |
| 108 Returns: |
| 109 A dict mapping crashed group to a ``CrashMatch``. |
| 110 """ |
| 111 |
| 112 # Dict mapping files in stacktrace touched by suspect to there |
| 113 # corresponding stacktrace frames information. |
| 114 matched_touched_files = defaultdict(list) |
| 115 for crashed in grouped_frame_infos: |
| 116 for touched_file in suspect.changelog.touched_files: |
| 117 if crashed.MatchTouchedFile(touched_file): |
| 118 matched_touched_files[crashed].append(touched_file) |
| 119 |
| 120 return {crashed: CrashMatch(crashed_group=crashed, |
| 121 touched_files=matched_touched_files[crashed], |
| 122 frame_infos=grouped_frame_infos[crashed]) |
| 123 for crashed in matched_touched_files} |
| OLD | NEW |