| 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 pending_manager.py.""" | 6 """Unit tests for pending_manager.py.""" |
| 7 | 7 |
| 8 import logging | 8 import logging |
| 9 import os | 9 import os |
| 10 import re | 10 import re |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 self.assertEquals(len(pc.queue.iterate()), 0) | 92 self.assertEquals(len(pc.queue.iterate()), 0) |
| 93 issue = 31337 | 93 issue = 31337 |
| 94 if pc.verifiers: | 94 if pc.verifiers: |
| 95 if success: | 95 if success: |
| 96 self.context.checkout.check_calls( | 96 self.context.checkout.check_calls( |
| 97 [ 'prepare(None)', | 97 [ 'prepare(None)', |
| 98 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],), | 98 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],), |
| 99 'prepare(None)', # Will sync to HEAD/124. | 99 'prepare(None)', # Will sync to HEAD/124. |
| 100 'apply_patch(%r)' % (self.context.rietveld.patchsets[1],), | 100 'apply_patch(%r)' % (self.context.rietveld.patchsets[1],), |
| 101 ( | 101 ( |
| 102 "commit(u'foo\\n\\n" | 102 "commit(u'foo\\n\\nR=rev@example.com\\n\\n" |
| 103 "Review URL: http://nowhere/%d', " | 103 "Review URL: http://nowhere/%d', " |
| 104 "u'author@example.com')") % issue]) | 104 "u'author@example.com')") % issue]) |
| 105 self.context.rietveld.check_calls( | 105 self.context.rietveld.check_calls( |
| 106 [ _try_comment(), | 106 [ _try_comment(), |
| 107 'close_issue(%d)' % issue, | 107 'close_issue(%d)' % issue, |
| 108 "update_description(%d, u'foo')" % issue, | 108 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % issue, |
| 109 "add_comment(%d, 'Change committed as 125')" % issue]) | 109 "add_comment(%d, 'Change committed as 125')" % issue]) |
| 110 else: | 110 else: |
| 111 self.context.checkout.check_calls( | 111 self.context.checkout.check_calls( |
| 112 [ 'prepare(None)', | 112 [ 'prepare(None)', |
| 113 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],)]) | 113 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],)]) |
| 114 self.context.rietveld.check_calls( | 114 self.context.rietveld.check_calls( |
| 115 [ _try_comment(), | 115 [ _try_comment(), |
| 116 "set_flag(%d, 1, 'commit', 'False')" % issue, | 116 "set_flag(%d, 1, 'commit', 'False')" % issue, |
| 117 "add_comment(%d, %r)" % (issue, pc.FAILED_NO_MESSAGE)]) | 117 "add_comment(%d, %r)" % (issue, pc.FAILED_NO_MESSAGE)]) |
| 118 else: | 118 else: |
| 119 if success: | 119 if success: |
| 120 self.context.checkout.check_calls( | 120 self.context.checkout.check_calls( |
| 121 self._prepare_apply_commit(0, issue)) | 121 self._prepare_apply_commit(0, issue)) |
| 122 self.context.rietveld.check_calls( | 122 self.context.rietveld.check_calls( |
| 123 [ _try_comment(), | 123 [ _try_comment(), |
| 124 'close_issue(%d)' % issue, | 124 'close_issue(%d)' % issue, |
| 125 "update_description(%d, u'foo')" % issue, | 125 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % issue, |
| 126 "add_comment(%d, 'Change committed as 125')" % issue]) | 126 "add_comment(%d, 'Change committed as 125')" % issue]) |
| 127 else: | 127 else: |
| 128 # checkout is never touched in that case. | 128 # checkout is never touched in that case. |
| 129 self.context.checkout.check_calls([]) | 129 self.context.checkout.check_calls([]) |
| 130 if defered: | 130 if defered: |
| 131 self.context.rietveld.check_calls( | 131 self.context.rietveld.check_calls( |
| 132 [ _try_comment(), | 132 [ _try_comment(), |
| 133 "set_flag(%d, 1, 'commit', 'False')" % issue, | 133 "set_flag(%d, 1, 'commit', 'False')" % issue, |
| 134 "add_comment(%d, %r)" % (issue, pc.FAILED_NO_MESSAGE)]) | 134 "add_comment(%d, %r)" % (issue, pc.FAILED_NO_MESSAGE)]) |
| 135 else: | 135 else: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 147 # Reverts any previous modification or checkout the tree if it was not | 147 # Reverts any previous modification or checkout the tree if it was not |
| 148 # present. | 148 # present. |
| 149 'prepare(None)', | 149 'prepare(None)', |
| 150 # Applies the requested PatchSet. | 150 # Applies the requested PatchSet. |
| 151 'apply_patch(%r)' % self.context.rietveld.patchsets[index], | 151 'apply_patch(%r)' % self.context.rietveld.patchsets[index], |
| 152 ] | 152 ] |
| 153 # Commits the patch. | 153 # Commits the patch. |
| 154 author_and_reviewer = '' | 154 author_and_reviewer = '' |
| 155 if server_hooks_missing: | 155 if server_hooks_missing: |
| 156 author_and_reviewer = ( | 156 author_and_reviewer = ( |
| 157 '\\n\\nR=rev@example.com\\n\\nAuthor: author@example.com') | 157 '\\n\\nAuthor: author@example.com') |
| 158 commit_message = ( | 158 commit_message = ( |
| 159 "commit(u'foo%s\\n\\n" | 159 "commit(u'foo\\n\\nR=rev@example.com%s\\n\\n" |
| 160 "Review URL: http://nowhere/%d', " | 160 "Review URL: http://nowhere/%d', " |
| 161 "u'author@example.com')") % (author_and_reviewer, issue) | 161 "u'author@example.com')") % (author_and_reviewer, issue) |
| 162 seq.append(commit_message) | 162 seq.append(commit_message) |
| 163 | 163 |
| 164 return seq | 164 return seq |
| 165 | 165 |
| 166 def testNoVerification(self): | 166 def testNoVerification(self): |
| 167 try: | 167 try: |
| 168 # Need at least one verification. | 168 # Need at least one verification. |
| 169 self._get_pc([], []) | 169 self._get_pc([], []) |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],)]) | 438 'apply_patch(%r)' % (self.context.rietveld.patchsets[0],)]) |
| 439 pc.update_status() | 439 pc.update_status() |
| 440 self.context.checkout.check_calls([]) | 440 self.context.checkout.check_calls([]) |
| 441 pc.scan_results() | 441 pc.scan_results() |
| 442 self.context.checkout.check_calls( | 442 self.context.checkout.check_calls( |
| 443 # Will sync to HEAD, 124. | 443 # Will sync to HEAD, 124. |
| 444 self._prepare_apply_commit(1, issue)) | 444 self._prepare_apply_commit(1, issue)) |
| 445 self.context.rietveld.check_calls( | 445 self.context.rietveld.check_calls( |
| 446 [ _try_comment(), | 446 [ _try_comment(), |
| 447 'close_issue(%d)' % issue, | 447 'close_issue(%d)' % issue, |
| 448 "update_description(%d, u'foo')" % issue, | 448 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % issue, |
| 449 "add_comment(%d, 'Change committed as 125')" % issue]) | 449 "add_comment(%d, 'Change committed as 125')" % issue]) |
| 450 self.context.status.check_names(['initial', 'why not', 'commit']) | 450 self.context.status.check_names(['initial', 'why not', 'commit']) |
| 451 | 451 |
| 452 def testCommitBurst(self): | 452 def testCommitBurst(self): |
| 453 issue = 31337 | 453 issue = 31337 |
| 454 pc = self._get_pc([fake.FakeVerifier(base.SUCCEEDED)], []) | 454 pc = self._get_pc([fake.FakeVerifier(base.SUCCEEDED)], []) |
| 455 self.assertEquals(4, pc.MAX_COMMIT_BURST) | 455 self.assertEquals(4, pc.MAX_COMMIT_BURST) |
| 456 timestamp = [1] | 456 timestamp = [1] |
| 457 self.mock(time, 'time', lambda: timestamp[-1]) | 457 self.mock(time, 'time', lambda: timestamp[-1]) |
| 458 for i in range(pc.MAX_COMMIT_BURST + 2): | 458 for i in range(pc.MAX_COMMIT_BURST + 2): |
| (...skipping 12 matching lines...) Expand all Loading... |
| 471 self._prepare_apply_commit(3, 3)) | 471 self._prepare_apply_commit(3, 3)) |
| 472 self.context.rietveld.check_calls( | 472 self.context.rietveld.check_calls( |
| 473 [ _try_comment(0), | 473 [ _try_comment(0), |
| 474 _try_comment(1), | 474 _try_comment(1), |
| 475 _try_comment(2), | 475 _try_comment(2), |
| 476 _try_comment(3), | 476 _try_comment(3), |
| 477 _try_comment(4), | 477 _try_comment(4), |
| 478 _try_comment(5), | 478 _try_comment(5), |
| 479 _try_comment(), | 479 _try_comment(), |
| 480 'close_issue(0)', | 480 'close_issue(0)', |
| 481 "update_description(0, u'foo')", | 481 "update_description(0, u'foo\\n\\nR=rev@example.com')", |
| 482 "add_comment(0, 'Change committed as 125')", | 482 "add_comment(0, 'Change committed as 125')", |
| 483 'close_issue(1)', | 483 'close_issue(1)', |
| 484 "update_description(1, u'foo')", | 484 "update_description(1, u'foo\\n\\nR=rev@example.com')", |
| 485 "add_comment(1, 'Change committed as 125')", | 485 "add_comment(1, 'Change committed as 125')", |
| 486 'close_issue(2)', | 486 'close_issue(2)', |
| 487 "update_description(2, u'foo')", | 487 "update_description(2, u'foo\\n\\nR=rev@example.com')", |
| 488 "add_comment(2, 'Change committed as 125')", | 488 "add_comment(2, 'Change committed as 125')", |
| 489 'close_issue(3)', | 489 'close_issue(3)', |
| 490 "update_description(3, u'foo')", | 490 "update_description(3, u'foo\\n\\nR=rev@example.com')", |
| 491 "add_comment(3, 'Change committed as 125')", | 491 "add_comment(3, 'Change committed as 125')", |
| 492 ]) | 492 ]) |
| 493 self.assertEquals(3, len(pc.queue.iterate())) | 493 self.assertEquals(3, len(pc.queue.iterate())) |
| 494 total = pc.MAX_COMMIT_BURST + 3 | 494 total = pc.MAX_COMMIT_BURST + 3 |
| 495 self.context.status.check_names(['initial'] * total + | 495 self.context.status.check_names(['initial'] * total + |
| 496 (['why not', 'commit'] * | 496 (['why not', 'commit'] * |
| 497 pc.MAX_COMMIT_BURST) + | 497 pc.MAX_COMMIT_BURST) + |
| 498 ['why not'] * 3) | 498 ['why not'] * 3) |
| 499 | 499 |
| 500 # Dry run. | 500 # Dry run. |
| 501 pc.scan_results() | 501 pc.scan_results() |
| 502 self.context.checkout.check_calls([]) | 502 self.context.checkout.check_calls([]) |
| 503 self.context.rietveld.check_calls([]) | 503 self.context.rietveld.check_calls([]) |
| 504 self.context.status.check_names(['why not'] * 3) | 504 self.context.status.check_names(['why not'] * 3) |
| 505 | 505 |
| 506 # Remove one item from the burst. | 506 # Remove one item from the burst. |
| 507 pc.recent_commit_timestamps.pop() | 507 pc.recent_commit_timestamps.pop() |
| 508 pc.scan_results() | 508 pc.scan_results() |
| 509 next_item = pc.MAX_COMMIT_BURST | 509 next_item = pc.MAX_COMMIT_BURST |
| 510 self.context.checkout.check_calls( | 510 self.context.checkout.check_calls( |
| 511 self._prepare_apply_commit(next_item, next_item)) | 511 self._prepare_apply_commit(next_item, next_item)) |
| 512 self.context.rietveld.check_calls( | 512 self.context.rietveld.check_calls( |
| 513 [ 'close_issue(%d)' % next_item, | 513 [ 'close_issue(%d)' % next_item, |
| 514 "update_description(%d, u'foo')" % next_item, | 514 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % next_item, |
| 515 "add_comment(%d, 'Change committed as 125')" % next_item, | 515 "add_comment(%d, 'Change committed as 125')" % next_item, |
| 516 ]) | 516 ]) |
| 517 self.context.status.check_names(['why not', 'commit'] + ['why not'] * 2) | 517 self.context.status.check_names(['why not', 'commit'] + ['why not'] * 2) |
| 518 # After a delay, must flush the queue. | 518 # After a delay, must flush the queue. |
| 519 timestamp.append(timestamp[-1] + pc.COMMIT_BURST_DELAY + 1) | 519 timestamp.append(timestamp[-1] + pc.COMMIT_BURST_DELAY + 1) |
| 520 pc.scan_results() | 520 pc.scan_results() |
| 521 self.context.checkout.check_calls( | 521 self.context.checkout.check_calls( |
| 522 self._prepare_apply_commit(next_item + 1, next_item + 1) + | 522 self._prepare_apply_commit(next_item + 1, next_item + 1) + |
| 523 self._prepare_apply_commit(next_item + 2, issue)) | 523 self._prepare_apply_commit(next_item + 2, issue)) |
| 524 self.context.rietveld.check_calls( | 524 self.context.rietveld.check_calls( |
| 525 [ 'close_issue(%d)' % (next_item + 1), | 525 [ 'close_issue(%d)' % (next_item + 1), |
| 526 "update_description(%d, u'foo')" % (next_item + 1), | 526 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % |
| 527 (next_item + 1), |
| 527 "add_comment(%d, 'Change committed as 125')" % (next_item + 1), | 528 "add_comment(%d, 'Change committed as 125')" % (next_item + 1), |
| 528 'close_issue(%d)' % issue, | 529 'close_issue(%d)' % issue, |
| 529 "update_description(%d, u'foo')" % issue, | 530 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % issue, |
| 530 "add_comment(%d, 'Change committed as 125')" % issue]) | 531 "add_comment(%d, 'Change committed as 125')" % issue]) |
| 531 self.context.status.check_names(['why not', 'commit'] * 2) | 532 self.context.status.check_names(['why not', 'commit'] * 2) |
| 532 | 533 |
| 533 def testIgnored(self): | 534 def testIgnored(self): |
| 534 issue = 31337 | 535 issue = 31337 |
| 535 verifiers = [ | 536 verifiers = [ |
| 536 project_base.ProjectBaseUrlVerifier( | 537 project_base.ProjectBaseUrlVerifier( |
| 537 [r'^%s(.*)$' % re.escape(r'http://example.com/')]), | 538 [r'^%s(.*)$' % re.escape(r'http://example.com/')]), |
| 538 ] | 539 ] |
| 539 pc = self._get_pc(verifiers, []) | 540 pc = self._get_pc(verifiers, []) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 555 self.context.server_hooks_missing = True | 556 self.context.server_hooks_missing = True |
| 556 pc = self._get_pc(verifiers, []) | 557 pc = self._get_pc(verifiers, []) |
| 557 pc.context.rietveld.issues[issue]['base_url'] = 'http://example.com/' | 558 pc.context.rietveld.issues[issue]['base_url'] = 'http://example.com/' |
| 558 pc.look_for_new_pending_commit() | 559 pc.look_for_new_pending_commit() |
| 559 pc.process_new_pending_commit() | 560 pc.process_new_pending_commit() |
| 560 pc.update_status() | 561 pc.update_status() |
| 561 pc.scan_results() | 562 pc.scan_results() |
| 562 self.context.rietveld.check_calls( | 563 self.context.rietveld.check_calls( |
| 563 [ _try_comment(), | 564 [ _try_comment(), |
| 564 'close_issue(%d)' % issue, | 565 'close_issue(%d)' % issue, |
| 565 "update_description(%d, u'foo')" % issue, | 566 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % issue, |
| 566 "add_comment(%d, 'Change committed as 125')" % issue]) | 567 "add_comment(%d, 'Change committed as 125')" % issue]) |
| 567 self.context.status.check_names(['initial', 'why not', 'commit']) | 568 self.context.status.check_names(['initial', 'why not', 'commit']) |
| 568 self.context.checkout.check_calls( | 569 self.context.checkout.check_calls( |
| 569 self._prepare_apply_commit(0, issue, server_hooks_missing=True)) | 570 self._prepare_apply_commit(0, issue, server_hooks_missing=True)) |
| 570 | 571 |
| 571 def testDisapeared(self): | 572 def testDisapeared(self): |
| 572 issue = 31337 | 573 issue = 31337 |
| 573 verifiers = [ | 574 verifiers = [ |
| 574 project_base.ProjectBaseUrlVerifier( | 575 project_base.ProjectBaseUrlVerifier( |
| 575 [r'^%s(.*)$' % re.escape(r'http://example.com/')]), | 576 [r'^%s(.*)$' % re.escape(r'http://example.com/')]), |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 self.assertEquals(1, len(pc.queue.iterate())) | 636 self.assertEquals(1, len(pc.queue.iterate())) |
| 636 pc.process_new_pending_commit() | 637 pc.process_new_pending_commit() |
| 637 self.assertEquals(1, len(pc.queue.iterate())) | 638 self.assertEquals(1, len(pc.queue.iterate())) |
| 638 pc.update_status() | 639 pc.update_status() |
| 639 self.assertEquals(1, len(pc.queue.iterate())) | 640 self.assertEquals(1, len(pc.queue.iterate())) |
| 640 pc.scan_results() | 641 pc.scan_results() |
| 641 self.assertEquals(0, len(pc.queue.iterate())) | 642 self.assertEquals(0, len(pc.queue.iterate())) |
| 642 self.context.rietveld.check_calls( | 643 self.context.rietveld.check_calls( |
| 643 [ _try_comment(), | 644 [ _try_comment(), |
| 644 'close_issue(%d)' % issue, | 645 'close_issue(%d)' % issue, |
| 645 "update_description(%d, u'foo')" % issue, | 646 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % issue, |
| 646 "add_comment(%d, 'Change committed as 125')" % issue]) | 647 "add_comment(%d, 'Change committed as 125')" % issue]) |
| 647 self.context.status.check_names(['initial', 'why not', 'commit']) | 648 self.context.status.check_names(['initial', 'why not', 'commit']) |
| 648 self.context.checkout.check_calls( | 649 self.context.checkout.check_calls( |
| 649 self._prepare_apply_commit(0, issue)) | 650 self._prepare_apply_commit(0, issue)) |
| 650 | 651 |
| 651 def testDriveBy(self): | 652 def testDriveBy(self): |
| 652 issue = 31337 | 653 issue = 31337 |
| 653 pc = self._get_pc_reviewer() | 654 pc = self._get_pc_reviewer() |
| 654 self._approve() | 655 self._approve() |
| 655 pc.look_for_new_pending_commit() | 656 pc.look_for_new_pending_commit() |
| (...skipping 19 matching lines...) Expand all Loading... |
| 675 pc.update_status() | 676 pc.update_status() |
| 676 # He's nice, he left a LGTM. | 677 # He's nice, he left a LGTM. |
| 677 i = self.context.rietveld.issues[issue] | 678 i = self.context.rietveld.issues[issue] |
| 678 i['reviewers'] = i['reviewers'] + ['nice@dude.org'] | 679 i['reviewers'] = i['reviewers'] + ['nice@dude.org'] |
| 679 self._approve('nice@dude.org') | 680 self._approve('nice@dude.org') |
| 680 pc.scan_results() | 681 pc.scan_results() |
| 681 self.assertEquals(0, len(pc.queue.iterate())) | 682 self.assertEquals(0, len(pc.queue.iterate())) |
| 682 self.context.rietveld.check_calls( | 683 self.context.rietveld.check_calls( |
| 683 [ _try_comment(), | 684 [ _try_comment(), |
| 684 'close_issue(%d)' % issue, | 685 'close_issue(%d)' % issue, |
| 685 "update_description(%d, u'foo')" % issue, | 686 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % issue, |
| 686 "add_comment(%d, 'Change committed as 125')" % issue]) | 687 "add_comment(%d, 'Change committed as 125')" % issue]) |
| 687 self.context.status.check_names(['initial', 'why not', 'commit']) | 688 self.context.status.check_names(['initial', 'why not', 'commit']) |
| 688 self.context.checkout.check_calls( | 689 self.context.checkout.check_calls( |
| 689 self._prepare_apply_commit(0, issue)) | 690 self._prepare_apply_commit(0, issue)) |
| 690 | 691 |
| 691 def testWhyNotUpdates(self): | 692 def testWhyNotUpdates(self): |
| 692 issue = 31337 | 693 issue = 31337 |
| 693 fake1_change = 1 | 694 fake1_change = 1 |
| 694 fake1 = fake.DeferredFakeVerifier(base.SUCCEEDED, fake1_change) | 695 fake1 = fake.DeferredFakeVerifier(base.SUCCEEDED, fake1_change) |
| 695 fake1.name = 'fake1' | 696 fake1.name = 'fake1' |
| (...skipping 11 matching lines...) Expand all Loading... |
| 707 for i in range(fake2_change * 2): | 708 for i in range(fake2_change * 2): |
| 708 expected = ['why not'] if fake1_change == i or fake2_change == i else [] | 709 expected = ['why not'] if fake1_change == i or fake2_change == i else [] |
| 709 pc.update_status() | 710 pc.update_status() |
| 710 self.context.status.check_names(expected) | 711 self.context.status.check_names(expected) |
| 711 | 712 |
| 712 pc.scan_results() | 713 pc.scan_results() |
| 713 | 714 |
| 714 self.context.rietveld.check_calls( | 715 self.context.rietveld.check_calls( |
| 715 [_try_comment(), | 716 [_try_comment(), |
| 716 'close_issue(%d)' % issue, | 717 'close_issue(%d)' % issue, |
| 717 "update_description(%d, u'foo')" % issue, | 718 "update_description(%d, u'foo\\n\\nR=rev@example.com')" % issue, |
| 718 "add_comment(%d, 'Change committed as 125')" % issue]) | 719 "add_comment(%d, 'Change committed as 125')" % issue]) |
| 719 self.context.status.check_names(['why not', 'commit']) | 720 self.context.status.check_names(['why not', 'commit']) |
| 720 self.context.checkout.check_calls( | 721 self.context.checkout.check_calls( |
| 721 self._prepare_apply_commit(0, issue)) | 722 self._prepare_apply_commit(0, issue)) |
| 722 | 723 |
| 723 | 724 |
| 724 if __name__ == '__main__': | 725 if __name__ == '__main__': |
| 725 logging.basicConfig( | 726 logging.basicConfig( |
| 726 level=[logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG][ | 727 level=[logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG][ |
| 727 min(sys.argv.count('-v'), 3)], | 728 min(sys.argv.count('-v'), 3)], |
| 728 format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s') | 729 format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s') |
| 729 unittest.main() | 730 unittest.main() |
| OLD | NEW |