run-test: ensure the test ports are available before launching test
I'm running into a systematic issue because there is always some port taken in the
1500-wide range of ports used by the test (3 for each test file).
--- a/tests/run-tests.py Fri May 08 18:11:26 2015 +0900
+++ b/tests/run-tests.py Thu May 07 17:14:00 2015 -0700
@@ -49,6 +49,7 @@
import shutil
import subprocess
import signal
+import socket
import sys
import tempfile
import time
@@ -78,6 +79,18 @@
wifexited = getattr(os, "WIFEXITED", lambda x: False)
+def checkportisavailable(port):
+ """return true if a port seems free to bind on localhost"""
+ try:
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.bind(('localhost', port))
+ s.close()
+ return True
+ except socket.error, exc:
+ if not exc.errno == errno.EADDRINUSE:
+ raise
+ return False
+
closefds = os.name == 'posix'
def Popen4(cmd, wd, timeout, env=None):
processlock.acquire()
@@ -1608,6 +1621,8 @@
self._coveragefile = None
self._createdfiles = []
self._hgpath = None
+ self._portoffset = 0
+ self._ports = {}
def run(self, args, parser=None):
"""Run the test suite."""
@@ -1812,6 +1827,24 @@
if warned:
return 80
+ def _getport(self, count):
+ port = self._ports.get(count) # do we have a cached entry?
+ if port is None:
+ port = self.options.port + self._portoffset
+ portneeded = 3
+ # above 100 tries we just give up and let test reports failure
+ for tries in xrange(100):
+ allfree = True
+ for idx in xrange(portneeded):
+ if not checkportisavailable(port + idx):
+ allfree = False
+ break
+ self._portoffset += portneeded
+ if allfree:
+ break
+ self._ports[count] = port
+ return port
+
def _gettest(self, test, count):
"""Obtain a Test by looking at its filename.
@@ -1833,7 +1866,7 @@
keeptmpdir=self.options.keep_tmpdir,
debug=self.options.debug,
timeout=self.options.timeout,
- startport=self.options.port + count * 3,
+ startport=self._getport(count),
extraconfigopts=self.options.extra_config_opt,
py3kwarnings=self.options.py3k_warnings,
shell=self.options.shell)