Mercurial > hg
comparison tests/run-tests.py @ 25161:4d30467d944e
run-tests: move unicode-to-bytes operations on paths to a helper (issue4667)
This doesn't fix the probably-wrong utf-8 encoding choice, it just
starts the process of encapsulating all the path handling in run-tests
in a single place.
One known-path use of .encode() remains: it's related to use of
mkdtemp, and it will be fixed in a followup patch once we have a
companion _strpath() helper function to go from bytes to a str, as we
need to file a bug about mkdtemp upstream.
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 17 May 2015 21:40:12 -0400 |
parents | fefc72523491 |
children | 153b9c5235c2 |
comparison
equal
deleted
inserted
replaced
25160:fefc72523491 | 25161:4d30467d944e |
---|---|
79 processlock = threading.Lock() | 79 processlock = threading.Lock() |
80 | 80 |
81 if sys.version_info > (3, 5, 0): | 81 if sys.version_info > (3, 5, 0): |
82 PYTHON3 = True | 82 PYTHON3 = True |
83 xrange = range # we use xrange in one place, and we'd rather not use range | 83 xrange = range # we use xrange in one place, and we'd rather not use range |
84 def _bytespath(p): | |
85 return p.encode('utf-8') | |
84 elif sys.version_info >= (3, 0, 0): | 86 elif sys.version_info >= (3, 0, 0): |
85 print('%s is only supported on Python 3.5+ and 2.6-2.7, not %s' % | 87 print('%s is only supported on Python 3.5+ and 2.6-2.7, not %s' % |
86 (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3]))) | 88 (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3]))) |
87 sys.exit(70) # EX_SOFTWARE from `man 3 sysexit` | 89 sys.exit(70) # EX_SOFTWARE from `man 3 sysexit` |
88 else: | 90 else: |
89 PYTHON3 = False | 91 PYTHON3 = False |
92 def _bytespath(p): | |
93 return p | |
90 | 94 |
91 def checkportisavailable(port): | 95 def checkportisavailable(port): |
92 """return true if a port seems free to bind on localhost""" | 96 """return true if a port seems free to bind on localhost""" |
93 try: | 97 try: |
94 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 98 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
124 terminate(p) | 128 terminate(p) |
125 threading.Thread(target=t).start() | 129 threading.Thread(target=t).start() |
126 | 130 |
127 return p | 131 return p |
128 | 132 |
129 PYTHON = sys.executable.replace('\\', '/').encode('utf-8') | 133 PYTHON = _bytespath(sys.executable.replace('\\', '/')) |
130 IMPL_PATH = b'PYTHONPATH' | 134 IMPL_PATH = b'PYTHONPATH' |
131 if 'java' in sys.platform: | 135 if 'java' in sys.platform: |
132 IMPL_PATH = b'JYTHONPATH' | 136 IMPL_PATH = b'JYTHONPATH' |
133 | 137 |
134 defaults = { | 138 defaults = { |
262 os.access(options.with_hg, os.X_OK)): | 266 os.access(options.with_hg, os.X_OK)): |
263 parser.error('--with-hg must specify an executable hg script') | 267 parser.error('--with-hg must specify an executable hg script') |
264 if not os.path.basename(options.with_hg) == 'hg': | 268 if not os.path.basename(options.with_hg) == 'hg': |
265 sys.stderr.write('warning: --with-hg should specify an hg script\n') | 269 sys.stderr.write('warning: --with-hg should specify an hg script\n') |
266 if options.local: | 270 if options.local: |
267 testdir = os.path.dirname(os.path.realpath(sys.argv[0]).encode('utf-8')) | 271 testdir = os.path.dirname(_bytespath(os.path.realpath(sys.argv[0]))) |
268 hgbin = os.path.join(os.path.dirname(testdir), b'hg') | 272 hgbin = os.path.join(os.path.dirname(testdir), b'hg') |
269 if os.name != 'nt' and not os.access(hgbin, os.X_OK): | 273 if os.name != 'nt' and not os.access(hgbin, os.X_OK): |
270 parser.error('--local specified, but %r not found or not executable' | 274 parser.error('--local specified, but %r not found or not executable' |
271 % hgbin) | 275 % hgbin) |
272 options.with_hg = hgbin | 276 options.with_hg = hgbin |
448 self._debug = debug | 452 self._debug = debug |
449 self._timeout = timeout | 453 self._timeout = timeout |
450 self._startport = startport | 454 self._startport = startport |
451 self._extraconfigopts = extraconfigopts or [] | 455 self._extraconfigopts = extraconfigopts or [] |
452 self._py3kwarnings = py3kwarnings | 456 self._py3kwarnings = py3kwarnings |
453 self._shell = shell.encode('utf-8') | 457 self._shell = _bytespath(shell) |
454 | 458 |
455 self._aborted = False | 459 self._aborted = False |
456 self._daemonpids = [] | 460 self._daemonpids = [] |
457 self._finished = None | 461 self._finished = None |
458 self._ret = None | 462 self._ret = None |
1281 if self._options.nodiff: | 1285 if self._options.nodiff: |
1282 pass | 1286 pass |
1283 elif self._options.view: | 1287 elif self._options.view: |
1284 v = self._options.view | 1288 v = self._options.view |
1285 if PYTHON3: | 1289 if PYTHON3: |
1286 v = v.encode('utf-8') | 1290 v = _bytespath(v) |
1287 os.system(b"%s %s %s" % | 1291 os.system(b"%s %s %s" % |
1288 (v, test.refpath, test.errpath)) | 1292 (v, test.refpath, test.errpath)) |
1289 else: | 1293 else: |
1290 servefail, lines = getdiff(expected, got, | 1294 servefail, lines = getdiff(expected, got, |
1291 test.refpath, test.errpath) | 1295 test.refpath, test.errpath) |
1619 Tests rely on a lot of state. This object holds it for them. | 1623 Tests rely on a lot of state. This object holds it for them. |
1620 """ | 1624 """ |
1621 | 1625 |
1622 # Programs required to run tests. | 1626 # Programs required to run tests. |
1623 REQUIREDTOOLS = [ | 1627 REQUIREDTOOLS = [ |
1624 os.path.basename(sys.executable).encode('utf-8'), | 1628 os.path.basename(_bytespath(sys.executable)), |
1625 b'diff', | 1629 b'diff', |
1626 b'grep', | 1630 b'grep', |
1627 b'unzip', | 1631 b'unzip', |
1628 b'gunzip', | 1632 b'gunzip', |
1629 b'bunzip2', | 1633 b'bunzip2', |
1655 """Run the test suite.""" | 1659 """Run the test suite.""" |
1656 oldmask = os.umask(0o22) | 1660 oldmask = os.umask(0o22) |
1657 try: | 1661 try: |
1658 parser = parser or getparser() | 1662 parser = parser or getparser() |
1659 options, args = parseargs(args, parser) | 1663 options, args = parseargs(args, parser) |
1660 args = [a.encode('utf-8') for a in args] | 1664 # positional arguments are paths to test files to run, so |
1665 # we make sure they're all bytestrings | |
1666 args = [_bytespath(a) for a in args] | |
1661 self.options = options | 1667 self.options = options |
1662 | 1668 |
1663 self._checktools() | 1669 self._checktools() |
1664 tests = self.findtests(args) | 1670 tests = self.findtests(args) |
1665 if options.profile_runner: | 1671 if options.profile_runner: |
1705 # we do the randomness ourself to know what seed is used | 1711 # we do the randomness ourself to know what seed is used |
1706 os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32)) | 1712 os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32)) |
1707 | 1713 |
1708 if self.options.tmpdir: | 1714 if self.options.tmpdir: |
1709 self.options.keep_tmpdir = True | 1715 self.options.keep_tmpdir = True |
1710 tmpdir = self.options.tmpdir.encode('utf-8') | 1716 tmpdir = _bytespath(self.options.tmpdir) |
1711 if os.path.exists(tmpdir): | 1717 if os.path.exists(tmpdir): |
1712 # Meaning of tmpdir has changed since 1.3: we used to create | 1718 # Meaning of tmpdir has changed since 1.3: we used to create |
1713 # HGTMP inside tmpdir; now HGTMP is tmpdir. So fail if | 1719 # HGTMP inside tmpdir; now HGTMP is tmpdir. So fail if |
1714 # tmpdir already exists. | 1720 # tmpdir already exists. |
1715 print("error: temp dir %r already exists" % tmpdir) | 1721 print("error: temp dir %r already exists" % tmpdir) |
1740 # If --with-hg is not specified, we have bytes already, | 1746 # If --with-hg is not specified, we have bytes already, |
1741 # but if it was specified in python3 we get a str, so we | 1747 # but if it was specified in python3 we get a str, so we |
1742 # have to encode it back into a bytes. | 1748 # have to encode it back into a bytes. |
1743 if PYTHON3: | 1749 if PYTHON3: |
1744 if not isinstance(whg, bytes): | 1750 if not isinstance(whg, bytes): |
1745 whg = whg.encode('utf-8') | 1751 whg = _bytespath(whg) |
1746 self._bindir = os.path.dirname(os.path.realpath(whg)) | 1752 self._bindir = os.path.dirname(os.path.realpath(whg)) |
1747 assert isinstance(self._bindir, bytes) | 1753 assert isinstance(self._bindir, bytes) |
1748 self._tmpbindir = os.path.join(self._hgtmp, b'install', b'bin') | 1754 self._tmpbindir = os.path.join(self._hgtmp, b'install', b'bin') |
1749 os.makedirs(self._tmpbindir) | 1755 os.makedirs(self._tmpbindir) |
1750 | 1756 |
1762 self._pythondir = os.path.join(self._installdir, b"lib", b"python") | 1768 self._pythondir = os.path.join(self._installdir, b"lib", b"python") |
1763 | 1769 |
1764 osenvironb[b"BINDIR"] = self._bindir | 1770 osenvironb[b"BINDIR"] = self._bindir |
1765 osenvironb[b"PYTHON"] = PYTHON | 1771 osenvironb[b"PYTHON"] = PYTHON |
1766 | 1772 |
1767 fileb = __file__.encode('utf-8') | 1773 fileb = _bytespath(__file__) |
1768 runtestdir = os.path.abspath(os.path.dirname(fileb)) | 1774 runtestdir = os.path.abspath(os.path.dirname(fileb)) |
1769 if PYTHON3: | 1775 if PYTHON3: |
1770 sepb = os.pathsep.encode('utf-8') | 1776 sepb = _bytespath(os.pathsep) |
1771 else: | 1777 else: |
1772 sepb = os.pathsep | 1778 sepb = os.pathsep |
1773 path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb) | 1779 path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb) |
1774 if os.path.islink(__file__): | 1780 if os.path.islink(__file__): |
1775 # test helper will likely be at the end of the symlink | 1781 # test helper will likely be at the end of the symlink |
1999 # Run installer in hg root | 2005 # Run installer in hg root |
2000 script = os.path.realpath(sys.argv[0]) | 2006 script = os.path.realpath(sys.argv[0]) |
2001 exe = sys.executable | 2007 exe = sys.executable |
2002 if PYTHON3: | 2008 if PYTHON3: |
2003 py3 = b'--c2to3' | 2009 py3 = b'--c2to3' |
2004 compiler = compiler.encode('utf-8') | 2010 compiler = _bytespath(compiler) |
2005 script = script.encode('utf-8') | 2011 script = _bytespath(script) |
2006 exe = exe.encode('utf-8') | 2012 exe = _bytespath(exe) |
2007 hgroot = os.path.dirname(os.path.dirname(script)) | 2013 hgroot = os.path.dirname(os.path.dirname(script)) |
2008 self._hgroot = hgroot | 2014 self._hgroot = hgroot |
2009 os.chdir(hgroot) | 2015 os.chdir(hgroot) |
2010 nohome = b'--home=""' | 2016 nohome = b'--home=""' |
2011 if os.name == 'nt': | 2017 if os.name == 'nt': |
2121 cmd = cmd % PYTHON | 2127 cmd = cmd % PYTHON |
2122 if PYTHON3: | 2128 if PYTHON3: |
2123 cmd = cmd.decode('utf-8') | 2129 cmd = cmd.decode('utf-8') |
2124 pipe = os.popen(cmd) | 2130 pipe = os.popen(cmd) |
2125 try: | 2131 try: |
2126 self._hgpath = pipe.read().strip() | 2132 self._hgpath = _bytespath(pipe.read().strip()) |
2127 if PYTHON3: | |
2128 self._hgpath = self._hgpath.encode('utf-8') | |
2129 finally: | 2133 finally: |
2130 pipe.close() | 2134 pipe.close() |
2131 | 2135 |
2132 return self._hgpath | 2136 return self._hgpath |
2133 | 2137 |
2159 os.mkdir(adir) | 2163 os.mkdir(adir) |
2160 cov.annotate(directory=adir, omit=omit) | 2164 cov.annotate(directory=adir, omit=omit) |
2161 | 2165 |
2162 def _findprogram(self, program): | 2166 def _findprogram(self, program): |
2163 """Search PATH for a executable program""" | 2167 """Search PATH for a executable program""" |
2164 if PYTHON3: | 2168 dpb = _bytespath(os.defpath) |
2165 dpb = os.defpath.encode('utf-8') | 2169 sepb = _bytespath(os.pathsep) |
2166 sepb = os.pathsep.encode('utf-8') | |
2167 else: | |
2168 dpb = os.defpath | |
2169 sepb = os.pathsep | |
2170 for p in osenvironb.get(b'PATH', dpb).split(sepb): | 2170 for p in osenvironb.get(b'PATH', dpb).split(sepb): |
2171 name = os.path.join(p, program) | 2171 name = os.path.join(p, program) |
2172 if os.name == 'nt' or os.access(name, os.X_OK): | 2172 if os.name == 'nt' or os.access(name, os.X_OK): |
2173 return name | 2173 return name |
2174 return None | 2174 return None |