# HG changeset patch # User Jun Wu # Date 1458519486 25200 # Node ID 759d167f75cf04e3a3691a418db7efa64b93e0fc # Parent 695c666f42ff9fea79057af3afdd942f9211c5d8 run-tests: use different chg socket directories for different tests Before this patch, if --chg or --with-chg is specified, all tests are using the same chgserver socket. Since the chg client holds a lock when it starts a new server, and every test needs at least a new chg server due to different HGRCPATH affecting the confighash, the result is a lot of tests will be timed out if -j is large (for example, 50 or 100). This patch solves the issue by using different chg socket directories for different tests. diff -r 695c666f42ff -r 759d167f75cf tests/run-tests.py --- a/tests/run-tests.py Mon Mar 21 20:56:46 2016 +0000 +++ b/tests/run-tests.py Sun Mar 20 17:18:06 2016 -0700 @@ -485,7 +485,7 @@ timeout=defaults['timeout'], startport=defaults['port'], extraconfigopts=None, py3kwarnings=False, shell=None, hgcommand=None, - slowtimeout=defaults['slowtimeout']): + slowtimeout=defaults['slowtimeout'], usechg=False): """Create a test from parameters. path is the full path to the file defining the test. @@ -532,6 +532,7 @@ self._py3kwarnings = py3kwarnings self._shell = _bytespath(shell) self._hgcommand = hgcommand or b'hg' + self._usechg = usechg self._aborted = False self._daemonpids = [] @@ -540,6 +541,7 @@ self._out = None self._skipped = None self._testtmp = None + self._chgsockdir = None # If we're not in --debug mode and reference output file exists, # check test output against it. @@ -576,8 +578,8 @@ if e.errno != errno.EEXIST: raise - self._testtmp = os.path.join(self._threadtmp, - os.path.basename(self.path)) + name = os.path.basename(self.path) + self._testtmp = os.path.join(self._threadtmp, name) os.mkdir(self._testtmp) # Remove any previous output files. @@ -591,6 +593,11 @@ if e.errno != errno.ENOENT: raise + if self._usechg: + self._chgsockdir = os.path.join(self._threadtmp, + b'%s.chgsock' % name) + os.mkdir(self._chgsockdir) + def run(self, result): """Run this test and report results against a TestResult instance.""" # This function is extremely similar to unittest.TestCase.run(). Once @@ -734,6 +741,11 @@ shutil.rmtree(self._testtmp, True) shutil.rmtree(self._threadtmp, True) + if self._usechg: + # chgservers will stop automatically after they find the socket + # files are deleted + shutil.rmtree(self._chgsockdir, True) + if (self._ret != 0 or self._out != self._refout) and not self._skipped \ and not self._debug and self._out: f = open(self.errpath, 'wb') @@ -823,6 +835,9 @@ if k.startswith('HG_'): del env[k] + if self._usechg: + env['CHGSOCKNAME'] = os.path.join(self._chgsockdir, b'server') + return env def _createhgrc(self, path): @@ -1910,7 +1925,6 @@ self._createdfiles = [] self._hgcommand = None self._hgpath = None - self._chgsockdir = None self._portoffset = 0 self._ports = {} @@ -2035,12 +2049,9 @@ self._tmpbindir = self._bindir self._pythondir = os.path.join(self._installdir, b"lib", b"python") - # set up crafted chg environment, then replace "hg" command by "chg" + # set CHGHG, then replace "hg" command by "chg" chgbindir = self._bindir if self.options.chg or self.options.with_chg: - self._chgsockdir = d = os.path.join(self._hgtmp, b'chgsock') - os.mkdir(d) - osenvironb[b'CHGSOCKNAME'] = os.path.join(d, b"server") osenvironb[b'CHGHG'] = os.path.join(self._bindir, self._hgcommand) if self.options.chg: self._hgcommand = b'chg' @@ -2234,15 +2245,13 @@ extraconfigopts=self.options.extra_config_opt, py3kwarnings=self.options.py3k_warnings, shell=self.options.shell, - hgcommand=self._hgcommand) + hgcommand=self._hgcommand, + usechg=bool(self.options.with_chg or self.options.chg)) t.should_reload = True return t def _cleanup(self): """Clean up state from this test invocation.""" - if self._chgsockdir: - self._killchgdaemons() - if self.options.keep_tmpdir: return @@ -2460,13 +2469,6 @@ sys.stdout.write(out) sys.exit(1) - def _killchgdaemons(self): - """Kill all background chg command servers spawned by tests""" - for f in os.listdir(self._chgsockdir): - if '.' in f: - continue - os.unlink(os.path.join(self._chgsockdir, f)) - def _outputcoverage(self): """Produce code coverage output.""" from coverage import coverage