##// END OF EJS Templates
run-tests: even more bytestring annotations for Python 3
Augie Fackler -
r25041:09c71e3d default
parent child Browse files
Show More
@@ -128,9 +128,9 b' def Popen4(cmd, wd, timeout, env=None):'
128 128 return p
129 129
130 130 PYTHON = sys.executable.replace('\\', '/')
131 IMPL_PATH = 'PYTHONPATH'
131 IMPL_PATH = b'PYTHONPATH'
132 132 if 'java' in sys.platform:
133 IMPL_PATH = 'JYTHONPATH'
133 IMPL_PATH = b'JYTHONPATH'
134 134
135 135 defaults = {
136 136 'jobs': ('HGTEST_JOBS', 1),
@@ -153,7 +153,7 b' def parselistfiles(files, listtype, warn'
153 153 continue
154 154
155 155 for line in f.readlines():
156 line = line.split('#', 1)[0].strip()
156 line = line.split(b'#', 1)[0].strip()
157 157 if line:
158 158 entries[line] = filename
159 159
@@ -263,8 +263,8 b' def parseargs(args, parser):'
263 263 if not os.path.basename(options.with_hg) == 'hg':
264 264 sys.stderr.write('warning: --with-hg should specify an hg script\n')
265 265 if options.local:
266 testdir = os.path.dirname(os.path.realpath(sys.argv[0]))
267 hgbin = os.path.join(os.path.dirname(testdir), 'hg')
266 testdir = os.path.dirname(os.path.realpath(sys.argv[0]).encode('utf-8'))
267 hgbin = os.path.join(os.path.dirname(testdir), b'hg')
268 268 if os.name != 'nt' and not os.access(hgbin, os.X_OK):
269 269 parser.error('--local specified, but %r not found or not executable'
270 270 % hgbin)
@@ -666,20 +666,20 b' class Test(unittest.TestCase):'
666 666 occur.
667 667 """
668 668 r = [
669 (r':%s\b' % self._startport, ':$HGPORT'),
670 (r':%s\b' % (self._startport + 1), ':$HGPORT1'),
671 (r':%s\b' % (self._startport + 2), ':$HGPORT2'),
672 (r'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$',
673 r'\1 (glob)'),
669 (br':%d\b' % self._startport, b':$HGPORT'),
670 (br':%d\b' % (self._startport + 1), b':$HGPORT1'),
671 (br':%d\b' % (self._startport + 2), b':$HGPORT2'),
672 (br'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$',
673 br'\1 (glob)'),
674 674 ]
675 675
676 676 if os.name == 'nt':
677 677 r.append(
678 (''.join(c.isalpha() and '[%s%s]' % (c.lower(), c.upper()) or
679 c in '/\\' and r'[/\\]' or c.isdigit() and c or '\\' + c
680 for c in self._testtmp), '$TESTTMP'))
678 (b''.join(c.isalpha() and b'[%s%s]' % (c.lower(), c.upper()) or
679 c in b'/\\' and br'[/\\]' or c.isdigit() and c or b'\\' + c
680 for c in self._testtmp), b'$TESTTMP'))
681 681 else:
682 r.append((re.escape(self._testtmp), '$TESTTMP'))
682 r.append((re.escape(self._testtmp), b'$TESTTMP'))
683 683
684 684 return r
685 685
@@ -837,15 +837,15 b' class TTest(Test):'
837 837
838 838 SKIPPED_PREFIX = 'skipped: '
839 839 FAILED_PREFIX = 'hghave check failed: '
840 NEEDESCAPE = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search
840 NEEDESCAPE = re.compile(br'[\x00-\x08\x0b-\x1f\x7f-\xff]').search
841 841
842 ESCAPESUB = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub
843 ESCAPEMAP = dict((chr(i), r'\x%02x' % i) for i in range(256))
844 ESCAPEMAP.update({'\\': '\\\\', '\r': r'\r'})
842 ESCAPESUB = re.compile(br'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub
843 ESCAPEMAP = dict((bchr(i), br'\x%02x' % i) for i in range(256))
844 ESCAPEMAP.update({b'\\': b'\\\\', b'\r': br'\r'})
845 845
846 846 @property
847 847 def refpath(self):
848 return os.path.join(self._testdir, self.name)
848 return os.path.join(self._testdir, self.bname)
849 849
850 850 def _run(self, env):
851 851 f = open(self.path, 'rb')
@@ -855,13 +855,13 b' class TTest(Test):'
855 855 salt, script, after, expected = self._parsetest(lines)
856 856
857 857 # Write out the generated script.
858 fname = '%s.sh' % self._testtmp
858 fname = b'%s.sh' % self._testtmp
859 859 f = open(fname, 'wb')
860 860 for l in script:
861 861 f.write(l)
862 862 f.close()
863 863
864 cmd = '%s "%s"' % (self._shell, fname)
864 cmd = b'%s "%s"' % (self._shell, fname)
865 865 vlog("# Running", cmd)
866 866
867 867 exitcode, output = self._runcommand(cmd, env)
@@ -878,9 +878,9 b' class TTest(Test):'
878 878
879 879 def _hghave(self, reqs):
880 880 # TODO do something smarter when all other uses of hghave are gone.
881 tdir = self._testdir.replace('\\', '/')
882 proc = Popen4('%s -c "%s/hghave %s"' %
883 (self._shell, tdir, ' '.join(reqs)),
881 tdir = self._testdir.replace(b'\\', b'/')
882 proc = Popen4(b'%s -c "%s/hghave %s"' %
883 (self._shell, tdir, b' '.join(reqs)),
884 884 self._testtmp, 0, self._getenv())
885 885 stdout, stderr = proc.communicate()
886 886 ret = proc.wait()
@@ -896,12 +896,12 b' class TTest(Test):'
896 896 # We generate a shell script which outputs unique markers to line
897 897 # up script results with our source. These markers include input
898 898 # line number and the last return code.
899 salt = "SALT" + str(time.time())
899 salt = b"SALT%d" % time.time()
900 900 def addsalt(line, inpython):
901 901 if inpython:
902 script.append('%s %d 0\n' % (salt, line))
902 script.append(b'%s %d 0\n' % (salt, line))
903 903 else:
904 script.append('echo %s %s $?\n' % (salt, line))
904 script.append(b'echo %s %d $?\n' % (salt, line))
905 905
906 906 script = []
907 907
@@ -1020,8 +1020,8 b' class TTest(Test):'
1020 1020 lout, lcmd = l.split(salt, 1)
1021 1021
1022 1022 if lout:
1023 if not lout.endswith('\n'):
1024 lout += ' (no-eol)\n'
1023 if not lout.endswith(b'\n'):
1024 lout += b' (no-eol)\n'
1025 1025
1026 1026 # Find the expected output at the current position.
1027 1027 el = None
@@ -1040,12 +1040,12 b' class TTest(Test):'
1040 1040 log('\ninfo, unknown linematch result: %r\n' % r)
1041 1041 r = False
1042 1042 if r:
1043 postout.append(' ' + el)
1043 postout.append(b' ' + el)
1044 1044 else:
1045 1045 if self.NEEDESCAPE(lout):
1046 lout = TTest._stringescape('%s (esc)\n' %
1047 lout.rstrip('\n'))
1048 postout.append(' ' + lout) # Let diff deal with it.
1046 lout = TTest._stringescape(b'%s (esc)\n' %
1047 lout.rstrip(b'\n'))
1048 postout.append(b' ' + lout) # Let diff deal with it.
1049 1049 if r != '': # If line failed.
1050 1050 warnonly = 3 # for sure not
1051 1051 elif warnonly == 1: # Is "not yet" and line is warn only.
@@ -1055,7 +1055,7 b' class TTest(Test):'
1055 1055 # Add on last return code.
1056 1056 ret = int(lcmd.split()[1])
1057 1057 if ret != 0:
1058 postout.append(' [%s]\n' % ret)
1058 postout.append(b' [%d]\n' % ret)
1059 1059 if pos in after:
1060 1060 # Merge in non-active test bits.
1061 1061 postout += after.pop(pos)
@@ -1074,8 +1074,8 b' class TTest(Test):'
1074 1074 try:
1075 1075 # use \Z to ensure that the regex matches to the end of the string
1076 1076 if os.name == 'nt':
1077 return re.match(el + r'\r?\n\Z', l)
1078 return re.match(el + r'\n\Z', l)
1077 return re.match(el + br'\r?\n\Z', l)
1078 return re.match(el + br'\n\Z', l)
1079 1079 except re.error:
1080 1080 # el is an invalid regex
1081 1081 return False
@@ -1084,28 +1084,28 b' class TTest(Test):'
1084 1084 def globmatch(el, l):
1085 1085 # The only supported special characters are * and ? plus / which also
1086 1086 # matches \ on windows. Escaping of these characters is supported.
1087 if el + '\n' == l:
1087 if el + b'\n' == l:
1088 1088 if os.altsep:
1089 1089 # matching on "/" is not needed for this line
1090 1090 for pat in checkcodeglobpats:
1091 1091 if pat.match(el):
1092 1092 return True
1093 return '-glob'
1093 return b'-glob'
1094 1094 return True
1095 1095 i, n = 0, len(el)
1096 res = ''
1096 res = b''
1097 1097 while i < n:
1098 c = el[i]
1098 c = el[i:i + 1]
1099 1099 i += 1
1100 if c == '\\' and i < n and el[i] in '*?\\/':
1100 if c == b'\\' and i < n and el[i:i + 1] in b'*?\\/':
1101 1101 res += el[i - 1:i + 1]
1102 1102 i += 1
1103 elif c == '*':
1104 res += '.*'
1105 elif c == '?':
1106 res += '.'
1107 elif c == '/' and os.altsep:
1108 res += '[/\\\\]'
1103 elif c == b'*':
1104 res += b'.*'
1105 elif c == b'?':
1106 res += b'.'
1107 elif c == b'/' and os.altsep:
1108 res += b'[/\\\\]'
1109 1109 else:
1110 1110 res += re.escape(c)
1111 1111 return TTest.rematch(res, l)
@@ -1115,19 +1115,21 b' class TTest(Test):'
1115 1115 if el == l: # perfect match (fast)
1116 1116 return True
1117 1117 if el:
1118 if el.endswith(" (esc)\n"):
1118 if el.endswith(b" (esc)\n"):
1119 1119 el = el[:-7].decode('string-escape') + '\n'
1120 if el == l or os.name == 'nt' and el[:-1] + '\r\n' == l:
1120 if sys.version_info[0] == 3:
1121 el.encode('utf-8')
1122 if el == l or os.name == 'nt' and el[:-1] + b'\r\n' == l:
1121 1123 return True
1122 if el.endswith(" (re)\n"):
1124 if el.endswith(b" (re)\n"):
1123 1125 return TTest.rematch(el[:-6], l)
1124 if el.endswith(" (glob)\n"):
1126 if el.endswith(b" (glob)\n"):
1125 1127 # ignore '(glob)' added to l by 'replacements'
1126 if l.endswith(" (glob)\n"):
1127 l = l[:-8] + "\n"
1128 if l.endswith(b" (glob)\n"):
1129 l = l[:-8] + b"\n"
1128 1130 return TTest.globmatch(el[:-8], l)
1129 if os.altsep and l.replace('\\', '/') == el:
1130 return '+glob'
1131 if os.altsep and l.replace(b'\\', b'/') == el:
1132 return b'+glob'
1131 1133 return False
1132 1134
1133 1135 @staticmethod
@@ -1387,7 +1389,7 b' class TestSuite(unittest.TestSuite):'
1387 1389 def get():
1388 1390 num_tests[0] += 1
1389 1391 if getattr(test, 'should_reload', False):
1390 return self._loadtest(test.name, num_tests[0])
1392 return self._loadtest(test.bname, num_tests[0])
1391 1393 return test
1392 1394 if not os.path.exists(test.path):
1393 1395 result.addSkip(test, "Doesn't exist")
@@ -1603,19 +1605,19 b' class TestRunner(object):'
1603 1605
1604 1606 # Programs required to run tests.
1605 1607 REQUIREDTOOLS = [
1606 os.path.basename(sys.executable),
1607 'diff',
1608 'grep',
1609 'unzip',
1610 'gunzip',
1611 'bunzip2',
1612 'sed',
1608 os.path.basename(sys.executable).encode('utf-8'),
1609 b'diff',
1610 b'grep',
1611 b'unzip',
1612 b'gunzip',
1613 b'bunzip2',
1614 b'sed',
1613 1615 ]
1614 1616
1615 1617 # Maps file extensions to test class.
1616 1618 TESTTYPES = [
1617 ('.py', PythonTest),
1618 ('.t', TTest),
1619 (b'.py', PythonTest),
1620 (b'.t', TTest),
1619 1621 ]
1620 1622
1621 1623 def __init__(self):
@@ -1639,6 +1641,7 b' class TestRunner(object):'
1639 1641 try:
1640 1642 parser = parser or getparser()
1641 1643 options, args = parseargs(args, parser)
1644 args = [a.encode('utf-8') for a in args]
1642 1645 self.options = options
1643 1646
1644 1647 self._checktools()
@@ -1652,7 +1655,7 b' class TestRunner(object):'
1652 1655 random.shuffle(tests)
1653 1656 else:
1654 1657 # keywords for slow tests
1655 slow = 'svn gendoc check-code-hg'.split()
1658 slow = b'svn gendoc check-code-hg'.split()
1656 1659 def sortkey(f):
1657 1660 # run largest tests first, as they tend to take the longest
1658 1661 try:
@@ -1667,7 +1670,8 b' class TestRunner(object):'
1667 1670 return val
1668 1671 tests.sort(key=sortkey)
1669 1672
1670 self._testdir = os.environ['TESTDIR'] = os.getcwd()
1673 self._testdir = osenvironb[b'TESTDIR'] = getattr(
1674 os, 'getcwdb', os.getcwd)()
1671 1675
1672 1676 if 'PYTHONHASHSEED' not in os.environ:
1673 1677 # use a random python hash seed all the time
@@ -1676,7 +1680,7 b' class TestRunner(object):'
1676 1680
1677 1681 if self.options.tmpdir:
1678 1682 self.options.keep_tmpdir = True
1679 tmpdir = self.options.tmpdir
1683 tmpdir = self.options.tmpdir.encode('utf-8')
1680 1684 if os.path.exists(tmpdir):
1681 1685 # Meaning of tmpdir has changed since 1.3: we used to create
1682 1686 # HGTMP inside tmpdir; now HGTMP is tmpdir. So fail if
@@ -1695,15 +1699,19 b' class TestRunner(object):'
1695 1699 if os.name == 'nt':
1696 1700 # without this, we get the default temp dir location, but
1697 1701 # in all lowercase, which causes troubles with paths (issue3490)
1698 d = os.getenv('TMP')
1699 tmpdir = tempfile.mkdtemp('', 'hgtests.', d)
1700 self._hgtmp = os.environ['HGTMP'] = os.path.realpath(tmpdir)
1702 d = osenvironb.get(b'TMP', None)
1703 # FILE BUG: mkdtemp works only on unicode in Python 3
1704 tmpdir = tempfile.mkdtemp('', 'hgtests.',
1705 d and d.decode('utf-8')).encode('utf-8')
1706
1707 self._hgtmp = osenvironb[b'HGTMP'] = (
1708 os.path.realpath(tmpdir))
1701 1709
1702 1710 if self.options.with_hg:
1703 1711 self._installdir = None
1704 1712 self._bindir = os.path.dirname(os.path.realpath(
1705 1713 self.options.with_hg))
1706 self._tmpbindir = os.path.join(self._hgtmp, 'install', 'bin')
1714 self._tmpbindir = os.path.join(self._hgtmp, b'install', b'bin')
1707 1715 os.makedirs(self._tmpbindir)
1708 1716
1709 1717 # This looks redundant with how Python initializes sys.path from
@@ -1713,25 +1721,30 b' class TestRunner(object):'
1713 1721 # ... which means it's not really redundant at all.
1714 1722 self._pythondir = self._bindir
1715 1723 else:
1716 self._installdir = os.path.join(self._hgtmp, "install")
1717 self._bindir = os.environ["BINDIR"] = \
1718 os.path.join(self._installdir, "bin")
1724 self._installdir = os.path.join(self._hgtmp, b"install")
1725 self._bindir = osenvironb[b"BINDIR"] = \
1726 os.path.join(self._installdir, b"bin")
1719 1727 self._tmpbindir = self._bindir
1720 self._pythondir = os.path.join(self._installdir, "lib", "python")
1728 self._pythondir = os.path.join(self._installdir, b"lib", b"python")
1721 1729
1722 os.environ["BINDIR"] = self._bindir
1730 osenvironb[b"BINDIR"] = self._bindir
1723 1731 os.environ["PYTHON"] = PYTHON
1724 1732
1725 runtestdir = os.path.abspath(os.path.dirname(__file__))
1726 path = [self._bindir, runtestdir] + os.environ["PATH"].split(os.pathsep)
1733 fileb = __file__.encode('utf-8')
1734 runtestdir = os.path.abspath(os.path.dirname(fileb))
1735 if sys.version_info[0] == 3:
1736 sepb = os.pathsep.encode('utf-8')
1737 else:
1738 sepb = os.pathsep
1739 path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb)
1727 1740 if os.path.islink(__file__):
1728 1741 # test helper will likely be at the end of the symlink
1729 realfile = os.path.realpath(__file__)
1742 realfile = os.path.realpath(fileb)
1730 1743 realdir = os.path.abspath(os.path.dirname(realfile))
1731 1744 path.insert(2, realdir)
1732 1745 if self._tmpbindir != self._bindir:
1733 1746 path = [self._tmpbindir] + path
1734 os.environ["PATH"] = os.pathsep.join(path)
1747 osenvironb[b"PATH"] = sepb.join(path)
1735 1748
1736 1749 # Include TESTDIR in PYTHONPATH so that out-of-tree extensions
1737 1750 # can run .../tests/run-tests.py test-foo where test-foo
@@ -1742,20 +1755,20 b' class TestRunner(object):'
1742 1755 # it, in case external libraries are only available via current
1743 1756 # PYTHONPATH. (In particular, the Subversion bindings on OS X
1744 1757 # are in /opt/subversion.)
1745 oldpypath = os.environ.get(IMPL_PATH)
1758 oldpypath = osenvironb.get(IMPL_PATH)
1746 1759 if oldpypath:
1747 1760 pypath.append(oldpypath)
1748 os.environ[IMPL_PATH] = os.pathsep.join(pypath)
1761 osenvironb[IMPL_PATH] = sepb.join(pypath)
1749 1762
1750 1763 if self.options.pure:
1751 1764 os.environ["HGTEST_RUN_TESTS_PURE"] = "--pure"
1752 1765
1753 self._coveragefile = os.path.join(self._testdir, '.coverage')
1766 self._coveragefile = os.path.join(self._testdir, b'.coverage')
1754 1767
1755 1768 vlog("# Using TESTDIR", self._testdir)
1756 1769 vlog("# Using HGTMP", self._hgtmp)
1757 1770 vlog("# Using PATH", os.environ["PATH"])
1758 vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH])
1771 vlog("# Using", IMPL_PATH, osenvironb[IMPL_PATH])
1759 1772
1760 1773 try:
1761 1774 return self._runtests(tests) or 0
@@ -1774,13 +1787,13 b' class TestRunner(object):'
1774 1787 proc = Popen4('hg st --rev "%s" -man0 .' %
1775 1788 self.options.changed, None, 0)
1776 1789 stdout, stderr = proc.communicate()
1777 args = stdout.strip('\0').split('\0')
1790 args = stdout.strip(b'\0').split(b'\0')
1778 1791 else:
1779 args = os.listdir('.')
1792 args = os.listdir(b'.')
1780 1793
1781 1794 return [t for t in args
1782 if os.path.basename(t).startswith('test-')
1783 and (t.endswith('.py') or t.endswith('.t'))]
1795 if os.path.basename(t).startswith(b'test-')
1796 and (t.endswith(b'.py') or t.endswith(b'.t'))]
1784 1797
1785 1798 def _runtests(self, tests):
1786 1799 try:
@@ -1869,7 +1882,7 b' class TestRunner(object):'
1869 1882 break
1870 1883
1871 1884 refpath = os.path.join(self._testdir, test)
1872 tmpdir = os.path.join(self._hgtmp, 'child%d' % count)
1885 tmpdir = os.path.join(self._hgtmp, b'child%d' % count)
1873 1886
1874 1887 t = testcls(refpath, tmpdir,
1875 1888 keeptmpdir=self.options.keep_tmpdir,
@@ -1899,7 +1912,7 b' class TestRunner(object):'
1899 1912 def _usecorrectpython(self):
1900 1913 """Configure the environment to use the appropriate Python in tests."""
1901 1914 # Tests must use the same interpreter as us or bad things will happen.
1902 pyexename = sys.platform == 'win32' and 'python.exe' or 'python'
1915 pyexename = sys.platform == 'win32' and b'python.exe' or b'python'
1903 1916 if getattr(os, 'symlink', None):
1904 1917 vlog("# Making python executable in test path a symlink to '%s'" %
1905 1918 sys.executable)
@@ -1967,7 +1980,7 b' class TestRunner(object):'
1967 1980 ' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1'
1968 1981 % {'exe': sys.executable, 'py3': py3, 'pure': pure,
1969 1982 'compiler': compiler,
1970 'base': os.path.join(self._hgtmp, "build"),
1983 'base': os.path.join(self._hgtmp, b"build"),
1971 1984 'prefix': self._installdir, 'libdir': self._pythondir,
1972 1985 'bindir': self._bindir,
1973 1986 'nohome': nohome, 'logfile': installerrs})
General Comments 0
You need to be logged in to leave comments. Login now