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

Side by Side Diff: tests/fake_repos.py

Issue 2594001: Significantly improve gclient_smoketest.py (Closed)
Patch Set: comments Created 10 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
« no previous file with comments | « no previous file | tests/gclient_smoketest.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/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 """Generate fake repositories for testing.""" 6 """Generate fake repositories for testing."""
7 7
8 import atexit 8 import atexit
9 import errno 9 import errno
10 import logging 10 import logging
11 import os 11 import os
12 import pprint 12 import pprint
13 import re 13 import re
14 import stat 14 import stat
15 import subprocess 15 import subprocess
16 import sys 16 import sys
17 import time 17 import time
18 import unittest 18 import unittest
19 19
20 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
21
22 import scm
20 23
21 ## Utility functions 24 ## Utility functions
22 25
23 26
24 def addKill(): 27 def addKill():
25 """Add kill() method to subprocess.Popen for python <2.6""" 28 """Add kill() method to subprocess.Popen for python <2.6"""
26 if getattr(subprocess.Popen, 'kill', None): 29 if getattr(subprocess.Popen, 'kill', None):
27 return 30 return
28 if sys.platform == 'win32': 31 if sys.platform == 'win32':
29 def kill_win(process): 32 def kill_win(process):
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 if k not in dict2: 145 if k not in dict2:
143 diff[k] = v 146 diff[k] = v
144 elif v != dict2[k]: 147 elif v != dict2[k]:
145 diff[k] = (v, dict2[k]) 148 diff[k] = (v, dict2[k])
146 for k, v in dict2.iteritems(): 149 for k, v in dict2.iteritems():
147 if k not in dict1: 150 if k not in dict1:
148 diff[k] = v 151 diff[k] = v
149 return diff 152 return diff
150 153
151 154
152 def mangle_svn_tree(*args):
153 result = {}
154 for old_root, new_root, tree in args:
155 for k, v in tree.iteritems():
156 if not k.startswith(old_root):
157 continue
158 result[join(new_root, k[len(old_root) + 1:]).replace(os.sep, '/')] = v
159 return result
160
161
162 def mangle_git_tree(*args):
163 result = {}
164 for new_root, tree in args:
165 for k, v in tree.iteritems():
166 result[join(new_root, k)] = v
167 return result
168
169
170 def commit_svn(repo): 155 def commit_svn(repo):
171 """Commits the changes and returns the new revision number.""" 156 """Commits the changes and returns the new revision number."""
172 # Basic parsing.
173 to_add = [] 157 to_add = []
174 to_remove = [] 158 to_remove = []
175 for item in Popen(['svn', 'status'], 159 for status, filepath in scm.SVN.CaptureStatus(repo):
176 cwd=repo).communicate()[0].splitlines(False): 160 if status[0] == '?':
177 if item[0] == '?': 161 to_add.append(filepath)
178 to_add.append(item[7:].strip()) 162 elif status[0] == '!':
179 elif item[0] == '!': 163 to_remove.append(filepath)
180 to_remove.append(item[7:].strip())
181 if to_add: 164 if to_add:
182 check_call(['svn', 'add', '--no-auto-props', '-q'] + to_add, cwd=repo) 165 check_call(['svn', 'add', '--no-auto-props', '-q'] + to_add, cwd=repo)
183 if to_remove: 166 if to_remove:
184 check_call(['svn', 'remove', '-q'] + to_remove, cwd=repo) 167 check_call(['svn', 'remove', '-q'] + to_remove, cwd=repo)
185 proc = Popen(['svn', 'commit', repo, '-m', 'foo', '--non-interactive', 168 proc = Popen(['svn', 'commit', repo, '-m', 'foo', '--non-interactive',
186 '--no-auth-cache', '--username', 'user1', '--password', 'foo'], 169 '--no-auth-cache', '--username', 'user1', '--password', 'foo'],
187 cwd=repo) 170 cwd=repo)
188 out, err = proc.communicate() 171 out, err = proc.communicate()
189 match = re.search(r'revision (\d+).', out) 172 match = re.search(r'revision (\d+).', out)
190 if not match: 173 if not match:
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 self.SHOULD_LEAK = True 218 self.SHOULD_LEAK = True
236 sys.argv.remove('-l') 219 sys.argv.remove('-l')
237 elif leak is not None: 220 elif leak is not None:
238 self.SHOULD_LEAK = leak 221 self.SHOULD_LEAK = leak
239 if host: 222 if host:
240 self.HOST = host 223 self.HOST = host
241 if trial_dir: 224 if trial_dir:
242 self.TRIAL_DIR = trial_dir 225 self.TRIAL_DIR = trial_dir
243 226
244 # Format is [ None, tree, tree, ...] 227 # Format is [ None, tree, tree, ...]
228 # i.e. revisions are 1-based.
245 self.svn_revs = [None] 229 self.svn_revs = [None]
246 # Format is { repo: [ (hash, tree), (hash, tree), ... ], ... } 230 # Format is { repo: [ None, (hash, tree), (hash, tree), ... ], ... }
231 # so reference looks like self.git_hashes[repo][rev][0] for hash and
232 # self.git_hashes[repo][rev][1] for it's tree snapshot.
233 # For consistency with self.svn_revs, it is 1-based too.
247 self.git_hashes = {} 234 self.git_hashes = {}
248 self.svnserve = None 235 self.svnserve = None
249 self.gitdaemon = None 236 self.gitdaemon = None
250 self.common_init = False 237 self.common_init = False
251 238
252 def trial_dir(self): 239 def trial_dir(self):
253 if not self.TRIAL_DIR: 240 if not self.TRIAL_DIR:
254 self.TRIAL_DIR = os.path.join( 241 self.TRIAL_DIR = os.path.join(
255 os.path.dirname(os.path.abspath(__file__)), '_trial') 242 os.path.dirname(os.path.abspath(__file__)), '_trial')
256 return self.TRIAL_DIR 243 return self.TRIAL_DIR
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 382
396 def setUpGIT(self): 383 def setUpGIT(self):
397 """Creates git repositories and start the servers.""" 384 """Creates git repositories and start the servers."""
398 if self.gitdaemon: 385 if self.gitdaemon:
399 return True 386 return True
400 self.setUp() 387 self.setUp()
401 if sys.platform == 'win32': 388 if sys.platform == 'win32':
402 return False 389 return False
403 for repo in ['repo_%d' % r for r in range(1, 5)]: 390 for repo in ['repo_%d' % r for r in range(1, 5)]:
404 check_call(['git', 'init', '-q', join(self.git_root, repo)]) 391 check_call(['git', 'init', '-q', join(self.git_root, repo)])
405 self.git_hashes[repo] = [] 392 self.git_hashes[repo] = [None]
406 393
407 # Testing: 394 # Testing:
408 # - dependency disapear 395 # - dependency disapear
409 # - dependency renamed 396 # - dependency renamed
410 # - versioned and unversioned reference 397 # - versioned and unversioned reference
411 # - relative and full reference 398 # - relative and full reference
412 # - deps_os 399 # - deps_os
413 # - var 400 # - var
414 # - hooks 401 # - hooks
415 # TODO(maruel): 402 # TODO(maruel):
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 'open(\\'src/git_hooked1\\', \\'w\\').write(\\'git_hooked1\\')'], 459 'open(\\'src/git_hooked1\\', \\'w\\').write(\\'git_hooked1\\')'],
473 }, 460 },
474 { 461 {
475 # Should not be run. 462 # Should not be run.
476 'pattern': 'nonexistent', 463 'pattern': 'nonexistent',
477 'action': ['python', '-c', 464 'action': ['python', '-c',
478 'open(\\'src/git_hooked2\\', \\'w\\').write(\\'git_hooked2\\')'], 465 'open(\\'src/git_hooked2\\', \\'w\\').write(\\'git_hooked2\\')'],
479 }, 466 },
480 ] 467 ]
481 """ % { 468 """ % {
469 'host': self.HOST,
470 # See self.__init__() for the format. Grab's the hash of the first
471 # commit in repo_2. Only keep the first 7 character because of:
482 # TODO(maruel): http://crosbug.com/3591 We need to strip the hash.. duh. 472 # TODO(maruel): http://crosbug.com/3591 We need to strip the hash.. duh.
483 'host': self.HOST, 473 'hash': self.git_hashes['repo_2'][1][0][:7]
484 'hash': self.git_hashes['repo_2'][0][0][:7]
485 }, 474 },
486 'origin': "git/repo_1@2\n" 475 'origin': "git/repo_1@2\n"
487 }) 476 })
488 477
489 # Start the daemon. 478 # Start the daemon.
490 cmd = ['git', 'daemon', '--export-all', '--base-path=' + self.repos_dir] 479 cmd = ['git', 'daemon', '--export-all', '--base-path=' + self.repos_dir]
491 if self.HOST == '127.0.0.1': 480 if self.HOST == '127.0.0.1':
492 cmd.append('--listen=127.0.0.1') 481 cmd.append('--listen=127.0.0.1')
493 logging.debug(cmd) 482 logging.debug(cmd)
494 self.gitdaemon = Popen(cmd, cwd=self.repos_dir) 483 self.gitdaemon = Popen(cmd, cwd=self.repos_dir)
495 return True 484 return True
496 485
497 def _commit_svn(self, tree): 486 def _commit_svn(self, tree):
498 self._genTree(self.svn_root, tree) 487 self._genTree(self.svn_root, tree)
499 commit_svn(self.svn_root) 488 commit_svn(self.svn_root)
500 if self.svn_revs and self.svn_revs[-1]: 489 if self.svn_revs and self.svn_revs[-1]:
501 new_tree = self.svn_revs[-1].copy() 490 new_tree = self.svn_revs[-1].copy()
502 new_tree.update(tree) 491 new_tree.update(tree)
503 else: 492 else:
504 new_tree = tree.copy() 493 new_tree = tree.copy()
505 self.svn_revs.append(new_tree) 494 self.svn_revs.append(new_tree)
506 495
507 def _commit_git(self, repo, tree): 496 def _commit_git(self, repo, tree):
508 repo_root = join(self.git_root, repo) 497 repo_root = join(self.git_root, repo)
509 self._genTree(repo_root, tree) 498 self._genTree(repo_root, tree)
510 hash = commit_git(repo_root) 499 hash = commit_git(repo_root)
511 if self.git_hashes[repo]: 500 if self.git_hashes[repo][-1]:
512 new_tree = self.git_hashes[repo][-1][1].copy() 501 new_tree = self.git_hashes[repo][-1][1].copy()
513 new_tree.update(tree) 502 new_tree.update(tree)
514 else: 503 else:
515 new_tree = tree.copy() 504 new_tree = tree.copy()
516 self.git_hashes[repo].append((hash, new_tree)) 505 self.git_hashes[repo].append((hash, new_tree))
517 506
518 507
519 class FakeReposTestBase(unittest.TestCase): 508 class FakeReposTestBase(unittest.TestCase):
520 """This is vaguely inspired by twisted.""" 509 """This is vaguely inspired by twisted."""
521 510
(...skipping 13 matching lines...) Expand all
535 self.root_dir = join(self.CLASS_ROOT_DIR, self.id()) 524 self.root_dir = join(self.CLASS_ROOT_DIR, self.id())
536 rmtree(self.root_dir) 525 rmtree(self.root_dir)
537 os.makedirs(self.root_dir) 526 os.makedirs(self.root_dir)
538 self.svn_base = 'svn://%s/svn/' % self.FAKE_REPOS.HOST 527 self.svn_base = 'svn://%s/svn/' % self.FAKE_REPOS.HOST
539 self.git_base = 'git://%s/git/' % self.FAKE_REPOS.HOST 528 self.git_base = 'git://%s/git/' % self.FAKE_REPOS.HOST
540 529
541 def tearDown(self): 530 def tearDown(self):
542 if not self.FAKE_REPOS.SHOULD_LEAK: 531 if not self.FAKE_REPOS.SHOULD_LEAK:
543 rmtree(self.root_dir) 532 rmtree(self.root_dir)
544 533
545 def checkString(self, expected, result): 534 def checkString(self, expected, result, msg=None):
546 """Prints the diffs to ease debugging.""" 535 """Prints the diffs to ease debugging."""
547 if expected != result: 536 if expected != result:
548 # Strip the begining 537 # Strip the begining
549 while expected and result and expected[0] == result[0]: 538 while expected and result and expected[0] == result[0]:
550 expected = expected[1:] 539 expected = expected[1:]
551 result = result[1:] 540 result = result[1:]
552 # The exception trace makes it hard to read so dump it too. 541 # The exception trace makes it hard to read so dump it too.
553 if '\n' in result: 542 if '\n' in result:
554 print result 543 print result
555 self.assertEquals(expected, result) 544 self.assertEquals(expected, result, msg)
556 545
557 def check(self, expected, results): 546 def check(self, expected, results):
558 """Checks stdout, stderr, retcode.""" 547 """Checks stdout, stderr, retcode."""
559 self.checkString(expected[0], results[0]) 548 self.checkString(expected[0], results[0])
560 self.checkString(expected[1], results[1]) 549 self.checkString(expected[1], results[1])
561 self.assertEquals(expected[2], results[2]) 550 self.assertEquals(expected[2], results[2])
562 551
563 def assertTree(self, tree, tree_root=None): 552 def assertTree(self, tree, tree_root=None):
564 """Diff the checkout tree with a dict.""" 553 """Diff the checkout tree with a dict."""
565 if not tree_root: 554 if not tree_root:
566 tree_root = self.root_dir 555 tree_root = self.root_dir
567 actual = read_tree(tree_root) 556 actual = read_tree(tree_root)
568 diff = dict_diff(tree, actual) 557 diff = dict_diff(tree, actual)
569 if diff: 558 if diff:
570 logging.debug('Actual %s\n%s' % (tree_root, pprint.pformat(actual))) 559 logging.debug('Actual %s\n%s' % (tree_root, pprint.pformat(actual)))
571 logging.debug('Expected\n%s' % pprint.pformat(tree)) 560 logging.debug('Expected\n%s' % pprint.pformat(tree))
572 logging.debug('Diff\n%s' % pprint.pformat(diff)) 561 logging.debug('Diff\n%s' % pprint.pformat(diff))
573 self.assertEquals(diff, []) 562 self.assertEquals(diff, [])
574 563
564 def mangle_svn_tree(self, *args):
565 """Creates a 'virtual directory snapshot' to compare with the actual result
566 on disk."""
567 result = {}
568 for item, new_root in args:
569 old_root, rev = item.split('@', 1)
570 tree = self.FAKE_REPOS.svn_revs[int(rev)]
571 for k, v in tree.iteritems():
572 if not k.startswith(old_root):
573 continue
574 result[join(new_root, k[len(old_root) + 1:]).replace(os.sep, '/')] = v
575 return result
576
577 def mangle_git_tree(self, *args):
578 """Creates a 'virtual directory snapshot' to compare with the actual result
579 on disk."""
580 result = {}
581 for item, new_root in args:
582 repo, rev = item.split('@', 1)
583 tree = self.gittree(repo, rev)
584 for k, v in tree.iteritems():
585 result[join(new_root, k)] = v
586 return result
587
588 def githash(self, repo, rev):
589 """Sort-hand: Returns the hash for a git 'revision'."""
590 return self.FAKE_REPOS.git_hashes[repo][int(rev)][0]
591
592 def gittree(self, repo, rev):
593 """Sort-hand: returns the directory tree for a git 'revision'."""
594 return self.FAKE_REPOS.git_hashes[repo][int(rev)][1]
595
575 596
576 def main(argv): 597 def main(argv):
577 fake = FakeRepos() 598 fake = FakeRepos()
578 print 'Using %s' % fake.trial_dir() 599 print 'Using %s' % fake.trial_dir()
579 try: 600 try:
580 fake.setUp() 601 fake.setUp()
581 print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.') 602 print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.')
582 sys.stdin.readline() 603 sys.stdin.readline()
583 except KeyboardInterrupt: 604 except KeyboardInterrupt:
584 fake.SHOULD_LEAK = True 605 fake.SHOULD_LEAK = True
585 return 0 606 return 0
586 607
587 608
588 if __name__ == '__main__': 609 if __name__ == '__main__':
589 sys.exit(main(sys.argv)) 610 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | tests/gclient_smoketest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698