diff --git a/tests/hghave.py b/tests/hghave.py index 71dab394b0187077c84c6790b999fbef8e259d7e_dGVzdHMvaGdoYXZlLnB5..658c0979a77e6873e0653b3aa4712e4b8db16635_dGVzdHMvaGdoYXZlLnB5 100755 --- a/tests/hghave.py +++ b/tests/hghave.py @@ -29,8 +29,8 @@ if sys.version_info[0] >= 3: - def _bytespath(p): + def _sys2bytes(p): if p is None: return p return p.encode('utf-8') @@ -33,8 +33,8 @@ if p is None: return p return p.encode('utf-8') - def _strpath(p): + def _bytes2sys(p): if p is None: return p return p.decode('utf-8') @@ -42,6 +42,6 @@ else: - def _bytespath(p): + def _sys2bytes(p): return p @@ -46,6 +46,6 @@ return p - _strpath = _bytespath + _bytes2sys = _sys2bytes def check(name, desc): @@ -307,10 +307,10 @@ return False -def gethgversion(): +def _gethgversion(): m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)') if not m: return (0, 0) return (int(m.group(1)), int(m.group(2))) @@ -311,9 +311,19 @@ m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)') if not m: return (0, 0) return (int(m.group(1)), int(m.group(2))) +_hgversion = None + + +def gethgversion(): + global _hgversion + if _hgversion is None: + _hgversion = _gethgversion() + return _hgversion + + @checkvers( "hg", "Mercurial >= %s", list([(1.0 * x) / 10 for x in range(9, 99)]) ) @@ -322,6 +332,17 @@ return gethgversion() >= (int(major), int(minor)) +@check("rust", "Using the Rust extensions") +def has_rust(): + """Check is the mercurial currently running is using some rust code""" + cmd = 'hg debuginstall --quiet 2>&1' + match = br'checking module policy \(([^)]+)\)' + policy = matchoutput(cmd, match) + if not policy: + return False + return b'rust' in policy.group(1) + + @check("hg08", "Mercurial >= 0.8") def has_hg08(): if checks["hg09"][0](): @@ -360,6 +381,17 @@ return (int(m.group(1)), int(m.group(2))) +@check("pygit2", "pygit2 Python library") +def has_git(): + try: + import pygit2 + + pygit2.Oid # silence unused import + return True + except ImportError: + return False + + # https://github.com/git-lfs/lfs-test-server @check("lfs-test-server", "git-lfs test server") def has_lfsserver(): @@ -451,7 +483,7 @@ os.close(fh) name = tempfile.mktemp(dir='.', prefix=tempprefix) try: - util.oslink(_bytespath(fn), _bytespath(name)) + util.oslink(_sys2bytes(fn), _sys2bytes(name)) os.unlink(name) return True except OSError: @@ -542,11 +574,14 @@ @check("pyflakes", "Pyflakes python linter") def has_pyflakes(): - return matchoutput( - "sh -c \"echo 'import re' 2>&1 | pyflakes\"", - br"<stdin>:1: 're' imported but unused", - True, - ) + try: + import pyflakes + + pyflakes.__version__ + except ImportError: + return False + else: + return True @check("pylint", "Pylint python linter") @@ -556,7 +591,7 @@ @check("clang-format", "clang-format C code formatter") def has_clang_format(): - m = matchoutput('clang-format --version', br'clang-format version (\d)') + m = matchoutput('clang-format --version', br'clang-format version (\d+)') # style changed somewhere between 4.x and 6.x return m and int(m.group(1)) >= 6 @@ -610,27 +645,8 @@ return False -@check("sslcontext", "python >= 2.7.9 ssl") -def has_sslcontext(): - try: - import ssl - - ssl.SSLContext - return True - except (ImportError, AttributeError): - return False - - -@check("defaultcacerts", "can verify SSL certs by system's CA certs store") -def has_defaultcacerts(): - from mercurial import sslutil, ui as uimod - - ui = uimod.ui.load() - return sslutil._defaultcacerts(ui) or sslutil._canloaddefaultcerts - - @check("defaultcacertsloaded", "detected presence of loaded system CA certs") def has_defaultcacertsloaded(): import ssl from mercurial import sslutil, ui as uimod @@ -632,13 +648,8 @@ @check("defaultcacertsloaded", "detected presence of loaded system CA certs") def has_defaultcacertsloaded(): import ssl from mercurial import sslutil, ui as uimod - if not has_defaultcacerts(): - return False - if not has_sslcontext(): - return False - ui = uimod.ui.load() cafile = sslutil._defaultcacerts(ui) ctx = ssl.create_default_context() @@ -672,6 +683,17 @@ return True +@check("setprocname", "whether osutil.setprocname is available or not") +def has_setprocname(): + try: + from mercurial.utils import procutil + + procutil.setprocname + return True + except AttributeError: + return False + + @check("test-repo", "running tests from repository") def has_test_repo(): t = os.environ["TESTDIR"] @@ -685,7 +707,7 @@ curses.COLOR_BLUE return matchoutput('test -x "`which tic`"', br'') - except ImportError: + except (ImportError, AttributeError): return False @@ -864,8 +886,11 @@ return False -@check("virtualenv", "Python virtualenv support") -def has_virtualenv(): +@check("py2virtualenv", "Python2 virtualenv support") +def has_py2virtualenv(): + if sys.version_info[0] != 2: + return False + try: import virtualenv @@ -1022,7 +1047,7 @@ version_regex = b'black, version ([0-9a-b.]+)' version = matchoutput(blackcmd, version_regex) sv = distutils.version.StrictVersion - return version and sv(_strpath(version.group(1))) >= sv('19.10b0') + return version and sv(_bytes2sys(version.group(1))) >= sv('19.10b0') @check('pytype', 'the pytype type checker') @@ -1030,7 +1055,7 @@ pytypecmd = 'pytype --version' version = matchoutput(pytypecmd, b'[0-9a-b.]+') sv = distutils.version.StrictVersion - return version and sv(_strpath(version.group(0))) >= sv('2019.10.17') + return version and sv(_bytes2sys(version.group(0))) >= sv('2019.10.17') @check("rustfmt", "rustfmt tool") @@ -1039,3 +1064,14 @@ return matchoutput( '`rustup which --toolchain nightly rustfmt` --version', b'rustfmt' ) + + +@check("lzma", "python lzma module") +def has_lzma(): + try: + import _lzma + + _lzma.FORMAT_XZ + return True + except ImportError: + return False diff --git a/tests/run-tests.py b/tests/run-tests.py index 71dab394b0187077c84c6790b999fbef8e259d7e_dGVzdHMvcnVuLXRlc3RzLnB5..658c0979a77e6873e0653b3aa4712e4b8db16635_dGVzdHMvcnVuLXRlc3RzLnB5 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -53,6 +53,7 @@ import json import multiprocessing import os +import platform import random import re import shutil @@ -143,8 +144,8 @@ PYTHON3 = True xrange = range # we use xrange in one place, and we'd rather not use range - def _bytespath(p): + def _sys2bytes(p): if p is None: return p return p.encode('utf-8') @@ -147,8 +148,8 @@ if p is None: return p return p.encode('utf-8') - def _strpath(p): + def _bytes2sys(p): if p is None: return p return p.decode('utf-8') @@ -165,7 +166,7 @@ self._strenv = strenv def __getitem__(self, k): - v = self._strenv.__getitem__(_strpath(k)) - return _bytespath(v) + v = self._strenv.__getitem__(_bytes2sys(k)) + return _sys2bytes(v) def __setitem__(self, k, v): @@ -170,5 +171,5 @@ def __setitem__(self, k, v): - self._strenv.__setitem__(_strpath(k), _strpath(v)) + self._strenv.__setitem__(_bytes2sys(k), _bytes2sys(v)) def __delitem__(self, k): @@ -173,5 +174,5 @@ def __delitem__(self, k): - self._strenv.__delitem__(_strpath(k)) + self._strenv.__delitem__(_bytes2sys(k)) def __contains__(self, k): @@ -176,5 +177,5 @@ def __contains__(self, k): - return self._strenv.__contains__(_strpath(k)) + return self._strenv.__contains__(_bytes2sys(k)) def __iter__(self): @@ -179,5 +180,5 @@ def __iter__(self): - return iter([_bytespath(k) for k in iter(self._strenv)]) + return iter([_sys2bytes(k) for k in iter(self._strenv)]) def get(self, k, default=None): @@ -182,6 +183,6 @@ def get(self, k, default=None): - v = self._strenv.get(_strpath(k), _strpath(default)) - return _bytespath(v) + v = self._strenv.get(_bytes2sys(k), _bytes2sys(default)) + return _sys2bytes(v) def pop(self, k, default=None): @@ -186,9 +187,9 @@ def pop(self, k, default=None): - v = self._strenv.pop(_strpath(k), _strpath(default)) - return _bytespath(v) + v = self._strenv.pop(_bytes2sys(k), _bytes2sys(default)) + return _sys2bytes(v) osenvironb = environbytes(os.environ) getcwdb = getattr(os, 'getcwdb') if not getcwdb or os.name == 'nt': @@ -190,9 +191,9 @@ osenvironb = environbytes(os.environ) getcwdb = getattr(os, 'getcwdb') if not getcwdb or os.name == 'nt': - getcwdb = lambda: _bytespath(os.getcwd()) + getcwdb = lambda: _sys2bytes(os.getcwd()) elif sys.version_info >= (3, 0, 0): print( @@ -207,6 +208,6 @@ # bytestrings by default, so we don't have to do any extra # fiddling there. We define the wrapper functions anyway just to # help keep code consistent between platforms. - def _bytespath(p): + def _sys2bytes(p): return p @@ -211,6 +212,6 @@ return p - _strpath = _bytespath + _bytes2sys = _sys2bytes osenvironb = os.environ getcwdb = os.getcwd @@ -274,6 +275,6 @@ def Popen4(cmd, wd, timeout, env=None): processlock.acquire() p = subprocess.Popen( - _strpath(cmd), + _bytes2sys(cmd), shell=True, bufsize=-1, @@ -278,6 +279,6 @@ shell=True, bufsize=-1, - cwd=_strpath(wd), + cwd=_bytes2sys(wd), env=env, close_fds=closefds, stdin=subprocess.PIPE, @@ -315,8 +316,8 @@ else: raise AssertionError('Could not find Python interpreter') -PYTHON = _bytespath(sysexecutable.replace('\\', '/')) +PYTHON = _sys2bytes(sysexecutable.replace('\\', '/')) IMPL_PATH = b'PYTHONPATH' if 'java' in sys.platform: IMPL_PATH = b'JYTHONPATH' @@ -319,8 +320,8 @@ IMPL_PATH = b'PYTHONPATH' if 'java' in sys.platform: IMPL_PATH = b'JYTHONPATH' -defaults = { +default_defaults = { 'jobs': ('HGTEST_JOBS', multiprocessing.cpu_count()), 'timeout': ('HGTEST_TIMEOUT', 180), 'slowtimeout': ('HGTEST_SLOWTIMEOUT', 1500), @@ -328,6 +329,8 @@ 'shell': ('HGTEST_SHELL', 'sh'), } +defaults = default_defaults.copy() + def canonpath(path): return os.path.realpath(os.path.expanduser(path)) @@ -530,6 +533,9 @@ action="store_true", help="install and use chg wrapper in place of hg", ) + hgconf.add_argument( + "--chg-debug", action="store_true", help="show chg debug logs", + ) hgconf.add_argument("--compiler", help="compiler to build with") hgconf.add_argument( '--extra-config-opt', @@ -555,6 +561,5 @@ help="use pure Python code instead of C extensions", ) hgconf.add_argument( - "-3", - "--py3-warnings", + "--rust", action="store_true", @@ -560,5 +565,10 @@ action="store_true", - help="enable Py3k warnings on Python 2.7+", + help="use Rust code alongside C extensions", + ) + hgconf.add_argument( + "--no-rust", + action="store_true", + help="do not use Rust code even if compiled", ) hgconf.add_argument( "--with-chg", @@ -643,6 +653,15 @@ if 'java' in sys.platform or '__pypy__' in sys.modules: options.pure = True + if platform.python_implementation() != 'CPython' and options.rust: + parser.error('Rust extensions are only available with CPython') + + if options.pure and options.rust: + parser.error('--rust cannot be used with --pure') + + if options.rust and options.no_rust: + parser.error('--rust cannot be used with --no-rust') + if options.local: if options.with_hg or options.with_chg: parser.error('--local cannot be used with --with-hg or --with-chg') @@ -646,7 +665,7 @@ if options.local: if options.with_hg or options.with_chg: parser.error('--local cannot be used with --with-hg or --with-chg') - testdir = os.path.dirname(_bytespath(canonpath(sys.argv[0]))) + testdir = os.path.dirname(_sys2bytes(canonpath(sys.argv[0]))) reporootdir = os.path.dirname(testdir) pathandattrs = [(b'hg', 'with_hg')] if options.chg: @@ -658,6 +677,6 @@ '--local specified, but %r not found or ' 'not executable' % binpath ) - setattr(options, attr, _strpath(binpath)) + setattr(options, attr, _bytes2sys(binpath)) if options.with_hg: @@ -662,6 +681,6 @@ if options.with_hg: - options.with_hg = canonpath(_bytespath(options.with_hg)) + options.with_hg = canonpath(_sys2bytes(options.with_hg)) if not ( os.path.isfile(options.with_hg) and os.access(options.with_hg, os.X_OK) @@ -675,7 +694,7 @@ parser.error('chg does not work on %s' % os.name) if options.with_chg: options.chg = False # no installation to temporary location - options.with_chg = canonpath(_bytespath(options.with_chg)) + options.with_chg = canonpath(_sys2bytes(options.with_chg)) if not ( os.path.isfile(options.with_chg) and os.access(options.with_chg, os.X_OK) @@ -748,9 +767,6 @@ ) options.timeout = 0 options.slowtimeout = 0 - if options.py3_warnings: - if PYTHON3: - parser.error('--py3-warnings can only be used on Python 2.7') if options.blacklist: options.blacklist = parselistfiles(options.blacklist, 'blacklist') @@ -909,8 +925,7 @@ timeout=None, startport=None, extraconfigopts=None, - py3warnings=False, shell=None, hgcommand=None, slowtimeout=None, usechg=False, @@ -913,7 +928,8 @@ shell=None, hgcommand=None, slowtimeout=None, usechg=False, + chgdebug=False, useipv6=False, ): """Create a test from parameters. @@ -942,8 +958,6 @@ must have the form "key=value" (something understood by hgrc). Values of the form "foo.key=value" will result in "[foo] key=value". - py3warnings enables Py3k warnings. - shell is the shell to execute tests in. """ if timeout is None: @@ -954,7 +968,7 @@ slowtimeout = defaults['slowtimeout'] self.path = path self.bname = os.path.basename(path) - self.name = _strpath(self.bname) + self.name = _bytes2sys(self.bname) self._testdir = os.path.dirname(path) self._outputdir = outputdir self._tmpname = os.path.basename(path) @@ -968,7 +982,6 @@ self._slowtimeout = slowtimeout self._startport = startport self._extraconfigopts = extraconfigopts or [] - self._py3warnings = py3warnings - self._shell = _bytespath(shell) + self._shell = _sys2bytes(shell) self._hgcommand = hgcommand or b'hg' self._usechg = usechg @@ -973,5 +986,6 @@ self._hgcommand = hgcommand or b'hg' self._usechg = usechg + self._chgdebug = chgdebug self._useipv6 = useipv6 self._aborted = False @@ -1178,10 +1192,7 @@ if self._keeptmpdir: log( '\nKeeping testtmp dir: %s\nKeeping threadtmp dir: %s' - % ( - self._testtmp.decode('utf-8'), - self._threadtmp.decode('utf-8'), - ) + % (_bytes2sys(self._testtmp), _bytes2sys(self._threadtmp),) ) else: try: @@ -1281,7 +1292,7 @@ environment.""" # Put the restoreenv script inside self._threadtmp scriptpath = os.path.join(self._threadtmp, b'restoreenv.sh') - testenv['HGTEST_RESTOREENV'] = _strpath(scriptpath) + testenv['HGTEST_RESTOREENV'] = _bytes2sys(scriptpath) # Only restore environment variable names that the shell allows # us to export. @@ -1315,5 +1326,5 @@ env = os.environ.copy() env['PYTHONUSERBASE'] = sysconfig.get_config_var('userbase') or '' env['HGEMITWARNINGS'] = '1' - env['TESTTMP'] = _strpath(self._testtmp) + env['TESTTMP'] = _bytes2sys(self._testtmp) env['TESTNAME'] = self.name @@ -1319,6 +1330,9 @@ env['TESTNAME'] = self.name - env['HOME'] = _strpath(self._testtmp) + env['HOME'] = _bytes2sys(self._testtmp) + formated_timeout = _bytes2sys(b"%d" % default_defaults['timeout'][1]) + env['HGTEST_TIMEOUT_DEFAULT'] = formated_timeout + env['HGTEST_TIMEOUT'] = _bytes2sys(b"%d" % self._timeout) # This number should match portneeded in _getport for port in xrange(3): # This list should be parallel to _portmap in _getreplacements defineport(port) @@ -1321,9 +1335,9 @@ # This number should match portneeded in _getport for port in xrange(3): # This list should be parallel to _portmap in _getreplacements defineport(port) - env["HGRCPATH"] = _strpath(os.path.join(self._threadtmp, b'.hgrc')) - env["DAEMON_PIDS"] = _strpath( + env["HGRCPATH"] = _bytes2sys(os.path.join(self._threadtmp, b'.hgrc')) + env["DAEMON_PIDS"] = _bytes2sys( os.path.join(self._threadtmp, b'daemon.pids') ) env["HGEDITOR"] = ( @@ -1344,7 +1358,7 @@ extraextensions = [] for opt in self._extraconfigopts: - section, key = opt.encode('utf-8').split(b'.', 1) + section, key = _sys2bytes(opt).split(b'.', 1) if section != 'extensions': continue name = key.split(b'=', 1)[0] @@ -1355,7 +1369,7 @@ # LOCALIP could be ::1 or 127.0.0.1. Useful for tests that require raw # IP addresses. - env['LOCALIP'] = _strpath(self._localip()) + env['LOCALIP'] = _bytes2sys(self._localip()) # This has the same effect as Py_LegacyWindowsStdioFlag in exewrapper.c, # but this is needed for testing python instances like dummyssh, @@ -1413,6 +1427,8 @@ if self._usechg: env['CHGSOCKNAME'] = os.path.join(self._chgsockdir, b'server') + if self._chgdebug: + env['CHGDEBUG'] = 'true' return env @@ -1441,7 +1457,7 @@ ) hgrc.write(b'[web]\n') hgrc.write(b'address = localhost\n') - hgrc.write(b'ipv6 = %s\n' % str(self._useipv6).encode('ascii')) + hgrc.write(b'ipv6 = %r\n' % self._useipv6) hgrc.write(b'server-header = testing stub value\n') for opt in self._extraconfigopts: @@ -1445,7 +1461,7 @@ hgrc.write(b'server-header = testing stub value\n') for opt in self._extraconfigopts: - section, key = opt.encode('utf-8').split(b'.', 1) + section, key = _sys2bytes(opt).split(b'.', 1) assert b'=' in key, ( 'extra config opt %s must ' 'have an = for assignment' % opt ) @@ -1464,7 +1480,10 @@ """ if self._debug: proc = subprocess.Popen( - _strpath(cmd), shell=True, cwd=_strpath(self._testtmp), env=env + _bytes2sys(cmd), + shell=True, + cwd=_bytes2sys(self._testtmp), + env=env, ) ret = proc.wait() return (ret, None) @@ -1515,5 +1534,4 @@ return os.path.join(self._testdir, b'%s.out' % self.bname) def _run(self, env): - py3switch = self._py3warnings and b' -3' or b'' # Quote the python(3) executable for Windows @@ -1519,5 +1537,5 @@ # Quote the python(3) executable for Windows - cmd = b'"%s"%s "%s"' % (PYTHON, py3switch, self.path) + cmd = b'"%s" "%s"' % (PYTHON, self.path) vlog("# Running", cmd.decode("utf-8")) normalizenewlines = os.name == 'nt' result = self._runcommand(cmd, env, normalizenewlines=normalizenewlines) @@ -1564,7 +1582,7 @@ NEEDESCAPE = re.compile(br'[\x00-\x08\x0b-\x1f\x7f-\xff]').search ESCAPESUB = re.compile(br'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub - ESCAPEMAP = dict((bchr(i), br'\x%02x' % i) for i in range(256)) + ESCAPEMAP = {bchr(i): br'\x%02x' % i for i in range(256)} ESCAPEMAP.update({b'\\': b'\\\\', b'\r': br'\r'}) def __init__(self, path, *args, **kwds): @@ -1575,5 +1593,5 @@ super(TTest, self).__init__(path, *args, **kwds) if case: casepath = b'#'.join(case) - self.name = '%s#%s' % (self.name, _strpath(casepath)) + self.name = '%s#%s' % (self.name, _bytes2sys(casepath)) self.errpath = b'%s#%s.err' % (self.errpath[:-4], casepath) @@ -1579,5 +1597,5 @@ self.errpath = b'%s#%s.err' % (self.errpath[:-4], casepath) - self._tmpname += b'-%s' % casepath + self._tmpname += b'-%s' % casepath.replace(b'#', b'-') self._have = {} @property @@ -1626,7 +1644,7 @@ return self._have.get(allreqs) # TODO do something smarter when all other uses of hghave are gone. - runtestdir = os.path.abspath(os.path.dirname(_bytespath(__file__))) + runtestdir = osenvironb[b'RUNTESTDIR'] tdir = runtestdir.replace(b'\\', b'/') proc = Popen4( b'%s -c "%s/hghave %s"' % (self._shell, tdir, allreqs), @@ -1770,7 +1788,7 @@ if self._case: casestr = b'#'.join(self._case) - if isinstance(self._case, str): + if isinstance(casestr, str): quoted = shellquote(casestr) else: quoted = shellquote(casestr.decode('utf8')).encode('utf8') @@ -2051,7 +2069,7 @@ if el.endswith(b" (esc)\n"): if PYTHON3: el = el[:-7].decode('unicode_escape') + '\n' - el = el.encode('utf-8') + el = el.encode('latin-1') else: el = el[:-7].decode('string-escape') + '\n' if el == l or os.name == 'nt' and el[:-1] + b'\r\n' == l: @@ -2081,8 +2099,6 @@ for line in lines: if line.startswith(TTest.SKIPPED_PREFIX): line = line.splitlines()[0] - missing.append( - line[len(TTest.SKIPPED_PREFIX) :].decode('utf-8') - ) + missing.append(_bytes2sys(line[len(TTest.SKIPPED_PREFIX) :])) elif line.startswith(TTest.FAILED_PREFIX): line = line.splitlines()[0] @@ -2087,6 +2103,6 @@ elif line.startswith(TTest.FAILED_PREFIX): line = line.splitlines()[0] - failed.append(line[len(TTest.FAILED_PREFIX) :].decode('utf-8')) + failed.append(_bytes2sys(line[len(TTest.FAILED_PREFIX) :])) return missing, failed @@ -2213,7 +2229,7 @@ v = self._options.view subprocess.call( r'"%s" "%s" "%s"' - % (v, _strpath(test.refpath), _strpath(test.errpath)), + % (v, _bytes2sys(test.refpath), _bytes2sys(test.errpath)), shell=True, ) else: @@ -2244,7 +2260,7 @@ 'changes)' ) else: - self.stream.write('Accept this change? [n] ') + self.stream.write('Accept this change? [y/N] ') self.stream.flush() answer = sys.stdin.readline().strip() if answer.lower() in ('y', 'yes'): @@ -2535,7 +2551,7 @@ def savetimes(outputdir, result): saved = dict(loadtimes(outputdir)) maxruns = 5 - skipped = set([str(t[0]) for t in result.skipped]) + skipped = {str(t[0]) for t in result.skipped} for tdata in result.times: test, real = tdata[0], tdata[3] if test not in skipped: @@ -2702,7 +2718,7 @@ opts = '' withhg = self._runner.options.with_hg if withhg: - opts += ' --with-hg=%s ' % shellquote(_strpath(withhg)) + opts += ' --with-hg=%s ' % shellquote(_bytes2sys(withhg)) rtc = '%s %s %s %s' % (sysexecutable, sys.argv[0], opts, test) data = pread(bisectcmd + ['--command', rtc]) m = re.search( @@ -2748,7 +2764,7 @@ @staticmethod def _writexunit(result, outf): # See http://llg.cubic.org/docs/junit/ for a reference. - timesd = dict((t[0], t[3]) for t in result.times) + timesd = {t[0]: t[3] for t in result.times} doc = minidom.Document() s = doc.createElement('testsuite') s.setAttribute('errors', "0") # TODO @@ -2944,7 +2960,7 @@ try: parser = parser or getparser() options = parseargs(args, parser) - tests = [_bytespath(a) for a in options.tests] + tests = [_sys2bytes(a) for a in options.tests] if options.test_list is not None: for listfile in options.test_list: with open(listfile, 'rb') as f: @@ -2976,7 +2992,7 @@ testdir = os.path.join(testdir, pathname) self._testdir = osenvironb[b'TESTDIR'] = testdir if self.options.outputdir: - self._outputdir = canonpath(_bytespath(self.options.outputdir)) + self._outputdir = canonpath(_sys2bytes(self.options.outputdir)) else: self._outputdir = getcwdb() if testdescs and pathname: @@ -2991,5 +3007,11 @@ # we do the randomness ourself to know what seed is used os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32)) + # Rayon (Rust crate for multi-threading) will use all logical CPU cores + # by default, causing thrashing on high-cpu-count systems. + # Setting its limit to 3 during tests should still let us uncover + # multi-threading bugs while keeping the thrashing reasonable. + os.environ.setdefault("RAYON_NUM_THREADS", "3") + if self.options.tmpdir: self.options.keep_tmpdir = True @@ -2994,6 +3016,6 @@ if self.options.tmpdir: self.options.keep_tmpdir = True - tmpdir = _bytespath(self.options.tmpdir) + tmpdir = _sys2bytes(self.options.tmpdir) if os.path.exists(tmpdir): # Meaning of tmpdir has changed since 1.3: we used to create # HGTMP inside tmpdir; now HGTMP is tmpdir. So fail if @@ -3022,7 +3044,7 @@ os.makedirs(self._tmpbindir) normbin = os.path.normpath(os.path.abspath(whg)) - normbin = normbin.replace(os.sep.encode('ascii'), b'/') + normbin = normbin.replace(_sys2bytes(os.sep), b'/') # Other Python scripts in the test harness need to # `import mercurial`. If `hg` is a Python script, we assume @@ -3071,7 +3093,7 @@ osenvironb[b"BINDIR"] = self._bindir osenvironb[b"PYTHON"] = PYTHON - fileb = _bytespath(__file__) + fileb = _sys2bytes(__file__) runtestdir = os.path.abspath(os.path.dirname(fileb)) osenvironb[b'RUNTESTDIR'] = runtestdir if PYTHON3: @@ -3075,7 +3097,7 @@ runtestdir = os.path.abspath(os.path.dirname(fileb)) osenvironb[b'RUNTESTDIR'] = runtestdir if PYTHON3: - sepb = _bytespath(os.pathsep) + sepb = _sys2bytes(os.pathsep) else: sepb = os.pathsep path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb) @@ -3109,6 +3131,13 @@ if self.options.pure: os.environ["HGTEST_RUN_TESTS_PURE"] = "--pure" os.environ["HGMODULEPOLICY"] = "py" + if self.options.rust: + os.environ["HGMODULEPOLICY"] = "rust+c" + if self.options.no_rust: + current_policy = os.environ.get("HGMODULEPOLICY", "") + if current_policy.startswith("rust+"): + os.environ["HGMODULEPOLICY"] = current_policy[len("rust+") :] + os.environ.pop("HGWITHRUSTEXT", None) if self.options.allow_slow_tests: os.environ["HGTEST_SLOW"] = "slow" @@ -3135,8 +3164,8 @@ 'extensions.logexceptions=%s' % logexceptions.decode('utf-8') ) - vlog("# Using TESTDIR", _strpath(self._testdir)) - vlog("# Using RUNTESTDIR", _strpath(osenvironb[b'RUNTESTDIR'])) - vlog("# Using HGTMP", _strpath(self._hgtmp)) + vlog("# Using TESTDIR", _bytes2sys(self._testdir)) + vlog("# Using RUNTESTDIR", _bytes2sys(osenvironb[b'RUNTESTDIR'])) + vlog("# Using HGTMP", _bytes2sys(self._hgtmp)) vlog("# Using PATH", os.environ["PATH"]) vlog( @@ -3141,4 +3170,4 @@ vlog("# Using PATH", os.environ["PATH"]) vlog( - "# Using", _strpath(IMPL_PATH), _strpath(osenvironb[IMPL_PATH]), + "# Using", _bytes2sys(IMPL_PATH), _bytes2sys(osenvironb[IMPL_PATH]), ) @@ -3144,5 +3173,5 @@ ) - vlog("# Writing to directory", _strpath(self._outputdir)) + vlog("# Writing to directory", _bytes2sys(self._outputdir)) try: return self._runtests(testdescs) or 0 @@ -3160,7 +3189,7 @@ if self.options.changed: proc = Popen4( b'hg st --rev "%s" -man0 .' - % _bytespath(self.options.changed), + % _sys2bytes(self.options.changed), None, 0, ) @@ -3354,7 +3383,7 @@ tmpdir = os.path.join(self._hgtmp, b'child%d' % count) # extra keyword parameters. 'case' is used by .t tests - kwds = dict((k, testdesc[k]) for k in ['case'] if k in testdesc) + kwds = {k: testdesc[k] for k in ['case'] if k in testdesc} t = testcls( refpath, @@ -3366,7 +3395,6 @@ timeout=self.options.timeout, startport=self._getport(count), extraconfigopts=self.options.extra_config_opt, - py3warnings=self.options.py3_warnings, shell=self.options.shell, hgcommand=self._hgcommand, usechg=bool(self.options.with_chg or self.options.chg), @@ -3370,6 +3398,7 @@ shell=self.options.shell, hgcommand=self._hgcommand, usechg=bool(self.options.with_chg or self.options.chg), + chgdebug=self.options.chg_debug, useipv6=useipv6, **kwds ) @@ -3381,7 +3410,7 @@ if self.options.keep_tmpdir: return - vlog("# Cleaning up HGTMP", _strpath(self._hgtmp)) + vlog("# Cleaning up HGTMP", _bytes2sys(self._hgtmp)) shutil.rmtree(self._hgtmp, True) for f in self._createdfiles: try: @@ -3440,4 +3469,5 @@ compiler = '' if self.options.compiler: compiler = '--compiler ' + self.options.compiler + setup_opts = b"" if self.options.pure: @@ -3443,9 +3473,11 @@ if self.options.pure: - pure = b"--pure" - else: - pure = b"" + setup_opts = b"--pure" + elif self.options.rust: + setup_opts = b"--rust" + elif self.options.no_rust: + setup_opts = b"--no-rust" # Run installer in hg root script = os.path.realpath(sys.argv[0]) exe = sysexecutable if PYTHON3: @@ -3447,11 +3479,11 @@ # Run installer in hg root script = os.path.realpath(sys.argv[0]) exe = sysexecutable if PYTHON3: - compiler = _bytespath(compiler) - script = _bytespath(script) - exe = _bytespath(exe) + compiler = _sys2bytes(compiler) + script = _sys2bytes(script) + exe = _sys2bytes(exe) hgroot = os.path.dirname(os.path.dirname(script)) self._hgroot = hgroot os.chdir(hgroot) @@ -3463,10 +3495,10 @@ # when they happen. nohome = b'' cmd = ( - b'"%(exe)s" setup.py %(pure)s clean --all' + b'"%(exe)s" setup.py %(setup_opts)s clean --all' b' build %(compiler)s --build-base="%(base)s"' b' install --force --prefix="%(prefix)s"' b' --install-lib="%(libdir)s"' b' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1' % { b'exe': exe, @@ -3467,10 +3499,10 @@ b' build %(compiler)s --build-base="%(base)s"' b' install --force --prefix="%(prefix)s"' b' --install-lib="%(libdir)s"' b' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1' % { b'exe': exe, - b'pure': pure, + b'setup_opts': setup_opts, b'compiler': compiler, b'base': os.path.join(self._hgtmp, b"build"), b'prefix': self._installdir, @@ -3493,7 +3525,7 @@ makedirs(self._bindir) vlog("# Running", cmd.decode("utf-8")) - if subprocess.call(_strpath(cmd), shell=True) == 0: + if subprocess.call(_bytes2sys(cmd), shell=True) == 0: if not self.options.verbose: try: os.remove(installerrs) @@ -3512,15 +3544,6 @@ self._usecorrectpython() - if self.options.py3_warnings and not self.options.anycoverage: - vlog("# Updating hg command to enable Py3k Warnings switch") - with open(os.path.join(self._bindir, 'hg'), 'rb') as f: - lines = [line.rstrip() for line in f] - lines[0] += ' -3' - with open(os.path.join(self._bindir, 'hg'), 'wb') as f: - for line in lines: - f.write(line + '\n') - hgbat = os.path.join(self._bindir, b'hg.bat') if os.path.isfile(hgbat): # hg.bat expects to be put in bin/scripts while run-tests.py @@ -3582,7 +3605,7 @@ cmd = b'"%s" -c "import mercurial; print (mercurial.__path__[0])"' cmd = cmd % PYTHON if PYTHON3: - cmd = _strpath(cmd) + cmd = _bytes2sys(cmd) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) out, err = p.communicate() @@ -3628,7 +3651,7 @@ # chdir is the easiest way to get short, relative paths in the # output. os.chdir(self._hgroot) - covdir = os.path.join(_strpath(self._installdir), '..', 'coverage') + covdir = os.path.join(_bytes2sys(self._installdir), '..', 'coverage') cov = coverage(data_file=os.path.join(covdir, 'cov')) # Map install directory paths back to source directory. @@ -3632,8 +3655,8 @@ cov = coverage(data_file=os.path.join(covdir, 'cov')) # Map install directory paths back to source directory. - cov.config.paths['srcdir'] = ['.', _strpath(self._pythondir)] + cov.config.paths['srcdir'] = ['.', _bytes2sys(self._pythondir)] cov.combine() omit = [ @@ -3636,10 +3659,10 @@ cov.combine() omit = [ - _strpath(os.path.join(x, b'*')) + _bytes2sys(os.path.join(x, b'*')) for x in [self._bindir, self._testdir] ] cov.report(ignore_errors=True, omit=omit) if self.options.htmlcov: @@ -3641,8 +3664,8 @@ for x in [self._bindir, self._testdir] ] cov.report(ignore_errors=True, omit=omit) if self.options.htmlcov: - htmldir = os.path.join(_strpath(self._outputdir), 'htmlcov') + htmldir = os.path.join(_bytes2sys(self._outputdir), 'htmlcov') cov.html_report(directory=htmldir, omit=omit) if self.options.annotate: @@ -3647,9 +3670,9 @@ cov.html_report(directory=htmldir, omit=omit) if self.options.annotate: - adir = os.path.join(_strpath(self._outputdir), 'annotated') + adir = os.path.join(_bytes2sys(self._outputdir), 'annotated') if not os.path.isdir(adir): os.mkdir(adir) cov.annotate(directory=adir, omit=omit) def _findprogram(self, program): """Search PATH for a executable program""" @@ -3650,11 +3673,11 @@ if not os.path.isdir(adir): os.mkdir(adir) cov.annotate(directory=adir, omit=omit) def _findprogram(self, program): """Search PATH for a executable program""" - dpb = _bytespath(os.defpath) - sepb = _bytespath(os.pathsep) + dpb = _sys2bytes(os.defpath) + sepb = _sys2bytes(os.pathsep) for p in osenvironb.get(b'PATH', dpb).split(sepb): name = os.path.join(p, program) if os.name == 'nt' or os.access(name, os.X_OK): @@ -3658,7 +3681,7 @@ for p in osenvironb.get(b'PATH', dpb).split(sepb): name = os.path.join(p, program) if os.name == 'nt' or os.access(name, os.X_OK): - return name + return _bytes2sys(name) return None def _checktools(self): @@ -3669,7 +3692,7 @@ found = self._findprogram(p) p = p.decode("utf-8") if found: - vlog("# Found prerequisite", p, "at", _strpath(found)) + vlog("# Found prerequisite", p, "at", found) else: print("WARNING: Did not find prerequisite tool: %s " % p) diff --git a/tests/test-check-pyflakes.t b/tests/test-check-pyflakes.t index 71dab394b0187077c84c6790b999fbef8e259d7e_dGVzdHMvdGVzdC1jaGVjay1weWZsYWtlcy50..658c0979a77e6873e0653b3aa4712e4b8db16635_dGVzdHMvdGVzdC1jaGVjay1weWZsYWtlcy50 100644 --- a/tests/test-check-pyflakes.t +++ b/tests/test-check-pyflakes.t @@ -8,8 +8,8 @@ $ cat > test.py <<EOF > print(undefinedname) > EOF - $ pyflakes test.py 2>/dev/null - test.py:1: undefined name 'undefinedname' + $ $PYTHON -m pyflakes test.py 2>/dev/null + test.py:1:* undefined name 'undefinedname' (glob) [1] $ cd "`dirname "$TESTDIR"`"