OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Unit tests for git_cl.py.""" | 6 """Unit tests for git_cl.py.""" |
7 | 7 |
8 import os | 8 import os |
9 import StringIO | 9 import StringIO |
10 import stat | 10 import stat |
(...skipping 12 matching lines...) Expand all Loading... |
23 def __init__(self, *args, **kwargs): | 23 def __init__(self, *args, **kwargs): |
24 self.reviewers = [] | 24 self.reviewers = [] |
25 @staticmethod | 25 @staticmethod |
26 def should_continue(): | 26 def should_continue(): |
27 return True | 27 return True |
28 | 28 |
29 | 29 |
30 class RietveldMock(object): | 30 class RietveldMock(object): |
31 def __init__(self, *args, **kwargs): | 31 def __init__(self, *args, **kwargs): |
32 pass | 32 pass |
| 33 |
33 @staticmethod | 34 @staticmethod |
34 def get_description(issue): | 35 def get_description(issue): |
35 return 'Issue: %d' % issue | 36 return 'Issue: %d' % issue |
36 | 37 |
| 38 @staticmethod |
| 39 def get_issue_properties(_issue, _messages): |
| 40 return { |
| 41 'reviewers': ['joe@chromium.org', 'john@chromium.org'], |
| 42 'messages': [ |
| 43 { |
| 44 'approval': True, |
| 45 'sender': 'john@chromium.org', |
| 46 }, |
| 47 ], |
| 48 } |
| 49 |
37 | 50 |
38 class WatchlistsMock(object): | 51 class WatchlistsMock(object): |
39 def __init__(self, _): | 52 def __init__(self, _): |
40 pass | 53 pass |
41 @staticmethod | 54 @staticmethod |
42 def GetWatchersForPaths(_): | 55 def GetWatchersForPaths(_): |
43 return ['joe@example.com'] | 56 return ['joe@example.com'] |
44 | 57 |
45 | 58 |
46 class CodereviewSettingsFileMock(object): | 59 class CodereviewSettingsFileMock(object): |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 ((['git', 'show-ref', '--quiet', '--verify', | 277 ((['git', 'show-ref', '--quiet', '--verify', |
265 'refs/heads/git-cl-commit'],), | 278 'refs/heads/git-cl-commit'],), |
266 (('', None), 0)), | 279 (('', None), 0)), |
267 ((['git', 'branch', '-D', 'git-cl-commit'],), ''), | 280 ((['git', 'branch', '-D', 'git-cl-commit'],), ''), |
268 ((['git', 'show-ref', '--quiet', '--verify', | 281 ((['git', 'show-ref', '--quiet', '--verify', |
269 'refs/heads/git-cl-cherry-pick'],), ''), | 282 'refs/heads/git-cl-cherry-pick'],), ''), |
270 ((['git', 'rev-parse', '--show-cdup'],), '\n'), | 283 ((['git', 'rev-parse', '--show-cdup'],), '\n'), |
271 ((['git', 'checkout', '-q', '-b', 'git-cl-commit'],), ''), | 284 ((['git', 'checkout', '-q', '-b', 'git-cl-commit'],), ''), |
272 ((['git', 'reset', '--soft', 'fake_ancestor_sha'],), ''), | 285 ((['git', 'reset', '--soft', 'fake_ancestor_sha'],), ''), |
273 ((['git', 'commit', '-m', | 286 ((['git', 'commit', '-m', |
274 'Issue: 12345\n\nReview URL: https://codereview.example.com/12345'],), | 287 'Issue: 12345\n\n' |
| 288 'Review URL: https://codereview.example.com/12345'],), |
275 ''), | 289 ''), |
276 ((['git', 'svn', 'dcommit', '-C50', '--no-rebase', '--rmdir'],), | 290 ((['git', 'svn', 'dcommit', '-C50', '--no-rebase', '--rmdir'],), |
277 (('', None), 0)), | 291 (('', None), 0)), |
278 ((['git', 'checkout', '-q', 'working'],), ''), | 292 ((['git', 'checkout', '-q', 'working'],), ''), |
279 ((['git', 'branch', '-D', 'git-cl-commit'],), ''), | 293 ((['git', 'branch', '-D', 'git-cl-commit'],), ''), |
280 ] | 294 ] |
281 | 295 |
282 @staticmethod | 296 @staticmethod |
283 def _cmd_line(description, args, similarity, find_copies): | 297 def _cmd_line(description, args, similarity, find_copies): |
284 """Returns the upload command line passed to upload.RealMain().""" | 298 """Returns the upload command line passed to upload.RealMain().""" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 cmd_line = self._cmd_line(final_description, reviewers, similarity, | 341 cmd_line = self._cmd_line(final_description, reviewers, similarity, |
328 find_copies) | 342 find_copies) |
329 self.assertEquals(cmd_line, args) | 343 self.assertEquals(cmd_line, args) |
330 return 1, 2 | 344 return 1, 2 |
331 self.mock(git_cl.upload, 'RealMain', check_upload) | 345 self.mock(git_cl.upload, 'RealMain', check_upload) |
332 git_cl.main(['upload'] + upload_args) | 346 git_cl.main(['upload'] + upload_args) |
333 | 347 |
334 def test_no_reviewer(self): | 348 def test_no_reviewer(self): |
335 self._run_reviewer_test( | 349 self._run_reviewer_test( |
336 [], | 350 [], |
337 'desc\n\nBUG=\n', | 351 'desc\n\nBUG=', |
338 '# Blah blah comment.\ndesc\n\nBUG=\n', | 352 '# Blah blah comment.\ndesc\n\nBUG=', |
339 'desc\n\nBUG=\n', | 353 'desc\n\nBUG=', |
340 []) | 354 []) |
341 | 355 |
342 def test_keep_similarity(self): | 356 def test_keep_similarity(self): |
343 self._run_reviewer_test( | 357 self._run_reviewer_test( |
344 ['--similarity', '70'], | 358 ['--similarity', '70'], |
345 'desc\n\nBUG=\n', | 359 'desc\n\nBUG=', |
346 '# Blah blah comment.\ndesc\n\nBUG=\n', | 360 '# Blah blah comment.\ndesc\n\nBUG=', |
347 'desc\n\nBUG=\n', | 361 'desc\n\nBUG=', |
348 []) | 362 []) |
349 | 363 |
350 def test_keep_find_copies(self): | 364 def test_keep_find_copies(self): |
351 self._run_reviewer_test( | 365 self._run_reviewer_test( |
352 ['--no-find-copies'], | 366 ['--no-find-copies'], |
353 'desc\n\nBUG=\n', | 367 'desc\n\nBUG=', |
354 '# Blah blah comment.\ndesc\n\nBUG=\n', | 368 '# Blah blah comment.\ndesc\n\nBUG=\n', |
355 'desc\n\nBUG=\n', | 369 'desc\n\nBUG=', |
356 []) | 370 []) |
357 | 371 |
358 def test_reviewers_cmd_line(self): | 372 def test_reviewers_cmd_line(self): |
359 # Reviewer is passed as-is | 373 # Reviewer is passed as-is |
360 description = 'desc\n\nR=foo@example.com\nBUG=\n' | 374 description = 'desc\n\nR=foo@example.com\nBUG=' |
361 self._run_reviewer_test( | 375 self._run_reviewer_test( |
362 ['-r' 'foo@example.com'], | 376 ['-r' 'foo@example.com'], |
363 description, | 377 description, |
364 '\n%s\n' % description, | 378 '\n%s\n' % description, |
365 description, | 379 description, |
366 ['--reviewers', 'foo@example.com']) | 380 ['--reviewers=foo@example.com']) |
367 | 381 |
368 def test_reviewer_tbr_overriden(self): | 382 def test_reviewer_tbr_overriden(self): |
369 # Reviewer is overriden with TBR | 383 # Reviewer is overriden with TBR |
370 # Also verifies the regexp work without a trailing LF | 384 # Also verifies the regexp work without a trailing LF |
371 description = 'Foo Bar\nTBR=reviewer@example.com\n' | 385 description = 'Foo Bar\n\nTBR=reviewer@example.com' |
372 self._run_reviewer_test( | 386 self._run_reviewer_test( |
373 ['-r' 'foo@example.com'], | 387 ['-r' 'foo@example.com'], |
374 'desc\n\nR=foo@example.com\nBUG=\n', | 388 'desc\n\nR=foo@example.com\nBUG=', |
375 description.strip('\n'), | 389 description.strip('\n'), |
376 description, | 390 description, |
377 ['--reviewers', 'reviewer@example.com']) | 391 ['--reviewers=reviewer@example.com']) |
378 | 392 |
379 def test_reviewer_multiple(self): | 393 def test_reviewer_multiple(self): |
380 # Handles multiple R= or TBR= lines. | 394 # Handles multiple R= or TBR= lines. |
381 description = ( | 395 description = ( |
382 'Foo Bar\nTBR=reviewer@example.com\nBUG=\nR=another@example.com\n') | 396 'Foo Bar\nTBR=reviewer@example.com\nBUG=\nR=another@example.com') |
383 self._run_reviewer_test( | 397 self._run_reviewer_test( |
384 [], | 398 [], |
385 'desc\n\nBUG=\n', | 399 'desc\n\nBUG=', |
386 description, | 400 description, |
387 description, | 401 description, |
388 ['--reviewers', 'reviewer@example.com,another@example.com']) | 402 ['--reviewers=another@example.com,reviewer@example.com']) |
389 | 403 |
390 def test_reviewer_send_mail(self): | 404 def test_reviewer_send_mail(self): |
391 # --send-mail can be used without -r if R= is used | 405 # --send-mail can be used without -r if R= is used |
392 description = 'Foo Bar\nR=reviewer@example.com\n' | 406 description = 'Foo Bar\nR=reviewer@example.com' |
393 self._run_reviewer_test( | 407 self._run_reviewer_test( |
394 ['--send-mail'], | 408 ['--send-mail'], |
395 'desc\n\nBUG=\n', | 409 'desc\n\nBUG=', |
396 description.strip('\n'), | 410 description.strip('\n'), |
397 description, | 411 description, |
398 ['--reviewers', 'reviewer@example.com', '--send_mail']) | 412 ['--reviewers=reviewer@example.com', '--send_mail']) |
399 | 413 |
400 def test_reviewer_send_mail_no_rev(self): | 414 def test_reviewer_send_mail_no_rev(self): |
401 # Fails without a reviewer. | 415 # Fails without a reviewer. |
402 class FileMock(object): | 416 class FileMock(object): |
403 buf = StringIO.StringIO() | 417 buf = StringIO.StringIO() |
404 def write(self, content): | 418 def write(self, content): |
405 self.buf.write(content) | 419 self.buf.write(content) |
406 | 420 |
407 mock = FileMock() | 421 mock = FileMock() |
408 try: | 422 try: |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 'fake_ancestor_sha..HEAD'],), | 497 'fake_ancestor_sha..HEAD'],), |
484 description) | 498 description) |
485 ] | 499 ] |
486 calls += [ | 500 calls += [ |
487 ((['git', 'config', 'rietveld.cc'],), '') | 501 ((['git', 'config', 'rietveld.cc'],), '') |
488 ] | 502 ] |
489 receive_pack = '--receive-pack=git receive-pack ' | 503 receive_pack = '--receive-pack=git receive-pack ' |
490 receive_pack += '--cc=joe@example.com' # from watch list | 504 receive_pack += '--cc=joe@example.com' # from watch list |
491 if reviewers: | 505 if reviewers: |
492 receive_pack += ' ' | 506 receive_pack += ' ' |
493 receive_pack += ' '.join(['--reviewer=' + email for email in reviewers]) | 507 receive_pack += ' '.join( |
| 508 '--reviewer=' + email for email in sorted(reviewers)) |
494 receive_pack += '' | 509 receive_pack += '' |
495 calls += [ | 510 calls += [ |
496 ((['git', 'push', receive_pack, 'origin', 'HEAD:refs/for/master'],), | 511 ((['git', 'push', receive_pack, 'origin', 'HEAD:refs/for/master'],), |
497 '') | 512 '') |
498 ] | 513 ] |
499 return calls | 514 return calls |
500 | 515 |
501 def _run_gerrit_upload_test( | 516 def _run_gerrit_upload_test( |
502 self, | 517 self, |
503 upload_args, | 518 upload_args, |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 (('CC list:',), ''), | 598 (('CC list:',), ''), |
584 ((['git', 'config', 'rietveld.tree-status-url'],), ''), | 599 ((['git', 'config', 'rietveld.tree-status-url'],), ''), |
585 (('Tree status URL:',), ''), | 600 (('Tree status URL:',), ''), |
586 ((['git', 'config', 'rietveld.viewvc-url'],), ''), | 601 ((['git', 'config', 'rietveld.viewvc-url'],), ''), |
587 (('ViewVC URL:',), ''), | 602 (('ViewVC URL:',), ''), |
588 # DownloadHooks(True) | 603 # DownloadHooks(True) |
589 ((commit_msg_path, os.X_OK,), True), | 604 ((commit_msg_path, os.X_OK,), True), |
590 ] | 605 ] |
591 git_cl.main(['config']) | 606 git_cl.main(['config']) |
592 | 607 |
| 608 def test_update_reviewers(self): |
| 609 data = [ |
| 610 ('foo', [], 'foo'), |
| 611 ('foo', ['a@c'], 'foo\n\nR=a@c'), |
| 612 ('foo\nBUG=', ['a@c'], 'foo\nBUG=\nR=a@c'), |
| 613 ('foo\nR=xx\nTBR=yy\nR=bar', ['a@c'], 'foo\nTBR=a@c'), |
| 614 ('foo', ['a@c', 'b@c'], 'foo\n\nR=a@c, b@c'), |
| 615 ] |
| 616 for orig, reviewers, expected in data: |
| 617 obj = git_cl.ChangeDescription(orig) |
| 618 obj.update_reviewers(reviewers) |
| 619 self.assertEqual(expected, obj.description) |
| 620 |
593 | 621 |
594 if __name__ == '__main__': | 622 if __name__ == '__main__': |
| 623 git_cl.logging.basicConfig( |
| 624 level=git_cl.logging.DEBUG if '-v' in sys.argv else git_cl.logging.ERROR) |
595 unittest.main() | 625 unittest.main() |
OLD | NEW |