Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: tests/checkout_test.py

Issue 1158043003: Remove most svn related testing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Fix typo in doc Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « testing_support/super_mox.py ('k') | tests/gcl_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 checkout.py.""" 6 """Unit tests for checkout.py."""
7 7
8 import logging 8 import logging
9 import os 9 import os
10 import shutil 10 import shutil
(...skipping 16 matching lines...) Expand all
27 DEBUGGING = False 27 DEBUGGING = False
28 28
29 # A patch that will fail to apply. 29 # A patch that will fail to apply.
30 BAD_PATCH = ''.join( 30 BAD_PATCH = ''.join(
31 [l for l in GIT.PATCH.splitlines(True) if l.strip() != 'e']) 31 [l for l in GIT.PATCH.splitlines(True) if l.strip() != 'e'])
32 32
33 33
34 class FakeRepos(fake_repos.FakeReposBase): 34 class FakeRepos(fake_repos.FakeReposBase):
35 TEST_GIT_REPO = 'repo_1' 35 TEST_GIT_REPO = 'repo_1'
36 36
37 def populateSvn(self):
38 """Creates a few revisions of changes files."""
39 subprocess2.check_call(
40 ['svn', 'checkout', self.svn_base, self.svn_checkout, '-q',
41 '--non-interactive', '--no-auth-cache',
42 '--username', self.USERS[0][0], '--password', self.USERS[0][1]])
43 assert os.path.isdir(os.path.join(self.svn_checkout, '.svn'))
44 self._commit_svn(self._svn_tree_1())
45 self._commit_svn(self._svn_tree_2())
46
47 def populateGit(self): 37 def populateGit(self):
48 """Creates a few revisions of changes files.""" 38 """Creates a few revisions of changes files."""
49 self._commit_git(self.TEST_GIT_REPO, self._git_tree()) 39 self._commit_git(self.TEST_GIT_REPO, self._git_tree())
50 # Fix for the remote rejected error. For more details see: 40 # Fix for the remote rejected error. For more details see:
51 # http://stackoverflow.com/questions/2816369/git-push-error-remote 41 # http://stackoverflow.com/questions/2816369/git-push-error-remote
52 subprocess2.check_output( 42 subprocess2.check_output(
53 ['git', '--git-dir', 43 ['git', '--git-dir',
54 os.path.join(self.git_root, self.TEST_GIT_REPO, '.git'), 44 os.path.join(self.git_root, self.TEST_GIT_REPO, '.git'),
55 'config', '--bool', 'core.bare', 'true']) 45 'config', '--bool', 'core.bare', 'true'])
56 46
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 '// found in the LICENSE file.\n' 79 '// found in the LICENSE file.\n'
90 '\n' 80 '\n'
91 '#ifndef DOM\n' 81 '#ifndef DOM\n'
92 '#define DOM\n' 82 '#define DOM\n'
93 '#pragma once\n' 83 '#pragma once\n'
94 '\n' 84 '\n'
95 '#include <string>\n' 85 '#include <string>\n'
96 '#endif\n') 86 '#endif\n')
97 return fs 87 return fs
98 88
99 @staticmethod
100 def _svn_tree_1():
101 fs = {}
102 fs['trunk/origin'] = 'svn@1'
103 fs['trunk/codereview.settings'] = (
104 '# Test data\n'
105 'bar: pouet\n')
106 fs['trunk/chrome/file.cc'] = (
107 'a\n'
108 'bb\n'
109 'ccc\n'
110 'dd\n'
111 'e\n'
112 'ff\n'
113 'ggg\n'
114 'hh\n'
115 'i\n'
116 'jj\n'
117 'kkk\n'
118 'll\n'
119 'm\n'
120 'nn\n'
121 'ooo\n'
122 'pp\n'
123 'q\n')
124 return fs
125
126 @classmethod
127 def _svn_tree_2(cls):
128 fs = cls._svn_tree_1()
129 fs['trunk/origin'] = 'svn@2\n'
130 fs['trunk/extra'] = 'dummy\n'
131 fs['trunk/bin_file'] = '\x00'
132 fs['trunk/chromeos/views/DOMui_menu_widget.h'] = (
133 '// Copyright (c) 2010\n'
134 '// Use of this source code\n'
135 '// found in the LICENSE file.\n'
136 '\n'
137 '#ifndef DOM\n'
138 '#define DOM\n'
139 '#pragma once\n'
140 '\n'
141 '#include <string>\n'
142 '#endif\n')
143 return fs
144
145 89
146 # pylint: disable=R0201 90 # pylint: disable=R0201
147 class BaseTest(fake_repos.FakeReposTestBase): 91 class BaseTest(fake_repos.FakeReposTestBase):
148 name = 'foo' 92 name = 'foo'
149 FAKE_REPOS_CLASS = FakeRepos 93 FAKE_REPOS_CLASS = FakeRepos
150 is_read_only = False 94 is_read_only = False
151 95
152 def setUp(self): 96 def setUp(self):
153 # Need to enforce subversion_config first.
154 checkout.SvnMixIn.svn_config_dir = os.path.join(
155 ROOT_DIR, 'subversion_config')
156 super(BaseTest, self).setUp() 97 super(BaseTest, self).setUp()
157 self._old_call = subprocess2.call 98 self._old_call = subprocess2.call
158 def redirect_call(args, **kwargs): 99 def redirect_call(args, **kwargs):
159 if not DEBUGGING: 100 if not DEBUGGING:
160 kwargs.setdefault('stdout', subprocess2.PIPE) 101 kwargs.setdefault('stdout', subprocess2.PIPE)
161 kwargs.setdefault('stderr', subprocess2.STDOUT) 102 kwargs.setdefault('stderr', subprocess2.STDOUT)
162 return self._old_call(args, **kwargs) 103 return self._old_call(args, **kwargs)
163 subprocess2.call = redirect_call 104 subprocess2.call = redirect_call
164 self.usr, self.pwd = self.FAKE_REPOS.USERS[0] 105 self.usr, self.pwd = self.FAKE_REPOS.USERS[0]
165 self.previous_log = None 106 self.previous_log = None
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 '#define WEB\n' 174 '#define WEB\n'
234 '#pragma once\n' 175 '#pragma once\n'
235 '\n' 176 '\n'
236 '#include <string>\n' 177 '#include <string>\n'
237 '#endif\n') 178 '#endif\n')
238 #print patchset[0].get() 179 #print patchset[0].get()
239 #print fake_repos.read_tree(root) 180 #print fake_repos.read_tree(root)
240 self.assertTree(tree, root) 181 self.assertTree(tree, root)
241 182
242 183
243 class SvnBaseTest(BaseTest):
244 def setUp(self):
245 super(SvnBaseTest, self).setUp()
246 self.enabled = self.FAKE_REPOS.set_up_svn()
247 self.assertTrue(self.enabled)
248 self.svn_trunk = 'trunk'
249 self.svn_url = self.svn_base + self.svn_trunk
250 self.previous_log = self._log()
251
252 def _log(self):
253 # Don't use the local checkout in case of caching incorrency.
254 out = subprocess2.check_output(
255 ['svn', 'log', self.svn_url,
256 '--non-interactive', '--no-auth-cache',
257 '--username', self.usr, '--password', self.pwd,
258 '--with-all-revprops', '--xml',
259 '--limit', '1'])
260 logentry = ElementTree.XML(out).find('logentry')
261 if logentry == None:
262 return {'revision': 0}
263 data = {
264 'revision': int(logentry.attrib['revision']),
265 }
266 def set_item(name):
267 item = logentry.find(name)
268 if item != None:
269 data[name] = item.text
270 set_item('author')
271 set_item('msg')
272 revprops = logentry.find('revprops')
273 if revprops != None:
274 data['revprops'] = []
275 for prop in revprops.getiterator('property'):
276 data['revprops'].append((prop.attrib['name'], prop.text))
277 return data
278
279 def _check_base(self, co, root, expected):
280 read_only = isinstance(co, checkout.ReadOnlyCheckout)
281 self.assertEquals(not read_only, bool(expected))
282 self.assertEquals(read_only, self.is_read_only)
283 if not read_only:
284 self.FAKE_REPOS.svn_dirty = True
285
286 self.assertEquals(root, co.project_path)
287 svn_rev = co.prepare(None)
288 self.assertEquals(int, type(svn_rev))
289 self.assertEquals(self.previous_log['revision'], svn_rev)
290 self.assertEquals('pouet', co.get_settings('bar'))
291 self.assertTree(self.get_trunk(False), root)
292 patches = self.get_patches()
293 co.apply_patch(patches)
294 self.assertEquals(
295 ['bin_file', 'chrome/file.cc', 'new_dir/subdir/new_file', 'extra'],
296 patches.filenames)
297
298 # Verify that the patch is applied even for read only checkout.
299 self.assertTree(self.get_trunk(True), root)
300 fake_author = self.FAKE_REPOS.USERS[1][0]
301 revision = co.commit(u'msg', fake_author)
302 # Nothing changed.
303 self.assertTree(self.get_trunk(True), root)
304
305 if read_only:
306 self.assertEquals('FAKE', revision)
307 self.assertEquals(self.previous_log['revision'], co.prepare(None))
308 # Changes should be reverted now.
309 self.assertTree(self.get_trunk(False), root)
310 expected = self.previous_log
311 else:
312 self.assertEquals(self.previous_log['revision'] + 1, revision)
313 self.assertEquals(self.previous_log['revision'] + 1, co.prepare(None))
314 self.assertTree(self.get_trunk(True), root)
315 expected = expected.copy()
316 expected['msg'] = 'msg'
317 expected['revision'] = self.previous_log['revision'] + 1
318 expected.setdefault('author', fake_author)
319
320 actual = self._log()
321 self.assertEquals(expected, actual)
322
323 def _test_prepare(self, co):
324 self.assertEquals(1, co.prepare(1))
325
326 def get_trunk(self, modified):
327 tree = {}
328 subroot = 'trunk/'
329 for k, v in self.FAKE_REPOS.svn_revs[-1].iteritems():
330 if k.startswith(subroot):
331 f = k[len(subroot):]
332 assert f not in tree
333 tree[f] = v
334
335 if modified:
336 content_lines = tree['chrome/file.cc'].splitlines(True)
337 tree['chrome/file.cc'] = ''.join(
338 content_lines[0:5] + ['FOO!\n'] + content_lines[5:])
339 del tree['extra']
340 tree['new_dir/subdir/new_file'] = 'A new file\nshould exist.\n'
341 return tree
342
343
344 class GitBaseTest(BaseTest): 184 class GitBaseTest(BaseTest):
345 def setUp(self): 185 def setUp(self):
346 super(GitBaseTest, self).setUp() 186 super(GitBaseTest, self).setUp()
347 self.enabled = self.FAKE_REPOS.set_up_git() 187 self.enabled = self.FAKE_REPOS.set_up_git()
348 self.assertTrue(self.enabled) 188 self.assertTrue(self.enabled)
349 self.previous_log = self._log() 189 self.previous_log = self._log()
350 190
351 # pylint: disable=W0221 191 # pylint: disable=W0221
352 def _log(self, log_from_local_repo=False): 192 def _log(self, log_from_local_repo=False):
353 if log_from_local_repo: 193 if log_from_local_repo:
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 ['git', 'diff', '--staged', '--name-status'], cwd=co.project_path) 314 ['git', 'diff', '--staged', '--name-status'], cwd=co.project_path)
475 out = sorted(out.splitlines()) 315 out = sorted(out.splitlines())
476 expected = sorted( 316 expected = sorted(
477 [ 317 [
478 'A\tchromeos/views/webui_menu_widget.h', 318 'A\tchromeos/views/webui_menu_widget.h',
479 'D\tchromeos/views/DOMui_menu_widget.h', 319 'D\tchromeos/views/DOMui_menu_widget.h',
480 ]) 320 ])
481 self.assertEquals(expected, out) 321 self.assertEquals(expected, out)
482 322
483 323
484 class SvnCheckout(SvnBaseTest):
485 def _get_co(self, post_processors):
486 self.assertNotEqual(False, post_processors)
487 return checkout.SvnCheckout(
488 self.root_dir, self.name, self.usr, self.pwd, self.svn_url,
489 post_processors)
490
491 def testAll(self):
492 expected = {
493 'author': self.FAKE_REPOS.USERS[0][0],
494 'revprops': [('realauthor', self.FAKE_REPOS.USERS[1][0])]
495 }
496 root = os.path.join(self.root_dir, self.name)
497 self._check_base(self._get_co(None), root, expected)
498
499 def testException(self):
500 self._check_exception(
501 self._get_co(None),
502 'While running patch -p1 --forward --force --no-backup-if-mismatch;\n'
503 ' patching file chrome/file.cc\n'
504 ' Hunk #1 FAILED at 3.\n'
505 ' 1 out of 1 hunk FAILED -- saving rejects to file '
506 'chrome/file.cc.rej\n')
507
508 def testSvnProps(self):
509 co = self._get_co(None)
510 co.prepare(None)
511 try:
512 # svn:ignore can only be applied to directories.
513 svn_props = [('svn:ignore', 'foo')]
514 co.apply_patch(
515 [patch.FilePatchDiff('chrome/file.cc', RAW.PATCH, svn_props)])
516 self.fail()
517 except checkout.PatchApplicationFailed, e:
518 self.assertEquals(e.filename, 'chrome/file.cc')
519 # The last line of the output depends on the svn version so we can't
520 # check it precisely
521 self.assertRegexpMatches(
522 e.status,
523 'While running svn propset svn:ignore foo chrome/file.cc '
524 '--non-interactive;\n'
525 ' patching file chrome/file.cc\n'
526 ' svn:.*')
527 co.prepare(None)
528 svn_props = [('svn:eol-style', 'LF'), ('foo', 'bar')]
529 co.apply_patch(
530 [patch.FilePatchDiff('chrome/file.cc', RAW.PATCH, svn_props)])
531 filepath = os.path.join(self.root_dir, self.name, 'chrome/file.cc')
532 # Manually verify the properties.
533 props = subprocess2.check_output(
534 ['svn', 'proplist', filepath],
535 cwd=self.root_dir).splitlines()[1:]
536 props = sorted(p.strip() for p in props)
537 expected_props = dict(svn_props)
538 self.assertEquals(sorted(expected_props.iterkeys()), props)
539 for k, v in expected_props.iteritems():
540 value = subprocess2.check_output(
541 ['svn', 'propget', '--strict', k, filepath],
542 cwd=self.root_dir).strip()
543 self.assertEquals(v, value)
544
545 def testWithRevPropsSupport(self):
546 # Add the hook that will commit in a way that removes the race condition.
547 hook = os.path.join(self.FAKE_REPOS.svn_repo, 'hooks', 'pre-commit')
548 shutil.copyfile(os.path.join(ROOT_DIR, 'sample_pre_commit_hook'), hook)
549 os.chmod(hook, 0755)
550 expected = {
551 'revprops': [('commit-bot', 'user1@example.com')],
552 }
553 root = os.path.join(self.root_dir, self.name)
554 self._check_base(self._get_co(None), root, expected)
555
556 def testWithRevPropsSupportNotCommitBot(self):
557 # Add the hook that will commit in a way that removes the race condition.
558 hook = os.path.join(self.FAKE_REPOS.svn_repo, 'hooks', 'pre-commit')
559 shutil.copyfile(os.path.join(ROOT_DIR, 'sample_pre_commit_hook'), hook)
560 os.chmod(hook, 0755)
561 co = checkout.SvnCheckout(
562 self.root_dir, self.name,
563 self.FAKE_REPOS.USERS[1][0], self.FAKE_REPOS.USERS[1][1],
564 self.svn_url)
565 root = os.path.join(self.root_dir, self.name)
566 expected = {
567 'author': self.FAKE_REPOS.USERS[1][0],
568 }
569 self._check_base(co, root, expected)
570
571 def testAutoProps(self):
572 co = self._get_co(None)
573 co.svn_config = checkout.SvnConfig(
574 os.path.join(ROOT_DIR, 'subversion_config'))
575 co.prepare(None)
576 patches = self.get_patches()
577 co.apply_patch(patches)
578 self.assertEquals(
579 ['bin_file', 'chrome/file.cc', 'new_dir/subdir/new_file', 'extra'],
580 patches.filenames)
581 # *.txt = svn:eol-style=LF in subversion_config/config.
582 out = subprocess2.check_output(
583 ['svn', 'pget', 'svn:eol-style', 'chrome/file.cc'],
584 cwd=co.project_path)
585 self.assertEquals('LF\n', out)
586
587 def testProcess(self):
588 self._test_process(self._get_co)
589
590 def testPrepare(self):
591 self._test_prepare(self._get_co(None))
592
593 def testMove(self):
594 co = self._get_co(None)
595 self._check_move(co)
596 out = subprocess2.check_output(
597 ['svn', 'status'], cwd=co.project_path)
598 out = sorted(out.splitlines())
599 expected = sorted(
600 [
601 'A + chromeos/views/webui_menu_widget.h',
602 'D chromeos/views/DOMui_menu_widget.h',
603 ])
604 self.assertEquals(expected, out)
605 # Make sure ancestry is what is expected;
606 env = os.environ.copy()
607 env['LANGUAGE'] = 'en_US.UTF-8'
608 out = subprocess2.check_output(
609 ['svn', 'info', 'chromeos/views/webui_menu_widget.h'],
610 cwd=co.project_path,
611 env=env)
612 values = dict(l.split(': ', 1) for l in out.splitlines() if l)
613 expected = {
614 # checksum seems to vary with svn version so we can't check it
615 #'Checksum': '65837bb3da662c8fa88a4a50940ea7c6',
616 'Copied From Rev': '2',
617 'Copied From URL':
618 '%strunk/chromeos/views/DOMui_menu_widget.h' % self.svn_base,
619 'Name': 'webui_menu_widget.h',
620 'Node Kind': 'file',
621 'Path': 'chromeos/views/webui_menu_widget.h',
622 'Repository Root': '%s' % self.svn_base.rstrip('/'),
623 'Revision': '2',
624 'Schedule': 'add',
625 'URL': '%strunk/chromeos/views/webui_menu_widget.h' % self.svn_base,
626 }
627 for key in expected:
628 self.assertIn(key, values)
629 self.assertEquals(expected[key], values[key])
630
631
632 class RawCheckout(SvnBaseTest):
633 def setUp(self):
634 super(RawCheckout, self).setUp()
635 # Use a svn checkout as the base.
636 self.base_co = checkout.SvnCheckout(
637 self.root_dir, self.name, None, None, self.svn_url)
638 self.base_co.prepare(None)
639
640 def _get_co(self, post_processors):
641 self.assertNotEqual(False, post_processors)
642 return checkout.RawCheckout(self.root_dir, self.name, post_processors)
643
644 def testAll(self):
645 # Can't use self._check_base() since it's too different.
646 root = os.path.join(self.root_dir, self.name)
647 co = self._get_co(None)
648
649 # A copy of BaseTest._check_base()
650 self.assertEquals(root, co.project_path)
651 self.assertEquals(None, co.prepare(None))
652 self.assertEquals('pouet', co.get_settings('bar'))
653 self.assertTree(self.get_trunk(False), root)
654 patches = self.get_patches()
655 co.apply_patch(patches)
656 self.assertEquals(
657 ['bin_file', 'chrome/file.cc', 'new_dir/subdir/new_file', 'extra'],
658 patches.filenames)
659
660 # Verify that the patch is applied even for read only checkout.
661 self.assertTree(self.get_trunk(True), root)
662 try:
663 co.commit(u'msg', self.FAKE_REPOS.USERS[1][0])
664 self.fail()
665 except NotImplementedError:
666 pass
667 self.assertTree(self.get_trunk(True), root)
668 # Verify that prepare() is a no-op.
669 self.assertEquals(None, co.prepare(None))
670 self.assertTree(self.get_trunk(True), root)
671
672 def testException(self):
673 self._check_exception(
674 self._get_co(None),
675 'While running patch -u --binary -p1;\n'
676 ' patching file chrome/file.cc\n'
677 ' Hunk #1 FAILED at 3.\n'
678 ' 1 out of 1 hunk FAILED -- saving rejects to file '
679 'chrome/file.cc.rej\n')
680
681 def testProcess(self):
682 self._test_process(self._get_co)
683
684 def testPrepare(self):
685 # RawCheckout doesn't support prepare() but emulate it.
686 co = self._get_co(None)
687 revs = [1]
688 def prepare(asked):
689 self.assertEquals(1, asked)
690 return revs.pop(0)
691 co.prepare = prepare
692 self._test_prepare(co)
693 self.assertEquals([], revs)
694
695 def testMove(self):
696 self._check_move(self._get_co(None))
697
698
699 class ReadOnlyCheckout(SvnBaseTest):
700 # Use SvnCheckout as the backed since it support read-only checkouts too.
701 is_read_only = True
702
703 def _get_co(self, post_processors):
704 self.assertNotEqual(False, post_processors)
705 return checkout.ReadOnlyCheckout(
706 checkout.SvnCheckout(
707 self.root_dir, self.name, None, None, self.svn_url, None),
708 post_processors)
709
710 def testAll(self):
711 root = os.path.join(self.root_dir, self.name)
712 self._check_base(self._get_co(None), root, None)
713
714 def testException(self):
715 self._check_exception(
716 self._get_co(None),
717 'While running patch -p1 --forward --force --no-backup-if-mismatch;\n'
718 ' patching file chrome/file.cc\n'
719 ' Hunk #1 FAILED at 3.\n'
720 ' 1 out of 1 hunk FAILED -- saving rejects to file '
721 'chrome/file.cc.rej\n')
722
723 def testProcess(self):
724 self._test_process(self._get_co)
725
726 def testPrepare(self):
727 self._test_prepare(self._get_co(None))
728
729 def testMove(self):
730 self._check_move(self._get_co(None))
731
732
733 if __name__ == '__main__': 324 if __name__ == '__main__':
734 if '-v' in sys.argv: 325 if '-v' in sys.argv:
735 DEBUGGING = True 326 DEBUGGING = True
736 logging.basicConfig( 327 logging.basicConfig(
737 level=logging.DEBUG, 328 level=logging.DEBUG,
738 format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') 329 format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s')
739 else: 330 else:
740 logging.basicConfig( 331 logging.basicConfig(
741 level=logging.ERROR, 332 level=logging.ERROR,
742 format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') 333 format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s')
743 unittest.main() 334 unittest.main()
OLDNEW
« no previous file with comments | « testing_support/super_mox.py ('k') | tests/gcl_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698