diff --git a/gcl.py b/gcl.py index 54c721cfb..76a217c44 100755 --- a/gcl.py +++ b/gcl.py @@ -42,7 +42,6 @@ from scm import SVN import fix_encoding import gclient_utils -import owners import presubmit_support __version__ = '1.2' diff --git a/tests/fake_repos.py b/tests/fake_repos.py index 7706bb253..09d873c8e 100755 --- a/tests/fake_repos.py +++ b/tests/fake_repos.py @@ -152,6 +152,68 @@ def commit_git(repo): return rev +def test_port(host, port): + s = socket.socket() + try: + return s.connect_ex((host, port)) == 0 + finally: + s.close() + + +def find_free_port(host, base_port): + """Finds a listening port free to listen to.""" + while base_port < (2<<16): + if not test_port(host, base_port): + return base_port + base_port += 1 + assert False, 'Having issues finding an available port' + + +def wait_for_port_to_bind(host, port, process): + sock = socket.socket() + + if sys.platform == 'darwin': + # On Mac SnowLeopard, if we attempt to connect to the socket + # immediately, it fails with EINVAL and never gets a chance to + # connect (putting us into a hard spin and then failing). + # Linux doesn't need this. + time.sleep(0.1) + + try: + start = datetime.datetime.utcnow() + maxdelay = datetime.timedelta(seconds=30) + while (datetime.datetime.utcnow() - start) < maxdelay: + try: + sock.connect((host, port)) + logging.debug('%d is now bound' % port) + return + except EnvironmentError: + pass + logging.debug('%d is still not bound' % port) + finally: + sock.close() + # The process failed to bind. Kill it and dump its ouput. + process.kill() + logging.error('%s' % process.communicate()[0]) + assert False, '%d is still not bound' % port + + +def wait_for_port_to_free(host, port): + start = datetime.datetime.utcnow() + maxdelay = datetime.timedelta(seconds=30) + while (datetime.datetime.utcnow() - start) < maxdelay: + try: + sock = socket.socket() + sock.connect((host, port)) + logging.debug('%d was bound, waiting to free' % port) + except EnvironmentError: + logging.debug('%d now free' % port) + return + finally: + sock.close() + assert False, '%d is still bound' % port + + _FAKE_LOADED = False class FakeReposBase(object): @@ -195,10 +257,10 @@ class FakeReposBase(object): self.svn_repo = None self.git_dirty = False self.svn_dirty = False - self.svn_base = 'svn://%s/svn/' % self.host - self.git_base = 'git://%s/git/' % self.host - self.svn_port = 3690 - self.git_port = 9418 + self.svn_port = None + self.git_port = None + self.svn_base = None + self.git_base = None @property def root_dir(self): @@ -244,8 +306,10 @@ class FakeReposBase(object): except OSError, e: if e.errno != errno.ESRCH: # no such process raise - self.wait_for_port_to_free(self.svn_port) + wait_for_port_to_free(self.host, self.svn_port) self.svnserve = None + self.svn_port = None + self.svn_base = None if not self.trial.SHOULD_LEAK: logging.debug('Removing %s' % self.svn_repo) gclient_utils.rmtree(self.svn_repo) @@ -266,7 +330,9 @@ class FakeReposBase(object): logging.debug('Killing git daemon pid %s' % pid) kill_pid(pid) self.git_pid_file = None - self.wait_for_port_to_free(self.git_port) + wait_for_port_to_free(self.host, self.git_port) + self.git_port = None + self.git_base = None if not self.trial.SHOULD_LEAK: logging.debug('Removing %s' % self.git_root) gclient_utils.rmtree(self.git_root) @@ -316,12 +382,15 @@ class FakeReposBase(object): 'enable-rep-sharing = false\n') # Start the daemon. - cmd = ['svnserve', '-d', '--foreground', '-r', self.root_dir] + self.svn_port = find_free_port(self.host, 10000) + cmd = ['svnserve', '-d', '--foreground', '-r', self.root_dir, + '--listen-port=%d' % self.svn_port] if self.host == '127.0.0.1': cmd.append('--listen-host=' + self.host) self.check_port_is_free(self.svn_port) self.svnserve = Popen(cmd, cwd=self.svn_repo) - self.wait_for_port_to_bind(self.svn_port, self.svnserve) + wait_for_port_to_bind(self.host, self.svn_port, self.svnserve) + self.svn_base = 'svn://%s:%d/svn/' % (self.host, self.svn_port) self.populateSvn() self.svn_dirty = False return True @@ -337,20 +406,22 @@ class FakeReposBase(object): for repo in ['repo_%d' % r for r in range(1, self.NB_GIT_REPOS + 1)]: check_call(['git', 'init', '-q', join(self.git_root, repo)]) self.git_hashes[repo] = [None] - # Unlike svn, populate git before starting the server. - self.populateGit() + self.git_port = find_free_port(self.host, 20000) + self.git_base = 'git://%s:%d/git/' % (self.host, self.git_port) # Start the daemon. self.git_pid_file = tempfile.NamedTemporaryFile() cmd = ['git', 'daemon', '--export-all', '--reuseaddr', '--base-path=' + self.root_dir, - '--pid-file=' + self.git_pid_file.name] + '--pid-file=' + self.git_pid_file.name, + '--port=%d' % self.git_port] if self.host == '127.0.0.1': cmd.append('--listen=' + self.host) self.check_port_is_free(self.git_port) self.gitdaemon = Popen(cmd, cwd=self.root_dir) - self.wait_for_port_to_bind(self.git_port, self.gitdaemon) + wait_for_port_to_bind(self.host, self.git_port, self.gitdaemon) + self.populateGit() self.git_dirty = False return True @@ -386,49 +457,6 @@ class FakeReposBase(object): finally: sock.close() - def wait_for_port_to_bind(self, port, process): - sock = socket.socket() - - if sys.platform == 'darwin': - # On Mac SnowLeopard, if we attempt to connect to the socket - # immediately, it fails with EINVAL and never gets a chance to - # connect (putting us into a hard spin and then failing). - # Linux doesn't need this. - time.sleep(0.1) - - try: - start = datetime.datetime.utcnow() - maxdelay = datetime.timedelta(seconds=30) - while (datetime.datetime.utcnow() - start) < maxdelay: - try: - sock.connect((self.host, port)) - logging.debug('%d is now bound' % port) - return - except EnvironmentError: - pass - logging.debug('%d is still not bound' % port) - finally: - sock.close() - # The process failed to bind. Kill it and dump its ouput. - process.kill() - logging.error('%s' % process.communicate()[0]) - assert False, '%d is still not bound' % port - - def wait_for_port_to_free(self, port): - start = datetime.datetime.utcnow() - maxdelay = datetime.timedelta(seconds=30) - while (datetime.datetime.utcnow() - start) < maxdelay: - try: - sock = socket.socket() - sock.connect((self.host, port)) - logging.debug('%d was bound, waiting to free' % port) - except EnvironmentError: - logging.debug('%d now free' % port) - return - finally: - sock.close() - assert False, '%d is still bound' % port - def populateSvn(self): raise NotImplementedError() diff --git a/tests/gcl_unittest.py b/tests/gcl_unittest.py index 35bd6a98b..c2dbbbed2 100755 --- a/tests/gcl_unittest.py +++ b/tests/gcl_unittest.py @@ -93,7 +93,7 @@ class GclUnittest(GclTestsBase): 'attrs', 'breakpad', 'defer_attributes', 'fix_encoding', 'gclient_utils', 'getpass', 'json', 'main', 'need_change', 'need_change_and_args', 'no_args', - 'optparse', 'os', 'owners', 'presubmit_support', 'random', 're', + 'optparse', 'os', 'presubmit_support', 'random', 're', 'string', 'subprocess', 'sys', 'tempfile', 'time', 'upload', 'urllib2', ] diff --git a/tests/gclient_smoketest.py b/tests/gclient_smoketest.py index c6e381e80..3fbff3651 100755 --- a/tests/gclient_smoketest.py +++ b/tests/gclient_smoketest.py @@ -142,7 +142,15 @@ class GClientSmokeBase(FakeReposTestBase): class GClientSmoke(GClientSmokeBase): - """Doesn't require neither svnserve nor git-daemon.""" + """Doesn't require either svnserve nor git-daemon.""" + @property + def svn_base(self): + return 'svn://random.server/svn/' + + @property + def git_base(self): + return 'git://random.server/git/' + def testHelp(self): """testHelp: make sure no new command was added.""" result = self.gclient(['help']) @@ -181,24 +189,24 @@ class GClientSmoke(GClientSmokeBase): self.checkString(expected, open(p, 'rU').read()) test(['config', self.svn_base + 'trunk/src/'], - 'solutions = [\n' - ' { "name" : "src",\n' - ' "url" : "svn://127.0.0.1/svn/trunk/src",\n' - ' "custom_deps" : {\n' - ' },\n' - ' "safesync_url": "",\n' - ' },\n' - ']\n') + ('solutions = [\n' + ' { "name" : "src",\n' + ' "url" : "%strunk/src",\n' + ' "custom_deps" : {\n' + ' },\n' + ' "safesync_url": "",\n' + ' },\n' + ']\n') % self.svn_base) test(['config', self.git_base + 'repo_1', '--name', 'src'], - 'solutions = [\n' - ' { "name" : "src",\n' - ' "url" : "git://127.0.0.1/git/repo_1",\n' - ' "custom_deps" : {\n' - ' },\n' - ' "safesync_url": "",\n' - ' },\n' - ']\n') + ('solutions = [\n' + ' { "name" : "src",\n' + ' "url" : "%srepo_1",\n' + ' "custom_deps" : {\n' + ' },\n' + ' "safesync_url": "",\n' + ' },\n' + ']\n') % self.git_base) test(['config', 'foo', 'faa'], 'solutions = [\n' @@ -1075,7 +1083,7 @@ class GClientSmokeFromCheckout(GClientSmokeBase): if self.enabled: usr, pwd = self.FAKE_REPOS.USERS[0] check_call( - ['svn', 'checkout', 'svn://127.0.0.1/svn/trunk/webkit', + ['svn', 'checkout', self.svn_base + '/trunk/webkit', self.root_dir, '-q', '--non-interactive', '--no-auth-cache', '--username', usr, '--password', pwd]) @@ -1137,13 +1145,13 @@ class GClientSmokeFromCheckout(GClientSmokeBase): self.gclient(['sync', '--deps', 'mac']) results = self.gclient(['revinfo', '--deps', 'mac']) expected = ( - './: None\nfoo/bar: svn://127.0.0.1/svn/trunk/third_party/foo@1\n', + './: None\nfoo/bar: %strunk/third_party/foo@1\n' % self.svn_base, '', 0) self.check(expected, results) # TODO(maruel): To be added after the refactor. #results = self.gclient(['revinfo', '--snapshot']) #expected = ( - # './: None\nfoo/bar: svn://127.0.0.1/svn/trunk/third_party/foo@1\n', + # './: None\nfoo/bar: %strunk/third_party/foo@1\n' % self.svn_base, # '', 0) #self.check(expected, results)