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

Side by Side Diff: tests/fake_repos.py

Issue 6783022: Add subprocess.Popen().kill() to python 2.5. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Rebase against HEAD Created 9 years, 8 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 | « subprocess2.py ('k') | 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/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 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 datetime 9 import datetime
10 import errno 10 import errno
11 import logging 11 import logging
12 import os 12 import os
13 import pprint 13 import pprint
14 import re 14 import re
15 import socket 15 import socket
16 import subprocess
17 import sys 16 import sys
18 import tempfile 17 import tempfile
19 import time 18 import time
20 19
21 # trial_dir must be first for non-system libraries. 20 # trial_dir must be first for non-system libraries.
22 from tests import trial_dir 21 from tests import trial_dir
23 import gclient_utils 22 import gclient_utils
24 import scm 23 import scm
25 24 import subprocess2
26 ## Utility functions
27
28
29 def kill_pid(pid):
30 """Kills a process by its process id."""
31 try:
32 # Unable to import 'module'
33 # pylint: disable=F0401
34 import signal
35 return os.kill(pid, signal.SIGKILL)
36 except ImportError:
37 pass
38
39
40 def kill_win(process):
41 """Kills a process with its windows handle.
42
43 Has no effect on other platforms.
44 """
45 try:
46 # Unable to import 'module'
47 # pylint: disable=F0401
48 import win32process
49 # Access to a protected member _handle of a client class
50 # pylint: disable=W0212
51 return win32process.TerminateProcess(process._handle, -1)
52 except ImportError:
53 pass
54
55
56 def add_kill():
57 """Adds kill() method to subprocess.Popen for python <2.6"""
58 if hasattr(subprocess.Popen, 'kill'):
59 return
60
61 if sys.platform == 'win32':
62 subprocess.Popen.kill = kill_win
63 else:
64 def kill_nix(process):
65 return kill_pid(process.pid)
66 subprocess.Popen.kill = kill_nix
67 25
68 26
69 def write(path, content): 27 def write(path, content):
70 f = open(path, 'wb') 28 f = open(path, 'wb')
71 f.write(content) 29 f.write(content)
72 f.close() 30 f.close()
73 31
74 32
75 join = os.path.join 33 join = os.path.join
76 34
77 35
78 def check_call(*args, **kwargs):
79 logging.debug(args[0])
80 subprocess.check_call(*args, **kwargs)
81
82
83 def Popen(*args, **kwargs):
84 kwargs.setdefault('stdout', subprocess.PIPE)
85 kwargs.setdefault('stderr', subprocess.STDOUT)
86 logging.debug(args[0])
87 return subprocess.Popen(*args, **kwargs)
88
89
90 def read_tree(tree_root): 36 def read_tree(tree_root):
91 """Returns a dict of all the files in a tree. Defaults to self.root_dir.""" 37 """Returns a dict of all the files in a tree. Defaults to self.root_dir."""
92 tree = {} 38 tree = {}
93 for root, dirs, files in os.walk(tree_root): 39 for root, dirs, files in os.walk(tree_root):
94 for d in filter(lambda x: x.startswith('.'), dirs): 40 for d in filter(lambda x: x.startswith('.'), dirs):
95 dirs.remove(d) 41 dirs.remove(d)
96 for f in [join(root, f) for f in files if not f.startswith('.')]: 42 for f in [join(root, f) for f in files if not f.startswith('.')]:
97 filepath = f[len(tree_root) + 1:].replace(os.sep, '/') 43 filepath = f[len(tree_root) + 1:].replace(os.sep, '/')
98 assert len(filepath), f 44 assert len(filepath), f
99 tree[filepath] = open(join(root, f), 'rU').read() 45 tree[filepath] = open(join(root, f), 'rU').read()
(...skipping 16 matching lines...) Expand all
116 def commit_svn(repo, usr, pwd): 62 def commit_svn(repo, usr, pwd):
117 """Commits the changes and returns the new revision number.""" 63 """Commits the changes and returns the new revision number."""
118 to_add = [] 64 to_add = []
119 to_remove = [] 65 to_remove = []
120 for status, filepath in scm.SVN.CaptureStatus(repo): 66 for status, filepath in scm.SVN.CaptureStatus(repo):
121 if status[0] == '?': 67 if status[0] == '?':
122 to_add.append(filepath) 68 to_add.append(filepath)
123 elif status[0] == '!': 69 elif status[0] == '!':
124 to_remove.append(filepath) 70 to_remove.append(filepath)
125 if to_add: 71 if to_add:
126 check_call(['svn', 'add', '--no-auto-props', '-q'] + to_add, cwd=repo) 72 subprocess2.check_output(
73 ['svn', 'add', '--no-auto-props', '-q'] + to_add, cwd=repo)
127 if to_remove: 74 if to_remove:
128 check_call(['svn', 'remove', '-q'] + to_remove, cwd=repo) 75 subprocess2.check_output(['svn', 'remove', '-q'] + to_remove, cwd=repo)
129 proc = Popen( 76
77 out = subprocess2.check_output(
130 ['svn', 'commit', repo, '-m', 'foo', '--non-interactive', 78 ['svn', 'commit', repo, '-m', 'foo', '--non-interactive',
131 '--no-auth-cache', 79 '--no-auth-cache',
132 '--username', usr, '--password', pwd], 80 '--username', usr, '--password', pwd],
133 cwd=repo) 81 cwd=repo)
134 out, err = proc.communicate()
135 match = re.search(r'(\d+)', out) 82 match = re.search(r'(\d+)', out)
136 if not match: 83 if not match:
137 raise Exception('Commit failed', out, err, proc.returncode) 84 raise Exception('Commit failed', out)
138 rev = match.group(1) 85 rev = match.group(1)
139 st = Popen(['svn', 'status'], cwd=repo).communicate()[0] 86 status = subprocess2.check_output(['svn', 'status'], cwd=repo)
140 assert len(st) == 0, st 87 assert len(status) == 0, status
141 logging.debug('At revision %s' % rev) 88 logging.debug('At revision %s' % rev)
142 return rev 89 return rev
143 90
144 91
145 def commit_git(repo): 92 def commit_git(repo):
146 """Commits the changes and returns the new hash.""" 93 """Commits the changes and returns the new hash."""
147 check_call(['git', 'add', '-A', '-f'], cwd=repo) 94 subprocess2.check_call(['git', 'add', '-A', '-f'], cwd=repo)
148 check_call(['git', 'commit', '-q', '--message', 'foo'], cwd=repo) 95 subprocess2.check_call(['git', 'commit', '-q', '--message', 'foo'], cwd=repo)
149 rev = Popen(['git', 'show-ref', '--head', 'HEAD'], 96 rev = subprocess2.check_output(
150 cwd=repo).communicate()[0].split(' ', 1)[0] 97 ['git', 'show-ref', '--head', 'HEAD'], cwd=repo).split(' ', 1)[0]
151 logging.debug('At revision %s' % rev) 98 logging.debug('At revision %s' % rev)
152 return rev 99 return rev
153 100
154 101
155 def test_port(host, port): 102 def test_port(host, port):
156 s = socket.socket() 103 s = socket.socket()
157 try: 104 try:
158 return s.connect_ex((host, port)) == 0 105 return s.connect_ex((host, port)) == 0
159 finally: 106 finally:
160 s.close() 107 s.close()
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 211
265 @property 212 @property
266 def root_dir(self): 213 def root_dir(self):
267 return self.trial.root_dir 214 return self.trial.root_dir
268 215
269 def set_up(self): 216 def set_up(self):
270 """All late initialization comes here.""" 217 """All late initialization comes here."""
271 self.cleanup_dirt() 218 self.cleanup_dirt()
272 if not self.root_dir: 219 if not self.root_dir:
273 try: 220 try:
274 add_kill()
275 # self.root_dir is not set before this call. 221 # self.root_dir is not set before this call.
276 self.trial.set_up() 222 self.trial.set_up()
277 self.git_root = join(self.root_dir, 'git') 223 self.git_root = join(self.root_dir, 'git')
278 self.svn_checkout = join(self.root_dir, 'svn_checkout') 224 self.svn_checkout = join(self.root_dir, 'svn_checkout')
279 self.svn_repo = join(self.root_dir, 'svn') 225 self.svn_repo = join(self.root_dir, 'svn')
280 finally: 226 finally:
281 # Registers cleanup. 227 # Registers cleanup.
282 atexit.register(self.tear_down) 228 atexit.register(self.tear_down)
283 229
284 def cleanup_dirt(self): 230 def cleanup_dirt(self):
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 267
322 def tear_down_git(self): 268 def tear_down_git(self):
323 if self.gitdaemon: 269 if self.gitdaemon:
324 logging.debug('Killing git-daemon pid %s' % self.gitdaemon.pid) 270 logging.debug('Killing git-daemon pid %s' % self.gitdaemon.pid)
325 self.gitdaemon.kill() 271 self.gitdaemon.kill()
326 self.gitdaemon = None 272 self.gitdaemon = None
327 if self.git_pid_file: 273 if self.git_pid_file:
328 pid = int(self.git_pid_file.read()) 274 pid = int(self.git_pid_file.read())
329 self.git_pid_file.close() 275 self.git_pid_file.close()
330 logging.debug('Killing git daemon pid %s' % pid) 276 logging.debug('Killing git daemon pid %s' % pid)
331 kill_pid(pid) 277 subprocess2.kill_pid(pid)
332 self.git_pid_file = None 278 self.git_pid_file = None
333 wait_for_port_to_free(self.host, self.git_port) 279 wait_for_port_to_free(self.host, self.git_port)
334 self.git_port = None 280 self.git_port = None
335 self.git_base = None 281 self.git_base = None
336 if not self.trial.SHOULD_LEAK: 282 if not self.trial.SHOULD_LEAK:
337 logging.debug('Removing %s' % self.git_root) 283 logging.debug('Removing %s' % self.git_root)
338 gclient_utils.rmtree(self.git_root) 284 gclient_utils.rmtree(self.git_root)
339 else: 285 else:
340 return False 286 return False
341 return True 287 return True
(...skipping 14 matching lines...) Expand all
356 os.remove(join(root, k)) 302 os.remove(join(root, k))
357 else: 303 else:
358 write(join(root, k), v) 304 write(join(root, k), v)
359 305
360 def set_up_svn(self): 306 def set_up_svn(self):
361 """Creates subversion repositories and start the servers.""" 307 """Creates subversion repositories and start the servers."""
362 self.set_up() 308 self.set_up()
363 if self.svnserve: 309 if self.svnserve:
364 return True 310 return True
365 try: 311 try:
366 check_call(['svnadmin', 'create', self.svn_repo]) 312 subprocess2.check_call(['svnadmin', 'create', self.svn_repo])
367 except OSError, e: 313 except subprocess2.CalledProcessError, e:
368 logging.debug('Failed with : %s' % e) 314 logging.debug('Failed with : %s' % e)
369 return False 315 return False
370 write(join(self.svn_repo, 'conf', 'svnserve.conf'), 316 write(join(self.svn_repo, 'conf', 'svnserve.conf'),
371 '[general]\n' 317 '[general]\n'
372 'anon-access = read\n' 318 'anon-access = read\n'
373 'auth-access = write\n' 319 'auth-access = write\n'
374 'password-db = passwd\n') 320 'password-db = passwd\n')
375 text = '[users]\n' 321 text = '[users]\n'
376 text += ''.join('%s = %s\n' % (usr, pwd) for usr, pwd in self.USERS) 322 text += ''.join('%s = %s\n' % (usr, pwd) for usr, pwd in self.USERS)
377 write(join(self.svn_repo, 'conf', 'passwd'), text) 323 write(join(self.svn_repo, 'conf', 'passwd'), text)
378 324
379 # Mac 10.6 ships with a buggy subversion build and we need this line 325 # Mac 10.6 ships with a buggy subversion build and we need this line
380 # to work around the bug. 326 # to work around the bug.
381 write(join(self.svn_repo, 'db', 'fsfs.conf'), 327 write(join(self.svn_repo, 'db', 'fsfs.conf'),
382 '[rep-sharing]\n' 328 '[rep-sharing]\n'
383 'enable-rep-sharing = false\n') 329 'enable-rep-sharing = false\n')
384 330
385 # Start the daemon. 331 # Start the daemon.
386 self.svn_port = find_free_port(self.host, 10000) 332 self.svn_port = find_free_port(self.host, 10000)
387 logging.debug('Using port %d' % self.svn_port) 333 logging.debug('Using port %d' % self.svn_port)
388 cmd = ['svnserve', '-d', '--foreground', '-r', self.root_dir, 334 cmd = ['svnserve', '-d', '--foreground', '-r', self.root_dir,
389 '--listen-port=%d' % self.svn_port] 335 '--listen-port=%d' % self.svn_port]
390 if self.host == '127.0.0.1': 336 if self.host == '127.0.0.1':
391 cmd.append('--listen-host=' + self.host) 337 cmd.append('--listen-host=' + self.host)
392 self.check_port_is_free(self.svn_port) 338 self.check_port_is_free(self.svn_port)
393 self.svnserve = Popen(cmd, cwd=self.svn_repo) 339 self.svnserve = subprocess2.Popen(
340 cmd,
341 cwd=self.svn_repo,
342 stdout=subprocess2.PIPE,
343 stderr=subprocess2.PIPE)
394 wait_for_port_to_bind(self.host, self.svn_port, self.svnserve) 344 wait_for_port_to_bind(self.host, self.svn_port, self.svnserve)
395 self.svn_base = 'svn://%s:%d/svn/' % (self.host, self.svn_port) 345 self.svn_base = 'svn://%s:%d/svn/' % (self.host, self.svn_port)
396 self.populateSvn() 346 self.populateSvn()
397 self.svn_dirty = False 347 self.svn_dirty = False
398 return True 348 return True
399 349
400 def set_up_git(self): 350 def set_up_git(self):
401 """Creates git repositories and start the servers.""" 351 """Creates git repositories and start the servers."""
402 self.set_up() 352 self.set_up()
403 if self.gitdaemon: 353 if self.gitdaemon:
404 return True 354 return True
405 if sys.platform == 'win32': 355 if sys.platform == 'win32':
406 return False 356 return False
407 assert self.git_pid_file == None 357 assert self.git_pid_file == None
408 for repo in ['repo_%d' % r for r in range(1, self.NB_GIT_REPOS + 1)]: 358 for repo in ['repo_%d' % r for r in range(1, self.NB_GIT_REPOS + 1)]:
409 check_call(['git', 'init', '-q', join(self.git_root, repo)]) 359 subprocess2.check_call(['git', 'init', '-q', join(self.git_root, repo)])
410 self.git_hashes[repo] = [None] 360 self.git_hashes[repo] = [None]
411 self.git_port = find_free_port(self.host, 20000) 361 self.git_port = find_free_port(self.host, 20000)
412 self.git_base = 'git://%s:%d/git/' % (self.host, self.git_port) 362 self.git_base = 'git://%s:%d/git/' % (self.host, self.git_port)
413 # Start the daemon. 363 # Start the daemon.
414 self.git_pid_file = tempfile.NamedTemporaryFile() 364 self.git_pid_file = tempfile.NamedTemporaryFile()
415 cmd = ['git', 'daemon', 365 cmd = ['git', 'daemon',
416 '--export-all', 366 '--export-all',
417 '--reuseaddr', 367 '--reuseaddr',
418 '--base-path=' + self.root_dir, 368 '--base-path=' + self.root_dir,
419 '--pid-file=' + self.git_pid_file.name, 369 '--pid-file=' + self.git_pid_file.name,
420 '--port=%d' % self.git_port] 370 '--port=%d' % self.git_port]
421 if self.host == '127.0.0.1': 371 if self.host == '127.0.0.1':
422 cmd.append('--listen=' + self.host) 372 cmd.append('--listen=' + self.host)
423 self.check_port_is_free(self.git_port) 373 self.check_port_is_free(self.git_port)
424 self.gitdaemon = Popen(cmd, cwd=self.root_dir) 374 self.gitdaemon = subprocess2.Popen(
375 cmd,
376 cwd=self.root_dir,
377 stdout=subprocess2.PIPE,
378 stderr=subprocess2.PIPE)
425 wait_for_port_to_bind(self.host, self.git_port, self.gitdaemon) 379 wait_for_port_to_bind(self.host, self.git_port, self.gitdaemon)
426 self.populateGit() 380 self.populateGit()
427 self.git_dirty = False 381 self.git_dirty = False
428 return True 382 return True
429 383
430 def _commit_svn(self, tree): 384 def _commit_svn(self, tree):
431 self._genTree(self.svn_checkout, tree) 385 self._genTree(self.svn_checkout, tree)
432 commit_svn(self.svn_checkout, self.USERS[0][0], self.USERS[0][1]) 386 commit_svn(self.svn_checkout, self.USERS[0][0], self.USERS[0][1])
433 if self.svn_revs and self.svn_revs[-1]: 387 if self.svn_revs and self.svn_revs[-1]:
434 new_tree = self.svn_revs[-1].copy() 388 new_tree = self.svn_revs[-1].copy()
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 raise NotImplementedError() 420 raise NotImplementedError()
467 421
468 422
469 class FakeRepos(FakeReposBase): 423 class FakeRepos(FakeReposBase):
470 """Implements populateSvn() and populateGit().""" 424 """Implements populateSvn() and populateGit()."""
471 NB_GIT_REPOS = 4 425 NB_GIT_REPOS = 4
472 426
473 def populateSvn(self): 427 def populateSvn(self):
474 """Creates a few revisions of changes including DEPS files.""" 428 """Creates a few revisions of changes including DEPS files."""
475 # Repos 429 # Repos
476 check_call(['svn', 'checkout', self.svn_base, self.svn_checkout, 430 subprocess2.check_call(
477 '-q', '--non-interactive', '--no-auth-cache', 431 ['svn', 'checkout', self.svn_base, self.svn_checkout,
478 '--username', self.USERS[0][0], '--password', self.USERS[0][1]]) 432 '-q', '--non-interactive', '--no-auth-cache',
433 '--username', self.USERS[0][0], '--password', self.USERS[0][1]])
479 assert os.path.isdir(join(self.svn_checkout, '.svn')) 434 assert os.path.isdir(join(self.svn_checkout, '.svn'))
480 def file_system(rev, DEPS): 435 def file_system(rev, DEPS):
481 fs = { 436 fs = {
482 'origin': 'svn@%(rev)d\n', 437 'origin': 'svn@%(rev)d\n',
483 'trunk/origin': 'svn/trunk@%(rev)d\n', 438 'trunk/origin': 'svn/trunk@%(rev)d\n',
484 'trunk/src/origin': 'svn/trunk/src@%(rev)d\n', 439 'trunk/src/origin': 'svn/trunk/src@%(rev)d\n',
485 'trunk/src/third_party/origin': 'svn/trunk/src/third_party@%(rev)d\n', 440 'trunk/src/third_party/origin': 'svn/trunk/src/third_party@%(rev)d\n',
486 'trunk/other/origin': 'src/trunk/other@%(rev)d\n', 441 'trunk/other/origin': 'src/trunk/other@%(rev)d\n',
487 'trunk/third_party/origin': 'svn/trunk/third_party@%(rev)d\n', 442 'trunk/third_party/origin': 'svn/trunk/third_party@%(rev)d\n',
488 'trunk/third_party/foo/origin': 'svn/trunk/third_party/foo@%(rev)d\n', 443 'trunk/third_party/foo/origin': 'svn/trunk/third_party/foo@%(rev)d\n',
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 fake.set_up_git() 732 fake.set_up_git()
778 print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.') 733 print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.')
779 sys.stdin.readline() 734 sys.stdin.readline()
780 except KeyboardInterrupt: 735 except KeyboardInterrupt:
781 trial_dir.TrialDir.SHOULD_LEAK.leak = True 736 trial_dir.TrialDir.SHOULD_LEAK.leak = True
782 return 0 737 return 0
783 738
784 739
785 if __name__ == '__main__': 740 if __name__ == '__main__':
786 sys.exit(main(sys.argv)) 741 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « subprocess2.py ('k') | tests/gclient_smoketest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698