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 |