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

Side by Side Diff: tests/fake_repos.py

Issue 6725042: Forcibly uses a non-standard port for local svn and git servers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Fix presubmit checks Created 9 years, 9 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 | « gcl.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/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 datetime 9 import datetime
10 import errno 10 import errno
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 def commit_git(repo): 145 def commit_git(repo):
146 """Commits the changes and returns the new hash.""" 146 """Commits the changes and returns the new hash."""
147 check_call(['git', 'add', '-A', '-f'], cwd=repo) 147 check_call(['git', 'add', '-A', '-f'], cwd=repo)
148 check_call(['git', 'commit', '-q', '--message', 'foo'], cwd=repo) 148 check_call(['git', 'commit', '-q', '--message', 'foo'], cwd=repo)
149 rev = Popen(['git', 'show-ref', '--head', 'HEAD'], 149 rev = Popen(['git', 'show-ref', '--head', 'HEAD'],
150 cwd=repo).communicate()[0].split(' ', 1)[0] 150 cwd=repo).communicate()[0].split(' ', 1)[0]
151 logging.debug('At revision %s' % rev) 151 logging.debug('At revision %s' % rev)
152 return rev 152 return rev
153 153
154 154
155 def test_port(host, port):
156 s = socket.socket()
157 try:
158 return s.connect_ex((host, port)) == 0
159 finally:
160 s.close()
161
162
163 def find_free_port(host, base_port):
164 """Finds a listening port free to listen to."""
165 while base_port < (2<<16):
166 if not test_port(host, base_port):
167 return base_port
168 base_port += 1
169 assert False, 'Having issues finding an available port'
170
171
172 def wait_for_port_to_bind(host, port, process):
173 sock = socket.socket()
174
175 if sys.platform == 'darwin':
176 # On Mac SnowLeopard, if we attempt to connect to the socket
177 # immediately, it fails with EINVAL and never gets a chance to
178 # connect (putting us into a hard spin and then failing).
179 # Linux doesn't need this.
180 time.sleep(0.1)
181
182 try:
183 start = datetime.datetime.utcnow()
184 maxdelay = datetime.timedelta(seconds=30)
185 while (datetime.datetime.utcnow() - start) < maxdelay:
186 try:
187 sock.connect((host, port))
188 logging.debug('%d is now bound' % port)
189 return
190 except EnvironmentError:
191 pass
192 logging.debug('%d is still not bound' % port)
193 finally:
194 sock.close()
195 # The process failed to bind. Kill it and dump its ouput.
196 process.kill()
197 logging.error('%s' % process.communicate()[0])
198 assert False, '%d is still not bound' % port
199
200
201 def wait_for_port_to_free(host, port):
202 start = datetime.datetime.utcnow()
203 maxdelay = datetime.timedelta(seconds=30)
204 while (datetime.datetime.utcnow() - start) < maxdelay:
205 try:
206 sock = socket.socket()
207 sock.connect((host, port))
208 logging.debug('%d was bound, waiting to free' % port)
209 except EnvironmentError:
210 logging.debug('%d now free' % port)
211 return
212 finally:
213 sock.close()
214 assert False, '%d is still bound' % port
215
216
155 _FAKE_LOADED = False 217 _FAKE_LOADED = False
156 218
157 class FakeReposBase(object): 219 class FakeReposBase(object):
158 """Generate both svn and git repositories to test gclient functionality. 220 """Generate both svn and git repositories to test gclient functionality.
159 221
160 Many DEPS functionalities need to be tested: Var, File, From, deps_os, hooks, 222 Many DEPS functionalities need to be tested: Var, File, From, deps_os, hooks,
161 use_relative_paths. 223 use_relative_paths.
162 224
163 And types of dependencies: Relative urls, Full urls, both svn and git. 225 And types of dependencies: Relative urls, Full urls, both svn and git.
164 226
(...skipping 23 matching lines...) Expand all
188 # For consistency with self.svn_revs, it is 1-based too. 250 # For consistency with self.svn_revs, it is 1-based too.
189 self.git_hashes = {} 251 self.git_hashes = {}
190 self.svnserve = None 252 self.svnserve = None
191 self.gitdaemon = None 253 self.gitdaemon = None
192 self.git_pid_file = None 254 self.git_pid_file = None
193 self.git_root = None 255 self.git_root = None
194 self.svn_checkout = None 256 self.svn_checkout = None
195 self.svn_repo = None 257 self.svn_repo = None
196 self.git_dirty = False 258 self.git_dirty = False
197 self.svn_dirty = False 259 self.svn_dirty = False
198 self.svn_base = 'svn://%s/svn/' % self.host 260 self.svn_port = None
199 self.git_base = 'git://%s/git/' % self.host 261 self.git_port = None
200 self.svn_port = 3690 262 self.svn_base = None
201 self.git_port = 9418 263 self.git_base = None
202 264
203 @property 265 @property
204 def root_dir(self): 266 def root_dir(self):
205 return self.trial.root_dir 267 return self.trial.root_dir
206 268
207 def set_up(self): 269 def set_up(self):
208 """All late initialization comes here.""" 270 """All late initialization comes here."""
209 self.cleanup_dirt() 271 self.cleanup_dirt()
210 if not self.root_dir: 272 if not self.root_dir:
211 try: 273 try:
(...skipping 25 matching lines...) Expand all
237 self.trial = None 299 self.trial = None
238 300
239 def tear_down_svn(self): 301 def tear_down_svn(self):
240 if self.svnserve: 302 if self.svnserve:
241 logging.debug('Killing svnserve pid %s' % self.svnserve.pid) 303 logging.debug('Killing svnserve pid %s' % self.svnserve.pid)
242 try: 304 try:
243 self.svnserve.kill() 305 self.svnserve.kill()
244 except OSError, e: 306 except OSError, e:
245 if e.errno != errno.ESRCH: # no such process 307 if e.errno != errno.ESRCH: # no such process
246 raise 308 raise
247 self.wait_for_port_to_free(self.svn_port) 309 wait_for_port_to_free(self.host, self.svn_port)
248 self.svnserve = None 310 self.svnserve = None
311 self.svn_port = None
312 self.svn_base = None
249 if not self.trial.SHOULD_LEAK: 313 if not self.trial.SHOULD_LEAK:
250 logging.debug('Removing %s' % self.svn_repo) 314 logging.debug('Removing %s' % self.svn_repo)
251 gclient_utils.rmtree(self.svn_repo) 315 gclient_utils.rmtree(self.svn_repo)
252 logging.debug('Removing %s' % self.svn_checkout) 316 logging.debug('Removing %s' % self.svn_checkout)
253 gclient_utils.rmtree(self.svn_checkout) 317 gclient_utils.rmtree(self.svn_checkout)
254 else: 318 else:
255 return False 319 return False
256 return True 320 return True
257 321
258 def tear_down_git(self): 322 def tear_down_git(self):
259 if self.gitdaemon: 323 if self.gitdaemon:
260 logging.debug('Killing git-daemon pid %s' % self.gitdaemon.pid) 324 logging.debug('Killing git-daemon pid %s' % self.gitdaemon.pid)
261 self.gitdaemon.kill() 325 self.gitdaemon.kill()
262 self.gitdaemon = None 326 self.gitdaemon = None
263 if self.git_pid_file: 327 if self.git_pid_file:
264 pid = int(self.git_pid_file.read()) 328 pid = int(self.git_pid_file.read())
265 self.git_pid_file.close() 329 self.git_pid_file.close()
266 logging.debug('Killing git daemon pid %s' % pid) 330 logging.debug('Killing git daemon pid %s' % pid)
267 kill_pid(pid) 331 kill_pid(pid)
268 self.git_pid_file = None 332 self.git_pid_file = None
269 self.wait_for_port_to_free(self.git_port) 333 wait_for_port_to_free(self.host, self.git_port)
334 self.git_port = None
335 self.git_base = None
270 if not self.trial.SHOULD_LEAK: 336 if not self.trial.SHOULD_LEAK:
271 logging.debug('Removing %s' % self.git_root) 337 logging.debug('Removing %s' % self.git_root)
272 gclient_utils.rmtree(self.git_root) 338 gclient_utils.rmtree(self.git_root)
273 else: 339 else:
274 return False 340 return False
275 return True 341 return True
276 342
277 @staticmethod 343 @staticmethod
278 def _genTree(root, tree_dict): 344 def _genTree(root, tree_dict):
279 """For a dictionary of file contents, generate a filesystem.""" 345 """For a dictionary of file contents, generate a filesystem."""
(...skipping 29 matching lines...) Expand all
309 text += ''.join('%s = %s\n' % (usr, pwd) for usr, pwd in self.USERS) 375 text += ''.join('%s = %s\n' % (usr, pwd) for usr, pwd in self.USERS)
310 write(join(self.svn_repo, 'conf', 'passwd'), text) 376 write(join(self.svn_repo, 'conf', 'passwd'), text)
311 377
312 # Mac 10.6 ships with a buggy subversion build and we need this line 378 # Mac 10.6 ships with a buggy subversion build and we need this line
313 # to work around the bug. 379 # to work around the bug.
314 write(join(self.svn_repo, 'db', 'fsfs.conf'), 380 write(join(self.svn_repo, 'db', 'fsfs.conf'),
315 '[rep-sharing]\n' 381 '[rep-sharing]\n'
316 'enable-rep-sharing = false\n') 382 'enable-rep-sharing = false\n')
317 383
318 # Start the daemon. 384 # Start the daemon.
319 cmd = ['svnserve', '-d', '--foreground', '-r', self.root_dir] 385 self.svn_port = find_free_port(self.host, 10000)
386 cmd = ['svnserve', '-d', '--foreground', '-r', self.root_dir,
387 '--listen-port=%d' % self.svn_port]
320 if self.host == '127.0.0.1': 388 if self.host == '127.0.0.1':
321 cmd.append('--listen-host=' + self.host) 389 cmd.append('--listen-host=' + self.host)
322 self.check_port_is_free(self.svn_port) 390 self.check_port_is_free(self.svn_port)
323 self.svnserve = Popen(cmd, cwd=self.svn_repo) 391 self.svnserve = Popen(cmd, cwd=self.svn_repo)
324 self.wait_for_port_to_bind(self.svn_port, self.svnserve) 392 wait_for_port_to_bind(self.host, self.svn_port, self.svnserve)
393 self.svn_base = 'svn://%s:%d/svn/' % (self.host, self.svn_port)
325 self.populateSvn() 394 self.populateSvn()
326 self.svn_dirty = False 395 self.svn_dirty = False
327 return True 396 return True
328 397
329 def set_up_git(self): 398 def set_up_git(self):
330 """Creates git repositories and start the servers.""" 399 """Creates git repositories and start the servers."""
331 self.set_up() 400 self.set_up()
332 if self.gitdaemon: 401 if self.gitdaemon:
333 return True 402 return True
334 if sys.platform == 'win32': 403 if sys.platform == 'win32':
335 return False 404 return False
336 assert self.git_pid_file == None 405 assert self.git_pid_file == None
337 for repo in ['repo_%d' % r for r in range(1, self.NB_GIT_REPOS + 1)]: 406 for repo in ['repo_%d' % r for r in range(1, self.NB_GIT_REPOS + 1)]:
338 check_call(['git', 'init', '-q', join(self.git_root, repo)]) 407 check_call(['git', 'init', '-q', join(self.git_root, repo)])
339 self.git_hashes[repo] = [None] 408 self.git_hashes[repo] = [None]
340 # Unlike svn, populate git before starting the server. 409 self.git_port = find_free_port(self.host, 20000)
341 self.populateGit() 410 self.git_base = 'git://%s:%d/git/' % (self.host, self.git_port)
342 # Start the daemon. 411 # Start the daemon.
343 self.git_pid_file = tempfile.NamedTemporaryFile() 412 self.git_pid_file = tempfile.NamedTemporaryFile()
344 cmd = ['git', 'daemon', 413 cmd = ['git', 'daemon',
345 '--export-all', 414 '--export-all',
346 '--reuseaddr', 415 '--reuseaddr',
347 '--base-path=' + self.root_dir, 416 '--base-path=' + self.root_dir,
348 '--pid-file=' + self.git_pid_file.name] 417 '--pid-file=' + self.git_pid_file.name,
418 '--port=%d' % self.git_port]
349 if self.host == '127.0.0.1': 419 if self.host == '127.0.0.1':
350 cmd.append('--listen=' + self.host) 420 cmd.append('--listen=' + self.host)
351 self.check_port_is_free(self.git_port) 421 self.check_port_is_free(self.git_port)
352 self.gitdaemon = Popen(cmd, cwd=self.root_dir) 422 self.gitdaemon = Popen(cmd, cwd=self.root_dir)
353 self.wait_for_port_to_bind(self.git_port, self.gitdaemon) 423 wait_for_port_to_bind(self.host, self.git_port, self.gitdaemon)
424 self.populateGit()
354 self.git_dirty = False 425 self.git_dirty = False
355 return True 426 return True
356 427
357 def _commit_svn(self, tree): 428 def _commit_svn(self, tree):
358 self._genTree(self.svn_checkout, tree) 429 self._genTree(self.svn_checkout, tree)
359 commit_svn(self.svn_checkout, self.USERS[0][0], self.USERS[0][1]) 430 commit_svn(self.svn_checkout, self.USERS[0][0], self.USERS[0][1])
360 if self.svn_revs and self.svn_revs[-1]: 431 if self.svn_revs and self.svn_revs[-1]:
361 new_tree = self.svn_revs[-1].copy() 432 new_tree = self.svn_revs[-1].copy()
362 new_tree.update(tree) 433 new_tree.update(tree)
363 else: 434 else:
(...skipping 15 matching lines...) Expand all
379 sock = socket.socket() 450 sock = socket.socket()
380 try: 451 try:
381 sock.connect((self.host, port)) 452 sock.connect((self.host, port))
382 # It worked, throw. 453 # It worked, throw.
383 assert False, '%d shouldn\'t be bound' % port 454 assert False, '%d shouldn\'t be bound' % port
384 except EnvironmentError: 455 except EnvironmentError:
385 pass 456 pass
386 finally: 457 finally:
387 sock.close() 458 sock.close()
388 459
389 def wait_for_port_to_bind(self, port, process):
390 sock = socket.socket()
391
392 if sys.platform == 'darwin':
393 # On Mac SnowLeopard, if we attempt to connect to the socket
394 # immediately, it fails with EINVAL and never gets a chance to
395 # connect (putting us into a hard spin and then failing).
396 # Linux doesn't need this.
397 time.sleep(0.1)
398
399 try:
400 start = datetime.datetime.utcnow()
401 maxdelay = datetime.timedelta(seconds=30)
402 while (datetime.datetime.utcnow() - start) < maxdelay:
403 try:
404 sock.connect((self.host, port))
405 logging.debug('%d is now bound' % port)
406 return
407 except EnvironmentError:
408 pass
409 logging.debug('%d is still not bound' % port)
410 finally:
411 sock.close()
412 # The process failed to bind. Kill it and dump its ouput.
413 process.kill()
414 logging.error('%s' % process.communicate()[0])
415 assert False, '%d is still not bound' % port
416
417 def wait_for_port_to_free(self, port):
418 start = datetime.datetime.utcnow()
419 maxdelay = datetime.timedelta(seconds=30)
420 while (datetime.datetime.utcnow() - start) < maxdelay:
421 try:
422 sock = socket.socket()
423 sock.connect((self.host, port))
424 logging.debug('%d was bound, waiting to free' % port)
425 except EnvironmentError:
426 logging.debug('%d now free' % port)
427 return
428 finally:
429 sock.close()
430 assert False, '%d is still bound' % port
431
432 def populateSvn(self): 460 def populateSvn(self):
433 raise NotImplementedError() 461 raise NotImplementedError()
434 462
435 def populateGit(self): 463 def populateGit(self):
436 raise NotImplementedError() 464 raise NotImplementedError()
437 465
438 466
439 class FakeRepos(FakeReposBase): 467 class FakeRepos(FakeReposBase):
440 """Implements populateSvn() and populateGit().""" 468 """Implements populateSvn() and populateGit()."""
441 NB_GIT_REPOS = 4 469 NB_GIT_REPOS = 4
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 fake.set_up_git() 775 fake.set_up_git()
748 print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.') 776 print('Fake setup, press enter to quit or Ctrl-C to keep the checkouts.')
749 sys.stdin.readline() 777 sys.stdin.readline()
750 except KeyboardInterrupt: 778 except KeyboardInterrupt:
751 trial_dir.TrialDir.SHOULD_LEAK.leak = True 779 trial_dir.TrialDir.SHOULD_LEAK.leak = True
752 return 0 780 return 0
753 781
754 782
755 if __name__ == '__main__': 783 if __name__ == '__main__':
756 sys.exit(main(sys.argv)) 784 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « gcl.py ('k') | tests/gcl_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698