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.blame import Blame | |
8 from common.blame import Region | |
9 from common.change_log import ChangeLog | |
10 from common.dependency import Dependency | 7 from common.dependency import Dependency |
11 from common.dependency import DependencyRoll | 8 from common.dependency import DependencyRoll |
12 from common.git_repository import GitRepository | |
13 from common.http_client_appengine import HttpClientAppengine | 9 from common.http_client_appengine import HttpClientAppengine |
14 from common import chrome_dependency_fetcher | 10 from common import chrome_dependency_fetcher |
15 from common import git_repository | |
16 from crash.crash_report import CrashReport | 11 from crash.crash_report import CrashReport |
17 from crash import changelist_classifier | 12 from crash import changelist_classifier |
18 from crash.results import MatchResult | 13 from crash.results import MatchResult |
19 from crash.stacktrace import CallStack | 14 from crash.stacktrace import CallStack |
20 from crash.stacktrace import StackFrame | 15 from crash.stacktrace import StackFrame |
21 from crash.stacktrace import Stacktrace | 16 from crash.stacktrace import Stacktrace |
22 from crash.test.crash_test_suite import CrashTestSuite | 17 from crash.test.crash_test_suite import CrashTestSuite |
| 18 from lib.gitiles.blame import Blame |
| 19 from lib.gitiles.blame import Region |
| 20 from lib.gitiles.change_log import ChangeLog |
| 21 from lib.gitiles.gitiles_repository import GitilesRepository |
23 | 22 |
24 DUMMY_CHANGELOG1 = ChangeLog.FromDict({ | 23 DUMMY_CHANGELOG1 = ChangeLog.FromDict({ |
25 'author_name': 'r@chromium.org', | 24 'author_name': 'r@chromium.org', |
26 'message': 'dummy', | 25 'message': 'dummy', |
27 'committer_email': 'r@chromium.org', | 26 'committer_email': 'r@chromium.org', |
28 'commit_position': 175900, | 27 'commit_position': 175900, |
29 'author_email': 'r@chromium.org', | 28 'author_email': 'r@chromium.org', |
30 'touched_files': [ | 29 'touched_files': [ |
31 { | 30 { |
32 'change_type': 'add', | 31 'change_type': 'add', |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 } | 134 } |
136 | 135 |
137 stack_deps = { | 136 stack_deps = { |
138 'src/': Dependency('src/', 'https://url_src', 'rev1', 'DEPS'), | 137 'src/': Dependency('src/', 'https://url_src', 'rev1', 'DEPS'), |
139 'src/new': Dependency('src/new', 'https://new', 'rev2', 'DEPS'), | 138 'src/new': Dependency('src/new', 'https://new', 'rev2', 'DEPS'), |
140 } | 139 } |
141 | 140 |
142 def _MockGetChangeLogs(*_): | 141 def _MockGetChangeLogs(*_): |
143 return [DUMMY_CHANGELOG1, DUMMY_CHANGELOG2, DUMMY_CHANGELOG3] | 142 return [DUMMY_CHANGELOG1, DUMMY_CHANGELOG2, DUMMY_CHANGELOG3] |
144 | 143 |
145 self.mock(git_repository.GitRepository, 'GetChangeLogs', _MockGetChangeLogs) | 144 self.mock(GitilesRepository, 'GetChangeLogs', _MockGetChangeLogs) |
146 | 145 |
147 dep_file_to_changelogs, ignore_cls = ( | 146 dep_file_to_changelogs, ignore_cls = ( |
148 changelist_classifier.GetChangeLogsForFilesGroupedByDeps( | 147 changelist_classifier.GetChangeLogsForFilesGroupedByDeps( |
149 regression_deps_rolls, stack_deps, git_repository.GitRepository())) | 148 regression_deps_rolls, stack_deps, GitilesRepository())) |
150 dep_file_to_changelogs_json = defaultdict(lambda: defaultdict(list)) | 149 dep_file_to_changelogs_json = defaultdict(lambda: defaultdict(list)) |
151 for dep, file_to_changelogs in dep_file_to_changelogs.iteritems(): | 150 for dep, file_to_changelogs in dep_file_to_changelogs.iteritems(): |
152 for file_path, changelogs in file_to_changelogs.iteritems(): | 151 for file_path, changelogs in file_to_changelogs.iteritems(): |
153 for changelog in changelogs: | 152 for changelog in changelogs: |
154 dep_file_to_changelogs_json[dep][file_path].append(changelog.ToDict()) | 153 dep_file_to_changelogs_json[dep][file_path].append(changelog.ToDict()) |
155 | 154 |
156 expected_dep_file_to_changelogs_json = { | 155 expected_dep_file_to_changelogs_json = { |
157 'src/': { | 156 'src/': { |
158 'a.cc': [DUMMY_CHANGELOG1.ToDict()], | 157 'a.cc': [DUMMY_CHANGELOG1.ToDict()], |
159 'f.cc': [DUMMY_CHANGELOG3.ToDict()] | 158 'f.cc': [DUMMY_CHANGELOG3.ToDict()] |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 ] | 230 ] |
232 } | 231 } |
233 } | 232 } |
234 | 233 |
235 dummy_blame = Blame('9', 'a.cc') | 234 dummy_blame = Blame('9', 'a.cc') |
236 dummy_blame.AddRegion( | 235 dummy_blame.AddRegion( |
237 Region(1, 5, '6', 'a', 'a@chromium.org', 'Thu Mar 31 21:24:43 2016')) | 236 Region(1, 5, '6', 'a', 'a@chromium.org', 'Thu Mar 31 21:24:43 2016')) |
238 dummy_blame.AddRegion( | 237 dummy_blame.AddRegion( |
239 Region(6, 10, '1', 'b', 'b@chromium.org', 'Thu Jun 19 12:11:40 2015')) | 238 Region(6, 10, '1', 'b', 'b@chromium.org', 'Thu Jun 19 12:11:40 2015')) |
240 | 239 |
241 self.mock(GitRepository, 'GetBlame', lambda *_: dummy_blame) | 240 self.mock(GitilesRepository, 'GetBlame', lambda *_: dummy_blame) |
242 | 241 |
243 stack_deps = { | 242 stack_deps = { |
244 'src/': Dependency('src/', 'https://url_src', 'rev1', 'DEPS'), | 243 'src/': Dependency('src/', 'https://url_src', 'rev1', 'DEPS'), |
245 } | 244 } |
246 | 245 |
247 expected_match_results = [{ | 246 expected_match_results = [{ |
248 'url': 'https://repo.test/+/1', | 247 'url': 'https://repo.test/+/1', |
249 'review_url': 'https://codereview.chromium.org/3281', | 248 'review_url': 'https://codereview.chromium.org/3281', |
250 'revision': '1', | 249 'revision': '1', |
251 'project_path': 'src/', | 250 'project_path': 'src/', |
252 'author': 'r@chromium.org', | 251 'author': 'r@chromium.org', |
253 'time': 'Thu Mar 31 21:24:43 2016', | 252 'time': 'Thu Mar 31 21:24:43 2016', |
254 'reasons': None, | 253 'reasons': None, |
255 'confidence': None, | 254 'confidence': None, |
256 'changed_files': None | 255 'changed_files': None |
257 }] | 256 }] |
258 | 257 |
259 match_results = changelist_classifier.FindMatchResults( | 258 match_results = changelist_classifier.FindMatchResults( |
260 dep_file_to_changelogs, dep_file_to_stack_infos, stack_deps, | 259 dep_file_to_changelogs, dep_file_to_stack_infos, stack_deps, |
261 git_repository.GitRepository()) | 260 GitilesRepository()) |
262 self.assertListEqual([result.ToDict() for result in match_results], | 261 self.assertListEqual([result.ToDict() for result in match_results], |
263 expected_match_results) | 262 expected_match_results) |
264 | 263 |
265 # TODO(http://crbug.com/659346): why do these mocks give coverage | 264 # TODO(http://crbug.com/659346): why do these mocks give coverage |
266 # failures? That's almost surely hiding a bug in the tests themselves. | 265 # failures? That's almost surely hiding a bug in the tests themselves. |
267 def testFindItForCrashNoRegressionRange(self): # pragma: no cover | 266 def testFindItForCrashNoRegressionRange(self): # pragma: no cover |
268 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 267 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
269 'GetDependencyRollsDict', lambda *_: {}) | 268 'GetDependencyRollsDict', lambda *_: {}) |
270 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 269 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
271 'GetDependency', lambda *_: {}) | 270 'GetDependency', lambda *_: {}) |
272 cl_classifier = changelist_classifier.ChangelistClassifier(7, | 271 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
273 git_repository.GitRepository()) | 272 GitilesRepository()) |
274 # N.B., for this one test we really do want regression_range=None. | 273 # N.B., for this one test we really do want regression_range=None. |
275 report = DUMMY_REPORT._replace(regression_range=None) | 274 report = DUMMY_REPORT._replace(regression_range=None) |
276 self.assertListEqual(cl_classifier(report), []) | 275 self.assertListEqual(cl_classifier(report), []) |
277 | 276 |
278 def testFindItForCrashNoMatchFound(self): | 277 def testFindItForCrashNoMatchFound(self): |
279 self.mock(changelist_classifier, 'FindMatchResults', lambda *_: []) | 278 self.mock(changelist_classifier, 'FindMatchResults', lambda *_: []) |
280 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 279 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
281 'GetDependencyRollsDict', | 280 'GetDependencyRollsDict', |
282 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) | 281 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) |
283 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 282 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
284 'GetDependency', lambda *_: {}) | 283 'GetDependency', lambda *_: {}) |
285 cl_classifier = changelist_classifier.ChangelistClassifier(7, | 284 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
286 git_repository.GitRepository()) | 285 GitilesRepository()) |
287 self.assertListEqual(cl_classifier(DUMMY_REPORT), []) | 286 self.assertListEqual(cl_classifier(DUMMY_REPORT), []) |
288 | 287 |
289 def testFindItForCrash(self): | 288 def testFindItForCrash(self): |
290 | 289 |
291 def _MockFindMatchResults(*_): | 290 def _MockFindMatchResults(*_): |
292 match_result1 = MatchResult(DUMMY_CHANGELOG1, 'src/', '') | 291 match_result1 = MatchResult(DUMMY_CHANGELOG1, 'src/', '') |
293 frame1 = StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [1]) | 292 frame1 = StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [1]) |
294 frame2 = StackFrame(1, 'src/', 'func', 'a.cc', 'src/a.cc', [7]) | 293 frame2 = StackFrame(1, 'src/', 'func', 'a.cc', 'src/a.cc', [7]) |
295 match_result1.file_to_stack_infos = { | 294 match_result1.file_to_stack_infos = { |
296 'a.cc': [(frame1, 0), (frame2, 0)] | 295 'a.cc': [(frame1, 0), (frame2, 0)] |
(...skipping 13 matching lines...) Expand all Loading... |
310 | 309 |
311 return [match_result1, match_result2] | 310 return [match_result1, match_result2] |
312 | 311 |
313 self.mock(changelist_classifier, 'FindMatchResults', _MockFindMatchResults) | 312 self.mock(changelist_classifier, 'FindMatchResults', _MockFindMatchResults) |
314 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 313 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
315 'GetDependencyRollsDict', | 314 'GetDependencyRollsDict', |
316 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) | 315 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) |
317 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 316 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
318 'GetDependency', lambda *_: {}) | 317 'GetDependency', lambda *_: {}) |
319 cl_classifier = changelist_classifier.ChangelistClassifier(7, | 318 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
320 git_repository.GitRepository()) | 319 GitilesRepository()) |
321 results = cl_classifier(DUMMY_REPORT) | 320 results = cl_classifier(DUMMY_REPORT) |
322 expected_match_results = [ | 321 expected_match_results = [ |
323 { | 322 { |
324 'reasons': [('TopFrameIndex', 1.0, 'Top frame is #0'), | 323 'reasons': [('TopFrameIndex', 1.0, 'Top frame is #0'), |
325 ('MinDistance', 1, 'Minimum distance is 0')], | 324 ('MinDistance', 1, 'Minimum distance is 0')], |
326 'changed_files': [{'info': 'Minimum distance (LOC) 0, frame #0', | 325 'changed_files': [{'info': 'Minimum distance (LOC) 0, frame #0', |
327 'blame_url': None, 'file': 'a.cc'}], | 326 'blame_url': None, 'file': 'a.cc'}], |
328 'time': 'Thu Mar 31 21:24:43 2016', | 327 'time': 'Thu Mar 31 21:24:43 2016', |
329 'author': 'r@chromium.org', | 328 'author': 'r@chromium.org', |
330 'url': 'https://repo.test/+/1', | 329 'url': 'https://repo.test/+/1', |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 return [match_result1, match_result2, match_result3] | 368 return [match_result1, match_result2, match_result3] |
370 | 369 |
371 self.mock(changelist_classifier, 'FindMatchResults', _MockFindMatchResults) | 370 self.mock(changelist_classifier, 'FindMatchResults', _MockFindMatchResults) |
372 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 371 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
373 'GetDependencyRollsDict', | 372 'GetDependencyRollsDict', |
374 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) | 373 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) |
375 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 374 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
376 'GetDependency', lambda *_: {}) | 375 'GetDependency', lambda *_: {}) |
377 | 376 |
378 cl_classifier = changelist_classifier.ChangelistClassifier(7, | 377 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
379 git_repository.GitRepository()) | 378 GitilesRepository()) |
380 results = cl_classifier(DUMMY_REPORT) | 379 results = cl_classifier(DUMMY_REPORT) |
381 expected_match_results = [ | 380 expected_match_results = [ |
382 { | 381 { |
383 'author': 'r@chromium.org', | 382 'author': 'r@chromium.org', |
384 'changed_files': [ | 383 'changed_files': [ |
385 { | 384 { |
386 'blame_url': None, | 385 'blame_url': None, |
387 'file': 'a.cc', | 386 'file': 'a.cc', |
388 'info': 'Minimum distance (LOC) 1, frame #0' | 387 'info': 'Minimum distance (LOC) 1, frame #0' |
389 } | 388 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 return [match_result1, match_result2] | 427 return [match_result1, match_result2] |
429 | 428 |
430 self.mock(changelist_classifier, 'FindMatchResults', _MockFindMatchResults) | 429 self.mock(changelist_classifier, 'FindMatchResults', _MockFindMatchResults) |
431 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 430 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
432 'GetDependencyRollsDict', | 431 'GetDependencyRollsDict', |
433 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) | 432 lambda *_: {'src/': DependencyRoll('src/', 'https://repo', '1', '2')}) |
434 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, | 433 self.mock(chrome_dependency_fetcher.ChromeDependencyFetcher, |
435 'GetDependency', lambda *_: {}) | 434 'GetDependency', lambda *_: {}) |
436 | 435 |
437 cl_classifier = changelist_classifier.ChangelistClassifier(7, | 436 cl_classifier = changelist_classifier.ChangelistClassifier(7, |
438 git_repository.GitRepository()) | 437 GitilesRepository()) |
439 self.assertListEqual(cl_classifier(DUMMY_REPORT), []) | 438 self.assertListEqual(cl_classifier(DUMMY_REPORT), []) |
OLD | NEW |