| 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 common import git_repository | 7 from common.blame import Blame |
| 8 from common.blame import Region | 8 from common.blame import Region |
| 9 from common.blame import Blame | |
| 10 from common.change_log import ChangeLog | 9 from common.change_log import ChangeLog |
| 11 from common.dependency import Dependency | 10 from common.dependency import Dependency |
| 12 from common.dependency import DependencyRoll | 11 from common.dependency import DependencyRoll |
| 12 from common.git_repository import GitRepository |
| 13 from common.http_client_appengine import HttpClientAppengine | 13 from common.http_client_appengine import HttpClientAppengine |
| 14 from crash import findit_for_crash | 14 from common import chrome_dependency_fetcher |
| 15 from common import git_repository |
| 16 from crash.crash_report import CrashReport |
| 17 from crash import changelist_classifier |
| 18 from crash.results import MatchResult |
| 19 from crash.stacktrace import CallStack |
| 15 from crash.stacktrace import StackFrame | 20 from crash.stacktrace import StackFrame |
| 16 from crash.stacktrace import CallStack | |
| 17 from crash.stacktrace import Stacktrace | 21 from crash.stacktrace import Stacktrace |
| 18 from crash.results import MatchResult | |
| 19 from crash.test.crash_test_suite import CrashTestSuite | 22 from crash.test.crash_test_suite import CrashTestSuite |
| 20 | 23 |
| 21 | |
| 22 DUMMY_CHANGELOG1 = ChangeLog.FromDict({ | 24 DUMMY_CHANGELOG1 = ChangeLog.FromDict({ |
| 23 'author_name': 'r@chromium.org', | 25 'author_name': 'r@chromium.org', |
| 24 'message': 'dummy', | 26 'message': 'dummy', |
| 25 'committer_email': 'r@chromium.org', | 27 'committer_email': 'r@chromium.org', |
| 26 'commit_position': 175900, | 28 'commit_position': 175900, |
| 27 'author_email': 'r@chromium.org', | 29 'author_email': 'r@chromium.org', |
| 28 'touched_files': [ | 30 'touched_files': [ |
| 29 { | 31 { |
| 30 'change_type': 'add', | 32 'change_type': 'add', |
| 31 'new_path': 'a.cc', | 33 'new_path': 'a.cc', |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 'author_time': 'Thu Apr 1 21:24:43 2016', | 88 'author_time': 'Thu Apr 1 21:24:43 2016', |
| 87 'committer_time': 'Thu Apr 1 21:28:39 2016', | 89 'committer_time': 'Thu Apr 1 21:28:39 2016', |
| 88 'commit_url': | 90 'commit_url': |
| 89 'https://repo.test/+/3', | 91 'https://repo.test/+/3', |
| 90 'code_review_url': 'https://codereview.chromium.org/3281', | 92 'code_review_url': 'https://codereview.chromium.org/3281', |
| 91 'committer_name': 'example@chromium.org', | 93 'committer_name': 'example@chromium.org', |
| 92 'revision': '3', | 94 'revision': '3', |
| 93 'reverted_revision': None | 95 'reverted_revision': None |
| 94 }) | 96 }) |
| 95 | 97 |
| 98 # TODO(wrengr): re crrev.com/2414523002: we need to have a specified |
| 99 # revision_range (even if the versions therein are None), because |
| 100 # ChangelistClassifier.__call__ will take it apart in order to call |
| 101 # GetDEPSRollsDict; if it can't then it will immediately return the |
| 102 # empty list of results, breaking many of the tests here. Of course, |
| 103 # taking revision_range apart isn't actually required for the tests, |
| 104 # since we mock GetDEPSRollsDict. So, really what we ought to do in the |
| 105 # long run is redesign things so that GetDEPSRollsDict takes the |
| 106 # CrashReport directly and pulls out the revision_range and platform |
| 107 # itself; that way ChangelistClassifier.__call__ needn't worry about it, |
| 108 # allowing us to clean up the tests here. |
| 109 DUMMY_REPORT = CrashReport(None, None, None, Stacktrace(), (None, None)) |
| 96 | 110 |
| 97 class FinditForCrashTest(CrashTestSuite): | 111 class ChangelistClassifierTest(CrashTestSuite): |
| 98 | 112 |
| 99 def testGetDepsInCrashStack(self): | 113 def testGetDepsInCrashStack(self): |
| 100 crash_stack = CallStack(0) | 114 crash_stack = CallStack(0) |
| 101 crash_stack.extend([ | 115 crash_stack.extend([ |
| 102 StackFrame(0, 'src/', 'func0', 'f0.cc', 'src/f0.cc', [1]), | 116 StackFrame(0, 'src/', 'func0', 'f0.cc', 'src/f0.cc', [1]), |
| 103 StackFrame(1, 'src/', 'func1', 'f1.cc', 'src/f1.cc', [2, 3]), | 117 StackFrame(1, 'src/', 'func1', 'f1.cc', 'src/f1.cc', [2, 3]), |
| 104 StackFrame(1, '', 'func2', 'f2.cc', 'src/f2.cc', [2, 3]), | 118 StackFrame(1, '', 'func2', 'f2.cc', 'src/f2.cc', [2, 3]), |
| 105 ]) | 119 ]) |
| 106 crash_deps = {'src/': Dependency('src/', 'https://chromium_repo', '1'), | 120 crash_deps = {'src/': Dependency('src/', 'https://chromium_repo', '1'), |
| 107 'src/v8/': Dependency('src/v8/', 'https://v8_repo', '2')} | 121 'src/v8/': Dependency('src/v8/', 'https://v8_repo', '2')} |
| 108 | 122 |
| 109 expected_stack_deps = {'src/': crash_deps['src/']} | 123 expected_stack_deps = {'src/': crash_deps['src/']} |
| 110 | 124 |
| 111 self.assertEqual( | 125 self.assertDictEqual( |
| 112 findit_for_crash.GetDepsInCrashStack(crash_stack, crash_deps), | 126 changelist_classifier.GetDepsInCrashStack(crash_stack, crash_deps), |
| 113 expected_stack_deps) | 127 expected_stack_deps) |
| 114 | 128 |
| 115 def testGetChangeLogsForFilesGroupedByDeps(self): | 129 def testGetChangeLogsForFilesGroupedByDeps(self): |
| 116 regression_deps_rolls = { | 130 regression_deps_rolls = { |
| 117 'src/dep1': DependencyRoll('src/dep1', 'https://url_dep1', '7', '9'), | 131 'src/dep1': DependencyRoll('src/dep1', 'https://url_dep1', '7', '9'), |
| 118 'src/dep2': DependencyRoll('src/dep2', 'repo_url', '3', None), | 132 'src/dep2': DependencyRoll('src/dep2', 'repo_url', '3', None), |
| 119 'src/': DependencyRoll('src/', ('https://chromium.googlesource.com/' | 133 'src/': DependencyRoll('src/', ('https://chromium.googlesource.com/' |
| 120 'chromium/src.git'), '4', '5') | 134 'chromium/src.git'), '4', '5') |
| 121 } | 135 } |
| 122 | 136 |
| 123 stack_deps = { | 137 stack_deps = { |
| 124 'src/': Dependency('src/', 'https://url_src', 'rev1', 'DEPS'), | 138 'src/': Dependency('src/', 'https://url_src', 'rev1', 'DEPS'), |
| 125 'src/new': Dependency('src/new', 'https://new', 'rev2', 'DEPS'), | 139 'src/new': Dependency('src/new', 'https://new', 'rev2', 'DEPS'), |
| 126 } | 140 } |
| 127 | 141 |
| 128 def _MockGetChangeLogs(*_): | 142 def _MockGetChangeLogs(*_): |
| 129 return [DUMMY_CHANGELOG1, DUMMY_CHANGELOG2, DUMMY_CHANGELOG3] | 143 return [DUMMY_CHANGELOG1, DUMMY_CHANGELOG2, DUMMY_CHANGELOG3] |
| 130 | 144 |
| 131 self.mock(git_repository.GitRepository, 'GetChangeLogs', _MockGetChangeLogs) | 145 self.mock(git_repository.GitRepository, 'GetChangeLogs', _MockGetChangeLogs) |
| 132 | 146 |
| 133 dep_file_to_changelogs, ignore_cls = ( | 147 dep_file_to_changelogs, ignore_cls = ( |
| 134 findit_for_crash.GetChangeLogsForFilesGroupedByDeps( | 148 changelist_classifier.GetChangeLogsForFilesGroupedByDeps( |
| 135 regression_deps_rolls, stack_deps, git_repository.GitRepository())) | 149 regression_deps_rolls, stack_deps, git_repository.GitRepository())) |
| 136 dep_file_to_changelogs_json = defaultdict(lambda: defaultdict(list)) | 150 dep_file_to_changelogs_json = defaultdict(lambda: defaultdict(list)) |
| 137 for dep, file_to_changelogs in dep_file_to_changelogs.iteritems(): | 151 for dep, file_to_changelogs in dep_file_to_changelogs.iteritems(): |
| 138 for file_path, changelogs in file_to_changelogs.iteritems(): | 152 for file_path, changelogs in file_to_changelogs.iteritems(): |
| 139 for changelog in changelogs: | 153 for changelog in changelogs: |
| 140 dep_file_to_changelogs_json[dep][file_path].append(changelog.ToDict()) | 154 dep_file_to_changelogs_json[dep][file_path].append(changelog.ToDict()) |
| 141 | 155 |
| 142 expected_dep_file_to_changelogs_json = { | 156 expected_dep_file_to_changelogs_json = { |
| 143 'src/': { | 157 'src/': { |
| 144 'a.cc': [DUMMY_CHANGELOG1.ToDict()], | 158 'a.cc': [DUMMY_CHANGELOG1.ToDict()], |
| 145 'f.cc': [DUMMY_CHANGELOG3.ToDict()] | 159 'f.cc': [DUMMY_CHANGELOG3.ToDict()] |
| 146 } | 160 } |
| 147 } | 161 } |
| 148 self.assertEqual(dep_file_to_changelogs_json, | 162 self.assertDictEqual(dep_file_to_changelogs_json, |
| 149 expected_dep_file_to_changelogs_json) | 163 expected_dep_file_to_changelogs_json) |
| 150 self.assertEqual(ignore_cls, set(['1'])) | 164 self.assertSetEqual(ignore_cls, set(['1'])) |
| 151 | 165 |
| 152 def testGetStackInfosForFilesGroupedByDeps(self): | 166 def testGetStackInfosForFilesGroupedByDeps(self): |
| 153 | |
| 154 main_stack = CallStack(0) | 167 main_stack = CallStack(0) |
| 155 main_stack.extend( | 168 main_stack.extend( |
| 156 [StackFrame(0, 'src/', 'c(p* &d)', 'a.cc', 'src/a.cc', [177]), | 169 [StackFrame(0, 'src/', 'c(p* &d)', 'a.cc', 'src/a.cc', [177]), |
| 157 StackFrame(1, 'src/', 'd(a* c)', 'a.cc', 'src/a.cc', [227, 228, 229]), | 170 StackFrame(1, 'src/', 'd(a* c)', 'a.cc', 'src/a.cc', [227, 228, 229]), |
| 158 StackFrame(2, 'src/v8/', 'e(int)', 'b.cc', 'src/v8/b.cc', [89, 90])]) | 171 StackFrame(2, 'src/v8/', 'e(int)', 'b.cc', 'src/v8/b.cc', [89, 90])]) |
| 159 | 172 |
| 160 low_priority_stack = CallStack(1) | 173 low_priority_stack = CallStack(1) |
| 161 low_priority_stack.append( | 174 low_priority_stack.append( |
| 162 StackFrame(0, 'src/dummy/', 'c(p* &d)', 'd.cc', 'src/dummy/d.cc', [17])) | 175 StackFrame(0, 'src/dummy/', 'c(p* &d)', 'd.cc', 'src/dummy/d.cc', [17])) |
| 163 | 176 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 175 ], | 188 ], |
| 176 }, | 189 }, |
| 177 'src/v8/': { | 190 'src/v8/': { |
| 178 'b.cc': [ | 191 'b.cc': [ |
| 179 (main_stack[2], 0), | 192 (main_stack[2], 0), |
| 180 ] | 193 ] |
| 181 } | 194 } |
| 182 } | 195 } |
| 183 | 196 |
| 184 dep_file_to_stack_infos = ( | 197 dep_file_to_stack_infos = ( |
| 185 findit_for_crash.GetStackInfosForFilesGroupedByDeps( | 198 changelist_classifier.GetStackInfosForFilesGroupedByDeps( |
| 186 stacktrace, crashed_deps)) | 199 stacktrace, crashed_deps)) |
| 187 | 200 |
| 188 self.assertEqual(len(dep_file_to_stack_infos), | 201 self.assertEqual(len(dep_file_to_stack_infos), |
| 189 len(expected_dep_file_to_stack_infos)) | 202 len(expected_dep_file_to_stack_infos)) |
| 190 | 203 |
| 191 for dep, file_to_stack_infos in dep_file_to_stack_infos.iteritems(): | 204 for dep, file_to_stack_infos in dep_file_to_stack_infos.iteritems(): |
| 192 self.assertTrue(dep in expected_dep_file_to_stack_infos) | 205 self.assertTrue(dep in expected_dep_file_to_stack_infos) |
| 193 expected_file_to_stack_infos = expected_dep_file_to_stack_infos[dep] | 206 expected_file_to_stack_infos = expected_dep_file_to_stack_infos[dep] |
| 194 | 207 |
| 195 for file_path, stack_infos in file_to_stack_infos.iteritems(): | 208 for file_path, stack_infos in file_to_stack_infos.iteritems(): |
| (...skipping 22 matching lines...) Expand all Loading... |
| 218 ] | 231 ] |
| 219 } | 232 } |
| 220 } | 233 } |
| 221 | 234 |
| 222 dummy_blame = Blame('9', 'a.cc') | 235 dummy_blame = Blame('9', 'a.cc') |
| 223 dummy_blame.AddRegion( | 236 dummy_blame.AddRegion( |
| 224 Region(1, 5, '6', 'a', 'a@chromium.org', 'Thu Mar 31 21:24:43 2016')) | 237 Region(1, 5, '6', 'a', 'a@chromium.org', 'Thu Mar 31 21:24:43 2016')) |
| 225 dummy_blame.AddRegion( | 238 dummy_blame.AddRegion( |
| 226 Region(6, 10, '1', 'b', 'b@chromium.org', 'Thu Jun 19 12:11:40 2015')) | 239 Region(6, 10, '1', 'b', 'b@chromium.org', 'Thu Jun 19 12:11:40 2015')) |
| 227 | 240 |
| 228 def _MockGetBlame(*_): | 241 self.mock(GitRepository, 'GetBlame', lambda *_: dummy_blame) |
| 229 return dummy_blame | |
| 230 | |
| 231 self.mock(git_repository.GitRepository, 'GetBlame', _MockGetBlame) | |
| 232 | 242 |
| 233 stack_deps = { | 243 stack_deps = { |
| 234 'src/': Dependency('src/', 'https://url_src', 'rev1', 'DEPS'), | 244 'src/': Dependency('src/', 'https://url_src', 'rev1', 'DEPS'), |
| 235 } | 245 } |
| 236 | 246 |
| 237 expected_match_results = [{ | 247 expected_match_results = [{ |
| 238 'url': 'https://repo.test/+/1', | 248 'url': 'https://repo.test/+/1', |
| 239 'review_url': 'https://codereview.chromium.org/3281', | 249 'review_url': 'https://codereview.chromium.org/3281', |
| 240 'revision': '1', | 250 'revision': '1', |
| 241 'project_path': 'src/', | 251 'project_path': 'src/', |
| 242 'author': 'r@chromium.org', | 252 'author': 'r@chromium.org', |
| 243 'time': 'Thu Mar 31 21:24:43 2016', | 253 'time': 'Thu Mar 31 21:24:43 2016', |
| 244 'reasons': None, | 254 'reasons': None, |
| 245 'confidence': None, | 255 'confidence': None, |
| 246 'changed_files': None | 256 'changed_files': None |
| 247 }] | 257 }] |
| 248 | 258 |
| 249 match_results = findit_for_crash.FindMatchResults( | 259 match_results = changelist_classifier.FindMatchResults( |
| 250 dep_file_to_changelogs, dep_file_to_stack_infos, stack_deps, | 260 dep_file_to_changelogs, dep_file_to_stack_infos, stack_deps, |
| 251 git_repository.GitRepository()) | 261 git_repository.GitRepository()) |
| 252 self.assertEqual([result.ToDict() for result in match_results], | 262 self.assertListEqual([result.ToDict() for result in match_results], |
| 253 expected_match_results) | 263 expected_match_results) |
| 254 | 264 |
| 255 def testFindItForCrashNoRegressionRange(self): | 265 # TODO(http://crbug.com/659346): why do these mocks give coverage |
| 256 self.assertEqual( | 266 # failures? That's almost surely hiding a bug in the tests themselves. |
| 257 findit_for_crash.FindItForCrash(Stacktrace(), {}, {}, 7, | 267 def testFindItForCrashNoRegressionRange(self): # pragma: no cover |
| 258 git_repository.GitRepository()), | 268 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 259 []) | 269 'GetDependencyRollsDict', lambda *_: {}) |
| 270 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 271 'GetDependency', lambda *_: {}) |
| 272 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
| 273 git_repository.GitRepository()) |
| 274 # N.B., for this one test we really do want regression_range=None. |
| 275 report = DUMMY_REPORT._replace(regression_range=None) |
| 276 self.assertListEqual(cl_classifier(report), []) |
| 260 | 277 |
| 261 def testFindItForCrashNoMatchFound(self): | 278 def testFindItForCrashNoMatchFound(self): |
| 262 | 279 self.mock(changelist_classifier, 'FindMatchResults', lambda *_: []) |
| 263 def _MockFindMatchResults(*_): | 280 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 264 return [] | 281 'GetDependencyRollsDict', |
| 265 | 282 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) |
| 266 self.mock(findit_for_crash, 'FindMatchResults', _MockFindMatchResults) | 283 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 267 | 284 'GetDependency', lambda *_: {}) |
| 268 regression_deps_rolls = {'src/': DependencyRoll('src/', 'https://repo', | 285 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
| 269 '1', '2')} | 286 git_repository.GitRepository()) |
| 270 self.assertEqual(findit_for_crash.FindItForCrash( | 287 self.assertListEqual(cl_classifier(DUMMY_REPORT), []) |
| 271 Stacktrace(), regression_deps_rolls, {}, 7, | |
| 272 git_repository.GitRepository()), []) | |
| 273 | 288 |
| 274 def testFindItForCrash(self): | 289 def testFindItForCrash(self): |
| 275 | 290 |
| 276 def _MockFindMatchResults(*_): | 291 def _MockFindMatchResults(*_): |
| 277 match_result1 = MatchResult(DUMMY_CHANGELOG1, 'src/', '') | 292 match_result1 = MatchResult(DUMMY_CHANGELOG1, 'src/', '') |
| 278 frame1 = StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [1]) | 293 frame1 = StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [1]) |
| 279 frame2 = StackFrame(1, 'src/', 'func', 'a.cc', 'src/a.cc', [7]) | 294 frame2 = StackFrame(1, 'src/', 'func', 'a.cc', 'src/a.cc', [7]) |
| 280 match_result1.file_to_stack_infos = { | 295 match_result1.file_to_stack_infos = { |
| 281 'a.cc': [(frame1, 0), (frame2, 0)] | 296 'a.cc': [(frame1, 0), (frame2, 0)] |
| 282 } | 297 } |
| 283 match_result1.file_to_analysis_info = { | 298 match_result1.file_to_analysis_info = { |
| 284 'a.cc': {'min_distance': 0, 'min_distance_frame': frame1} | 299 'a.cc': {'min_distance': 0, 'min_distance_frame': frame1} |
| 285 } | 300 } |
| 286 | 301 |
| 287 match_result2 = MatchResult(DUMMY_CHANGELOG3, 'src/', '') | 302 match_result2 = MatchResult(DUMMY_CHANGELOG3, 'src/', '') |
| 288 frame3 = StackFrame(5, 'src/', 'func', 'f.cc', 'src/f.cc', [1]) | 303 frame3 = StackFrame(5, 'src/', 'func', 'f.cc', 'src/f.cc', [1]) |
| 289 match_result2.file_to_stack_infos = { | 304 match_result2.file_to_stack_infos = { |
| 290 'f.cc': [(frame3, 0)] | 305 'f.cc': [(frame3, 0)] |
| 291 } | 306 } |
| 292 match_result2.file_to_analysis_info = { | 307 match_result2.file_to_analysis_info = { |
| 293 'a.cc': {'min_distance': 20, 'min_distance_frame': frame3} | 308 'a.cc': {'min_distance': 20, 'min_distance_frame': frame3} |
| 294 } | 309 } |
| 295 | 310 |
| 296 return [match_result1, match_result2] | 311 return [match_result1, match_result2] |
| 297 | 312 |
| 298 self.mock(findit_for_crash, 'FindMatchResults', _MockFindMatchResults) | 313 self.mock(changelist_classifier, 'FindMatchResults', _MockFindMatchResults) |
| 299 | 314 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 315 'GetDependencyRollsDict', |
| 316 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) |
| 317 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 318 'GetDependency', lambda *_: {}) |
| 319 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
| 320 git_repository.GitRepository()) |
| 321 results = cl_classifier(DUMMY_REPORT) |
| 300 expected_match_results = [ | 322 expected_match_results = [ |
| 301 { | 323 { |
| 302 'reasons': [('TopFrameIndex', 1.0, 'Top frame is #0'), | 324 'reasons': [('TopFrameIndex', 1.0, 'Top frame is #0'), |
| 303 ('MinDistance', 1, 'Minimum distance is 0')], | 325 ('MinDistance', 1, 'Minimum distance is 0')], |
| 304 'changed_files': [{'info': 'Minimum distance (LOC) 0, frame #0', | 326 'changed_files': [{'info': 'Minimum distance (LOC) 0, frame #0', |
| 305 'blame_url': None, 'file': 'a.cc'}], | 327 'blame_url': None, 'file': 'a.cc'}], |
| 306 'time': 'Thu Mar 31 21:24:43 2016', | 328 'time': 'Thu Mar 31 21:24:43 2016', |
| 307 'author': 'r@chromium.org', | 329 'author': 'r@chromium.org', |
| 308 'url': 'https://repo.test/+/1', | 330 'url': 'https://repo.test/+/1', |
| 309 'project_path': 'src/', | 331 'project_path': 'src/', |
| 310 'review_url': 'https://codereview.chromium.org/3281', | 332 'review_url': 'https://codereview.chromium.org/3281', |
| 311 'confidence': 1.0, 'revision': '1' | 333 'confidence': 1.0, 'revision': '1' |
| 312 }, | 334 }, |
| 313 ] | 335 ] |
| 314 | 336 self.assertListEqual([result.ToDict() for result in results], |
| 315 regression_deps_rolls = {'src/': DependencyRoll('src/', 'https://repo', | 337 expected_match_results) |
| 316 '1', '2')} | |
| 317 | |
| 318 results = findit_for_crash.FindItForCrash(Stacktrace(), | |
| 319 regression_deps_rolls, {}, 7, | |
| 320 git_repository.GitRepository()) | |
| 321 self.assertEqual([result.ToDict() for result in results], | |
| 322 expected_match_results) | |
| 323 | 338 |
| 324 def testFinditForCrashFilterZeroConfidentResults(self): | 339 def testFinditForCrashFilterZeroConfidentResults(self): |
| 325 def _MockFindMatchResults(*_): | 340 def _MockFindMatchResults(*_): |
| 326 match_result1 = MatchResult(DUMMY_CHANGELOG1, 'src/', '') | 341 match_result1 = MatchResult(DUMMY_CHANGELOG1, 'src/', '') |
| 327 frame1 = StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [1]) | 342 frame1 = StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [1]) |
| 328 frame2 = StackFrame(1, 'src/', 'func', 'a.cc', 'src/a.cc', [7]) | 343 frame2 = StackFrame(1, 'src/', 'func', 'a.cc', 'src/a.cc', [7]) |
| 329 match_result1.file_to_stack_infos = { | 344 match_result1.file_to_stack_infos = { |
| 330 'a.cc': [(frame1, 0), (frame2, 0)] | 345 'a.cc': [(frame1, 0), (frame2, 0)] |
| 331 } | 346 } |
| 332 match_result1.file_to_analysis_info = { | 347 match_result1.file_to_analysis_info = { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 346 frame4 = StackFrame(3, 'src/', 'func', 'ff.cc', 'src/ff.cc', [1]) | 361 frame4 = StackFrame(3, 'src/', 'func', 'ff.cc', 'src/ff.cc', [1]) |
| 347 match_result3.file_to_stack_infos = { | 362 match_result3.file_to_stack_infos = { |
| 348 'f.cc': [(frame4, 0)] | 363 'f.cc': [(frame4, 0)] |
| 349 } | 364 } |
| 350 match_result3.file_to_analysis_info = { | 365 match_result3.file_to_analysis_info = { |
| 351 'f.cc': {'min_distance': 60, 'min_distance_frame': frame4} | 366 'f.cc': {'min_distance': 60, 'min_distance_frame': frame4} |
| 352 } | 367 } |
| 353 | 368 |
| 354 return [match_result1, match_result2, match_result3] | 369 return [match_result1, match_result2, match_result3] |
| 355 | 370 |
| 356 self.mock(findit_for_crash, 'FindMatchResults', _MockFindMatchResults) | 371 self.mock(changelist_classifier, 'FindMatchResults', _MockFindMatchResults) |
| 372 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 373 'GetDependencyRollsDict', |
| 374 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) |
| 375 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 376 'GetDependency', lambda *_: {}) |
| 357 | 377 |
| 378 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
| 379 git_repository.GitRepository()) |
| 380 results = cl_classifier(DUMMY_REPORT) |
| 358 expected_match_results = [ | 381 expected_match_results = [ |
| 359 { | 382 { |
| 360 'author': 'r@chromium.org', | 383 'author': 'r@chromium.org', |
| 361 'changed_files': [ | 384 'changed_files': [ |
| 362 { | 385 { |
| 363 'blame_url': None, | 386 'blame_url': None, |
| 364 'file': 'a.cc', | 387 'file': 'a.cc', |
| 365 'info': 'Minimum distance (LOC) 1, frame #0' | 388 'info': 'Minimum distance (LOC) 1, frame #0' |
| 366 } | 389 } |
| 367 ], | 390 ], |
| 368 'confidence': 0.8, | 391 'confidence': 0.8, |
| 369 'project_path': 'src/', | 392 'project_path': 'src/', |
| 370 'reasons': [ | 393 'reasons': [ |
| 371 ('TopFrameIndex', 1.0, 'Top frame is #0'), | 394 ('TopFrameIndex', 1.0, 'Top frame is #0'), |
| 372 ('MinDistance', 0.8, 'Minimum distance is 1') | 395 ('MinDistance', 0.8, 'Minimum distance is 1') |
| 373 ], | 396 ], |
| 374 'review_url': 'https://codereview.chromium.org/3281', | 397 'review_url': 'https://codereview.chromium.org/3281', |
| 375 'revision': '1', | 398 'revision': '1', |
| 376 'time': 'Thu Mar 31 21:24:43 2016', | 399 'time': 'Thu Mar 31 21:24:43 2016', |
| 377 'url': 'https://repo.test/+/1' | 400 'url': 'https://repo.test/+/1' |
| 378 } | 401 } |
| 379 ] | 402 ] |
| 380 | 403 self.assertListEqual([result.ToDict() for result in results], |
| 381 regression_deps_rolls = {'src/': DependencyRoll('src/', 'https://repo', | 404 expected_match_results) |
| 382 '1', '2')} | |
| 383 | |
| 384 results = findit_for_crash.FindItForCrash(Stacktrace(), | |
| 385 regression_deps_rolls, {}, 7, | |
| 386 git_repository.GitRepository()) | |
| 387 | |
| 388 self.assertEqual([result.ToDict() for result in results], | |
| 389 expected_match_results) | |
| 390 | 405 |
| 391 def testFinditForCrashAllMatchResultsWithZeroConfidences(self): | 406 def testFinditForCrashAllMatchResultsWithZeroConfidences(self): |
| 392 def _MockFindMatchResults(*_): | 407 def _MockFindMatchResults(*_): |
| 393 match_result1 = MatchResult(DUMMY_CHANGELOG1, 'src/', '') | 408 match_result1 = MatchResult(DUMMY_CHANGELOG1, 'src/', '') |
| 394 frame1 = StackFrame(20, 'src/', '', 'func', 'a.cc', [1]) | 409 frame1 = StackFrame(20, 'src/', '', 'func', 'a.cc', [1]) |
| 395 frame2 = StackFrame(21, 'src/', '', 'func', 'a.cc', [7]) | 410 frame2 = StackFrame(21, 'src/', '', 'func', 'a.cc', [7]) |
| 396 match_result1.file_to_stack_infos = { | 411 match_result1.file_to_stack_infos = { |
| 397 'a.cc': [(frame1, 0), (frame2, 0)] | 412 'a.cc': [(frame1, 0), (frame2, 0)] |
| 398 } | 413 } |
| 399 match_result1.file_to_analysis_info = { | 414 match_result1.file_to_analysis_info = { |
| 400 'a.cc': {'min_distance': 1, 'min_distance_frame': frame1} | 415 'a.cc': {'min_distance': 1, 'min_distance_frame': frame1} |
| 401 } | 416 } |
| 402 | 417 |
| 403 match_result2 = MatchResult(DUMMY_CHANGELOG3, 'src/', '') | 418 match_result2 = MatchResult(DUMMY_CHANGELOG3, 'src/', '') |
| 404 frame3 = StackFrame(15, 'src/', '', 'func', 'f.cc', [1]) | 419 frame3 = StackFrame(15, 'src/', '', 'func', 'f.cc', [1]) |
| 405 match_result2.file_to_stack_infos = { | 420 match_result2.file_to_stack_infos = { |
| 406 'f.cc': [(frame3, 0)] | 421 'f.cc': [(frame3, 0)] |
| 407 } | 422 } |
| 408 match_result2.min_distance = 20 | 423 match_result2.min_distance = 20 |
| 409 match_result2.file_to_analysis_info = { | 424 match_result2.file_to_analysis_info = { |
| 410 'f.cc': {'min_distance': 20, 'min_distance_frame': frame3} | 425 'f.cc': {'min_distance': 20, 'min_distance_frame': frame3} |
| 411 } | 426 } |
| 412 | 427 |
| 413 return [match_result1, match_result2] | 428 return [match_result1, match_result2] |
| 414 | 429 |
| 415 self.mock(findit_for_crash, 'FindMatchResults', _MockFindMatchResults) | 430 self.mock(changelist_classifier, 'FindMatchResults', _MockFindMatchResults) |
| 431 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 432 'GetDependencyRollsDict', |
| 433 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) |
| 434 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
| 435 'GetDependency', lambda *_: {}) |
| 416 | 436 |
| 417 regression_deps_rolls = {'src/': DependencyRoll('src/', 'https://repo', | 437 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
| 418 '1', '2')} | 438 git_repository.GitRepository()) |
| 419 | 439 self.assertListEqual(cl_classifier(DUMMY_REPORT), []) |
| 420 self.assertEqual(findit_for_crash.FindItForCrash( | |
| 421 Stacktrace(), regression_deps_rolls, {}, 7, | |
| 422 git_repository.GitRepository()), []) | |
| OLD | NEW |