| 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 """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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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)) |
| OLD | NEW |