| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 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 """Smoke tests for gclient.py. | 6 """Smoke tests for gclient.py. |
| 7 | 7 |
| 8 Shell out 'gclient' and run basic conformance tests. | 8 Shell out 'gclient' and run basic conformance tests. |
| 9 | 9 |
| 10 This test assumes GClientSmokeBase.URL_BASE is valid. | 10 This test assumes GClientSmokeBase.URL_BASE is valid. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 cmd = cmd_base + cmd | 42 cmd = cmd_base + cmd |
| 43 process = subprocess.Popen(cmd, cwd=cwd, env=self.env, | 43 process = subprocess.Popen(cmd, cwd=cwd, env=self.env, |
| 44 stdout=subprocess.PIPE, stderr=subprocess.PIPE, | 44 stdout=subprocess.PIPE, stderr=subprocess.PIPE, |
| 45 shell=sys.platform.startswith('win')) | 45 shell=sys.platform.startswith('win')) |
| 46 (stdout, stderr) = process.communicate() | 46 (stdout, stderr) = process.communicate() |
| 47 logging.debug("XXX: %s\n%s\nXXX" % (' '.join(cmd), stdout)) | 47 logging.debug("XXX: %s\n%s\nXXX" % (' '.join(cmd), stdout)) |
| 48 logging.debug("YYY: %s\n%s\nYYY" % (' '.join(cmd), stderr)) | 48 logging.debug("YYY: %s\n%s\nYYY" % (' '.join(cmd), stderr)) |
| 49 return (stdout.replace('\r\n', '\n'), stderr.replace('\r\n', '\n'), | 49 return (stdout.replace('\r\n', '\n'), stderr.replace('\r\n', '\n'), |
| 50 process.returncode) | 50 process.returncode) |
| 51 | 51 |
| 52 def parseGclient(self, cmd, items): | 52 def parseGclient(self, cmd, items, expected_stderr=''): |
| 53 """Parse gclient's output to make it easier to test.""" | 53 """Parse gclient's output to make it easier to test.""" |
| 54 (stdout, stderr, returncode) = self.gclient(cmd) | 54 (stdout, stderr, returncode) = self.gclient(cmd) |
| 55 self.checkString('', stderr) | 55 self.checkString(expected_stderr, stderr) |
| 56 self.assertEquals(0, returncode) | 56 self.assertEquals(0, returncode) |
| 57 return self.checkBlock(stdout, items) | 57 return self.checkBlock(stdout, items) |
| 58 | 58 |
| 59 def splitBlock(self, stdout): | 59 def splitBlock(self, stdout): |
| 60 """Split gclient's output into logical execution blocks. | 60 """Split gclient's output into logical execution blocks. |
| 61 ___ running 'foo' at '/bar' | 61 ___ running 'foo' at '/bar' |
| 62 (...) | 62 (...) |
| 63 ___ running 'baz' at '/bar' | 63 ___ running 'baz' at '/bar' |
| 64 (...) | 64 (...) |
| 65 | 65 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 96 results = self.splitBlock(stdout) | 96 results = self.splitBlock(stdout) |
| 97 for i in xrange(min(len(results), len(items))): | 97 for i in xrange(min(len(results), len(items))): |
| 98 if isinstance(items[i], (list, tuple)): | 98 if isinstance(items[i], (list, tuple)): |
| 99 verb = items[i][0] | 99 verb = items[i][0] |
| 100 path = items[i][1] | 100 path = items[i][1] |
| 101 else: | 101 else: |
| 102 verb = items[i] | 102 verb = items[i] |
| 103 path = self.root_dir | 103 path = self.root_dir |
| 104 self.checkString(results[i][0][0], verb, (i, results[i][0][0], verb)) | 104 self.checkString(results[i][0][0], verb, (i, results[i][0][0], verb)) |
| 105 self.checkString(results[i][0][2], path, (i, results[i][0][2], path)) | 105 self.checkString(results[i][0][2], path, (i, results[i][0][2], path)) |
| 106 self.assertEquals(len(results), len(items), (stdout, items)) | 106 self.assertEquals(len(results), len(items), (stdout, items, len(results))) |
| 107 return results | 107 return results |
| 108 | 108 |
| 109 def svnBlockCleanup(self, out): | 109 def svnBlockCleanup(self, out): |
| 110 """Work around svn status difference between svn 1.5 and svn 1.6 | 110 """Work around svn status difference between svn 1.5 and svn 1.6 |
| 111 I don't know why but on Windows they are reversed. So sorts the items.""" | 111 I don't know why but on Windows they are reversed. So sorts the items.""" |
| 112 for i in xrange(len(out)): | 112 for i in xrange(len(out)): |
| 113 if len(out[i]) < 2: | 113 if len(out[i]) < 2: |
| 114 continue | 114 continue |
| 115 out[i] = [out[i][0]] + sorted([x[1:].strip() for x in out[i][1:]]) | 115 out[i] = [out[i][0]] + sorted([x[1:].strip() for x in out[i][1:]]) |
| 116 return out | 116 return out |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 def setUp(self): | 466 def setUp(self): |
| 467 GClientSmokeBase.setUp(self) | 467 GClientSmokeBase.setUp(self) |
| 468 self.enabled = self.FAKE_REPOS.setUpGIT() | 468 self.enabled = self.FAKE_REPOS.setUpGIT() |
| 469 | 469 |
| 470 def testSync(self): | 470 def testSync(self): |
| 471 if not self.enabled: | 471 if not self.enabled: |
| 472 return | 472 return |
| 473 # TODO(maruel): safesync. | 473 # TODO(maruel): safesync. |
| 474 self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) | 474 self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) |
| 475 # Test unversioned checkout. | 475 # Test unversioned checkout. |
| 476 results = self.gclient(['sync', '--deps', 'mac']) | 476 self.parseGclient(['sync', '--deps', 'mac'], |
| 477 self.checkBlock(results[0], ['running', 'running']) | 477 ['running', 'running', 'running', 'running', 'running']) |
| 478 # TODO(maruel): http://crosbug.com/3582 hooks run even if not matching, must | 478 # TODO(maruel): http://crosbug.com/3582 hooks run even if not matching, must |
| 479 # add sync parsing to get the list of updated files. | 479 # add sync parsing to get the list of updated files. |
| 480 #self.assertTrue(results[1].startswith('Switched to a new branch \'')) | |
| 481 self.assertEquals(0, results[2]) | |
| 482 tree = self.mangle_git_tree(('repo_1@2', 'src'), | 480 tree = self.mangle_git_tree(('repo_1@2', 'src'), |
| 483 ('repo_2@1', 'src/repo2'), | 481 ('repo_2@1', 'src/repo2'), |
| 484 ('repo_3@2', 'src/repo2/repo_renamed')) | 482 ('repo_3@2', 'src/repo2/repo_renamed')) |
| 485 tree['src/git_hooked1'] = 'git_hooked1' | 483 tree['src/git_hooked1'] = 'git_hooked1' |
| 486 tree['src/git_hooked2'] = 'git_hooked2' | 484 tree['src/git_hooked2'] = 'git_hooked2' |
| 487 self.assertTree(tree) | 485 self.assertTree(tree) |
| 488 | 486 |
| 489 # Manually remove git_hooked1 before synching to make sure it's not | 487 # Manually remove git_hooked1 before synching to make sure it's not |
| 490 # recreated. | 488 # recreated. |
| 491 os.remove(join(self.root_dir, 'src', 'git_hooked1')) | 489 os.remove(join(self.root_dir, 'src', 'git_hooked1')) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 518 ('repo_4@2', 'src/repo4')) | 516 ('repo_4@2', 'src/repo4')) |
| 519 tree['src/git_hooked1'] = 'git_hooked1' | 517 tree['src/git_hooked1'] = 'git_hooked1' |
| 520 tree['src/git_hooked2'] = 'git_hooked2' | 518 tree['src/git_hooked2'] = 'git_hooked2' |
| 521 self.assertTree(tree) | 519 self.assertTree(tree) |
| 522 | 520 |
| 523 def testSyncIgnoredSolutionName(self): | 521 def testSyncIgnoredSolutionName(self): |
| 524 """TODO(maruel): This will become an error soon.""" | 522 """TODO(maruel): This will become an error soon.""" |
| 525 if not self.enabled: | 523 if not self.enabled: |
| 526 return | 524 return |
| 527 self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) | 525 self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) |
| 528 results = self.gclient(['sync', '--deps', 'mac', '--revision', | 526 self.parseGclient( |
| 529 'invalid@' + self.githash('repo_1', 1)]) | 527 ['sync', '--deps', 'mac', |
| 530 self.checkBlock(results[0], ['running', 'running']) | 528 '--revision', 'invalid@' + self.githash('repo_1', 1)], |
| 531 # TODO(maruel): git shouldn't output to stderr... | 529 ['running', 'running', 'running', 'running', 'running'], |
| 532 self.checkString('Please fix your script, having invalid --revision flags ' | 530 'Please fix your script, having invalid --revision flags ' |
| 533 'will soon considered an error.\n', | 531 'will soon considered an error.\n') |
| 534 results[1]) | |
| 535 #self.checkString('Please fix your script, having invalid --revision flags ' | |
| 536 # 'will soon considered an error.\nSwitched to a new branch \'%s\'\n' % | |
| 537 # self.githash('repo_2', 1)[:7], | |
| 538 # results[1]) | |
| 539 self.assertEquals(0, results[2]) | |
| 540 tree = self.mangle_git_tree(('repo_1@2', 'src'), | 532 tree = self.mangle_git_tree(('repo_1@2', 'src'), |
| 541 ('repo_2@1', 'src/repo2'), | 533 ('repo_2@1', 'src/repo2'), |
| 542 ('repo_3@2', 'src/repo2/repo_renamed')) | 534 ('repo_3@2', 'src/repo2/repo_renamed')) |
| 543 tree['src/git_hooked1'] = 'git_hooked1' | 535 tree['src/git_hooked1'] = 'git_hooked1' |
| 544 tree['src/git_hooked2'] = 'git_hooked2' | 536 tree['src/git_hooked2'] = 'git_hooked2' |
| 545 self.assertTree(tree) | 537 self.assertTree(tree) |
| 546 | 538 |
| 547 def testSyncNoSolutionName(self): | 539 def testSyncNoSolutionName(self): |
| 548 if not self.enabled: | 540 if not self.enabled: |
| 549 return | 541 return |
| 550 # When no solution name is provided, gclient uses the first solution listed. | 542 # When no solution name is provided, gclient uses the first solution listed. |
| 551 self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) | 543 self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) |
| 552 results = self.gclient(['sync', '--deps', 'mac', | 544 self.parseGclient(['sync', '--deps', 'mac', |
| 553 '--revision', self.githash('repo_1', 1)]) | 545 '--revision', self.githash('repo_1', 1)], |
| 554 self.checkBlock(results[0], []) | 546 ['running', 'running', 'running', 'running']) |
| 555 # TODO(maruel): git shouldn't output to stderr... | |
| 556 #self.checkString('Switched to a new branch \'%s\'\n' | |
| 557 # % self.githash('repo_1', 1), results[1]) | |
| 558 self.checkString('', results[1]) | |
| 559 self.assertEquals(0, results[2]) | |
| 560 tree = self.mangle_git_tree(('repo_1@1', 'src'), | 547 tree = self.mangle_git_tree(('repo_1@1', 'src'), |
| 561 ('repo_2@2', 'src/repo2'), | 548 ('repo_2@2', 'src/repo2'), |
| 562 ('repo_3@1', 'src/repo2/repo3'), | 549 ('repo_3@1', 'src/repo2/repo3'), |
| 563 ('repo_4@2', 'src/repo4')) | 550 ('repo_4@2', 'src/repo4')) |
| 564 self.assertTree(tree) | 551 self.assertTree(tree) |
| 565 | 552 |
| 566 def testRevertAndStatus(self): | 553 def testRevertAndStatus(self): |
| 567 """TODO(maruel): Remove this line once this test is fixed.""" | 554 """TODO(maruel): Remove this line once this test is fixed.""" |
| 568 if not self.enabled: | 555 if not self.enabled: |
| 569 return | 556 return |
| 570 self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) | 557 self.gclient(['config', self.git_base + 'repo_1', '--name', 'src']) |
| 571 # Tested in testSync. | 558 # Tested in testSync. |
| 572 self.gclient(['sync', '--deps', 'mac']) | 559 self.gclient(['sync', '--deps', 'mac']) |
| 573 write(join(self.root_dir, 'src', 'repo2', 'hi'), 'Hey!') | 560 write(join(self.root_dir, 'src', 'repo2', 'hi'), 'Hey!') |
| 574 | 561 |
| 575 results = self.gclient(['status', '--deps', 'mac']) | 562 out = self.parseGclient(['status', '--deps', 'mac'], []) |
| 576 out = results[0].splitlines(False) | |
| 577 # TODO(maruel): http://crosbug.com/3584 It should output the unversioned | 563 # TODO(maruel): http://crosbug.com/3584 It should output the unversioned |
| 578 # files. | 564 # files. |
| 579 self.assertEquals(0, len(out)) | 565 self.assertEquals(0, len(out)) |
| 580 | 566 |
| 581 # Revert implies --force implies running hooks without looking at pattern | 567 # Revert implies --force implies running hooks without looking at pattern |
| 582 # matching. | 568 # matching. |
| 583 results = self.gclient(['revert', '--deps', 'mac']) | 569 results = self.gclient(['revert', '--deps', 'mac']) |
| 584 out = results[0].splitlines(False) | 570 out = results[0].splitlines(False) |
| 585 # TODO(maruel): http://crosbug.com/3583 It just runs the hooks right now. | 571 # TODO(maruel): http://crosbug.com/3583 It just runs the hooks right now. |
| 586 self.assertEquals(7, len(out)) | 572 self.assertEquals(13, len(out)) |
| 587 self.checkString('', results[1]) | 573 self.checkString('', results[1]) |
| 588 self.assertEquals(0, results[2]) | 574 self.assertEquals(0, results[2]) |
| 589 tree = self.mangle_git_tree(('repo_1@2', 'src'), | 575 tree = self.mangle_git_tree(('repo_1@2', 'src'), |
| 590 ('repo_2@1', 'src/repo2'), | 576 ('repo_2@1', 'src/repo2'), |
| 591 ('repo_3@2', 'src/repo2/repo_renamed')) | 577 ('repo_3@2', 'src/repo2/repo_renamed')) |
| 592 # TODO(maruel): http://crosbug.com/3583 This file should have been removed. | 578 # TODO(maruel): http://crosbug.com/3583 This file should have been removed. |
| 593 tree[join('src', 'repo2', 'hi')] = 'Hey!' | 579 tree[join('src', 'repo2', 'hi')] = 'Hey!' |
| 594 tree['src/git_hooked1'] = 'git_hooked1' | 580 tree['src/git_hooked1'] = 'git_hooked1' |
| 595 tree['src/git_hooked2'] = 'git_hooked2' | 581 tree['src/git_hooked2'] = 'git_hooked2' |
| 596 self.assertTree(tree) | 582 self.assertTree(tree) |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 | 650 |
| 665 def testMultiSolutions(self): | 651 def testMultiSolutions(self): |
| 666 if not self.enabled: | 652 if not self.enabled: |
| 667 return | 653 return |
| 668 self.gclient(['config', '--spec', | 654 self.gclient(['config', '--spec', |
| 669 'solutions=[' | 655 'solutions=[' |
| 670 '{"name": "src",' | 656 '{"name": "src",' |
| 671 ' "url": "' + self.svn_base + 'trunk/src/"},' | 657 ' "url": "' + self.svn_base + 'trunk/src/"},' |
| 672 '{"name": "src-git",' | 658 '{"name": "src-git",' |
| 673 '"url": "' + self.git_base + 'repo_1"}]']) | 659 '"url": "' + self.git_base + 'repo_1"}]']) |
| 674 results = self.gclient(['sync', '--deps', 'mac']) | 660 self.parseGclient(['sync', '--deps', 'mac'], |
| 675 # 3x svn checkout, 3x run hooks | 661 ['running', 'running', 'running', |
| 676 self.checkBlock(results[0], | 662 # This is due to the way svn update is called for a single |
| 677 ['running', 'running', | 663 # file when File() is used in a DEPS file. |
| 678 # This is due to the way svn update is called for a single | 664 ('running', self.root_dir + '/src/file/other'), |
| 679 # file when File() is used in a DEPS file. | 665 'running', 'running', 'running', 'running', 'running', 'running', |
| 680 ('running', self.root_dir + '/src/file/other'), | 666 'running', 'running']) |
| 681 'running', 'running', 'running', 'running', 'running', | |
| 682 'running']) | |
| 683 # TODO(maruel): Something's wrong here. git outputs to stderr 'Switched to | |
| 684 # new branch \'hash\''. | |
| 685 #self.checkString('', results[1]) | |
| 686 self.assertEquals(0, results[2]) | |
| 687 tree = self.mangle_git_tree(('repo_1@2', 'src-git'), | 667 tree = self.mangle_git_tree(('repo_1@2', 'src-git'), |
| 688 ('repo_2@1', 'src/repo2'), | 668 ('repo_2@1', 'src/repo2'), |
| 689 ('repo_3@2', 'src/repo2/repo_renamed')) | 669 ('repo_3@2', 'src/repo2/repo_renamed')) |
| 690 tree.update(self.mangle_svn_tree( | 670 tree.update(self.mangle_svn_tree( |
| 691 ('trunk/src@2', 'src'), | 671 ('trunk/src@2', 'src'), |
| 692 ('trunk/third_party/foo@1', 'src/third_party/foo'), | 672 ('trunk/third_party/foo@1', 'src/third_party/foo'), |
| 693 ('trunk/other@2', 'src/other'))) | 673 ('trunk/other@2', 'src/other'))) |
| 694 tree['src/file/other/DEPS'] = ( | 674 tree['src/file/other/DEPS'] = ( |
| 695 self.FAKE_REPOS.svn_revs[2]['trunk/other/DEPS']) | 675 self.FAKE_REPOS.svn_revs[2]['trunk/other/DEPS']) |
| 696 tree['src/git_hooked1'] = 'git_hooked1' | 676 tree['src/git_hooked1'] = 'git_hooked1' |
| 697 tree['src/git_hooked2'] = 'git_hooked2' | 677 tree['src/git_hooked2'] = 'git_hooked2' |
| 698 tree['src/svn_hooked1'] = 'svn_hooked1' | 678 tree['src/svn_hooked1'] = 'svn_hooked1' |
| 699 self.assertTree(tree) | 679 self.assertTree(tree) |
| 700 | 680 |
| 701 def testMultiSolutionsMultiRev(self): | 681 def testMultiSolutionsMultiRev(self): |
| 702 if not self.enabled: | 682 if not self.enabled: |
| 703 return | 683 return |
| 704 self.gclient(['config', '--spec', | 684 self.gclient(['config', '--spec', |
| 705 'solutions=[' | 685 'solutions=[' |
| 706 '{"name": "src",' | 686 '{"name": "src",' |
| 707 ' "url": "' + self.svn_base + 'trunk/src/"},' | 687 ' "url": "' + self.svn_base + 'trunk/src/"},' |
| 708 '{"name": "src-git",' | 688 '{"name": "src-git",' |
| 709 '"url": "' + self.git_base + 'repo_1"}]']) | 689 '"url": "' + self.git_base + 'repo_1"}]']) |
| 710 results = self.gclient(['sync', '--deps', 'mac', '--revision', '1', | 690 self.parseGclient( |
| 711 '-r', 'src-git@' + self.githash('repo_1', 1)]) | 691 ['sync', '--deps', 'mac', '--revision', '1', |
| 712 self.checkBlock(results[0], ['running', 'running', 'running', 'running']) | 692 '-r', 'src-git@' + self.githash('repo_1', 1)], |
| 713 # TODO(maruel): Something's wrong here. git outputs to stderr 'Switched to | 693 ['running', 'running', 'running', 'running', |
| 714 # new branch \'hash\''. | 694 'running', 'running', 'running', 'running']) |
| 715 #self.checkString('', results[1]) | |
| 716 self.assertEquals(0, results[2]) | |
| 717 tree = self.mangle_git_tree(('repo_1@1', 'src-git'), | 695 tree = self.mangle_git_tree(('repo_1@1', 'src-git'), |
| 718 ('repo_2@2', 'src/repo2'), | 696 ('repo_2@2', 'src/repo2'), |
| 719 ('repo_3@1', 'src/repo2/repo3'), | 697 ('repo_3@1', 'src/repo2/repo3'), |
| 720 ('repo_4@2', 'src/repo4')) | 698 ('repo_4@2', 'src/repo4')) |
| 721 tree.update(self.mangle_svn_tree( | 699 tree.update(self.mangle_svn_tree( |
| 722 ('trunk/src@1', 'src'), | 700 ('trunk/src@1', 'src'), |
| 723 ('trunk/third_party/foo@2', 'src/third_party/fpp'), | 701 ('trunk/third_party/foo@2', 'src/third_party/fpp'), |
| 724 ('trunk/other@1', 'src/other'), | 702 ('trunk/other@1', 'src/other'), |
| 725 ('trunk/third_party/foo@2', 'src/third_party/prout'))) | 703 ('trunk/third_party/foo@2', 'src/third_party/prout'))) |
| 726 self.assertTree(tree) | 704 self.assertTree(tree) |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 if __name__ == '__main__': | 857 if __name__ == '__main__': |
| 880 if '-c' in sys.argv: | 858 if '-c' in sys.argv: |
| 881 COVERAGE = True | 859 COVERAGE = True |
| 882 sys.argv.remove('-c') | 860 sys.argv.remove('-c') |
| 883 if os.path.exists('.coverage'): | 861 if os.path.exists('.coverage'): |
| 884 os.remove('.coverage') | 862 os.remove('.coverage') |
| 885 os.environ['COVERAGE_FILE'] = os.path.join( | 863 os.environ['COVERAGE_FILE'] = os.path.join( |
| 886 os.path.dirname(os.path.dirname(os.path.abspath(__file__))), | 864 os.path.dirname(os.path.dirname(os.path.abspath(__file__))), |
| 887 '.coverage') | 865 '.coverage') |
| 888 unittest.main() | 866 unittest.main() |
| OLD | NEW |