Mercurial > hg
comparison tests/run-tests.py @ 28284:0fe00bdb2f4f
run-tests: fix Python 3 incompatibilities
At one point run-tests.py and test-run-tests.t worked and passed
under Python 3.5. Various changes to run-tests.py over the past
several months appear to have broken Python 3.5 compatibility.
This patch implements various fixes (all related to str/bytes type
coercion) to make run-tests.py and test-run-tests.t mostly work
again. There are still a few failures in test-run-tests.t due to
issues importing mercurial.* modules. But at least run-tests.py
seems to work under 3.5 again.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 27 Feb 2016 21:29:42 -0800 |
parents | 2836a43c7722 |
children | 8de70574be2c |
comparison
equal
deleted
inserted
replaced
28283:544444991c83 | 28284:0fe00bdb2f4f |
---|---|
696 killdaemons(entry) | 696 killdaemons(entry) |
697 self._daemonpids = [] | 697 self._daemonpids = [] |
698 | 698 |
699 if self._keeptmpdir: | 699 if self._keeptmpdir: |
700 log('\nKeeping testtmp dir: %s\nKeeping threadtmp dir: %s' % | 700 log('\nKeeping testtmp dir: %s\nKeeping threadtmp dir: %s' % |
701 (self._testtmp, self._threadtmp)) | 701 (self._testtmp.decode('utf-8'), |
702 self._threadtmp.decode('utf-8'))) | |
702 else: | 703 else: |
703 shutil.rmtree(self._testtmp, True) | 704 shutil.rmtree(self._testtmp, True) |
704 shutil.rmtree(self._threadtmp, True) | 705 shutil.rmtree(self._threadtmp, True) |
705 | 706 |
706 if (self._ret != 0 or self._out != self._refout) and not self._skipped \ | 707 if (self._ret != 0 or self._out != self._refout) and not self._skipped \ |
719 def abort(self): | 720 def abort(self): |
720 """Terminate execution of this test.""" | 721 """Terminate execution of this test.""" |
721 self._aborted = True | 722 self._aborted = True |
722 | 723 |
723 def _portmap(self, i): | 724 def _portmap(self, i): |
724 offset = '' if i == 0 else '%s' % i | 725 offset = b'' if i == 0 else b'%d' % i |
725 return (br':%d\b' % (self._startport + i), b':$HGPORT%s' % offset) | 726 return (br':%d\b' % (self._startport + i), b':$HGPORT%s' % offset) |
726 | 727 |
727 def _getreplacements(self): | 728 def _getreplacements(self): |
728 """Obtain a mapping of text replacements to apply to test output. | 729 """Obtain a mapping of text replacements to apply to test output. |
729 | 730 |
907 bchr = lambda x: bytes([x]) | 908 bchr = lambda x: bytes([x]) |
908 | 909 |
909 class TTest(Test): | 910 class TTest(Test): |
910 """A "t test" is a test backed by a .t file.""" | 911 """A "t test" is a test backed by a .t file.""" |
911 | 912 |
912 SKIPPED_PREFIX = 'skipped: ' | 913 SKIPPED_PREFIX = b'skipped: ' |
913 FAILED_PREFIX = 'hghave check failed: ' | 914 FAILED_PREFIX = b'hghave check failed: ' |
914 NEEDESCAPE = re.compile(br'[\x00-\x08\x0b-\x1f\x7f-\xff]').search | 915 NEEDESCAPE = re.compile(br'[\x00-\x08\x0b-\x1f\x7f-\xff]').search |
915 | 916 |
916 ESCAPESUB = re.compile(br'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub | 917 ESCAPESUB = re.compile(br'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub |
917 ESCAPEMAP = dict((bchr(i), br'\x%02x' % i) for i in range(256)) | 918 ESCAPEMAP = dict((bchr(i), br'\x%02x' % i) for i in range(256)) |
918 ESCAPEMAP.update({b'\\': b'\\\\', b'\r': br'\r'}) | 919 ESCAPEMAP.update({b'\\': b'\\\\', b'\r': br'\r'}) |
1211 if el == l: # perfect match (fast) | 1212 if el == l: # perfect match (fast) |
1212 return True | 1213 return True |
1213 if el: | 1214 if el: |
1214 if el.endswith(b" (?)\n"): | 1215 if el.endswith(b" (?)\n"): |
1215 retry = "retry" | 1216 retry = "retry" |
1216 el = el[:-5] + "\n" | 1217 el = el[:-5] + b"\n" |
1217 if el.endswith(b" (esc)\n"): | 1218 if el.endswith(b" (esc)\n"): |
1218 if PYTHON3: | 1219 if PYTHON3: |
1219 el = el[:-7].decode('unicode_escape') + '\n' | 1220 el = el[:-7].decode('unicode_escape') + '\n' |
1220 el = el.encode('utf-8') | 1221 el = el.encode('utf-8') |
1221 else: | 1222 else: |
1243 missing = [] | 1244 missing = [] |
1244 failed = [] | 1245 failed = [] |
1245 for line in lines: | 1246 for line in lines: |
1246 if line.startswith(TTest.SKIPPED_PREFIX): | 1247 if line.startswith(TTest.SKIPPED_PREFIX): |
1247 line = line.splitlines()[0] | 1248 line = line.splitlines()[0] |
1248 missing.append(line[len(TTest.SKIPPED_PREFIX):]) | 1249 missing.append(line[len(TTest.SKIPPED_PREFIX):].decode('utf-8')) |
1249 elif line.startswith(TTest.FAILED_PREFIX): | 1250 elif line.startswith(TTest.FAILED_PREFIX): |
1250 line = line.splitlines()[0] | 1251 line = line.splitlines()[0] |
1251 failed.append(line[len(TTest.FAILED_PREFIX):]) | 1252 failed.append(line[len(TTest.FAILED_PREFIX):].decode('utf-8')) |
1252 | 1253 |
1253 return missing, failed | 1254 return missing, failed |
1254 | 1255 |
1255 @staticmethod | 1256 @staticmethod |
1256 def _escapef(m): | 1257 def _escapef(m): |
1640 # newest. | 1641 # newest. |
1641 | 1642 |
1642 def loadtimes(testdir): | 1643 def loadtimes(testdir): |
1643 times = [] | 1644 times = [] |
1644 try: | 1645 try: |
1645 with open(os.path.join(testdir, '.testtimes-')) as fp: | 1646 with open(os.path.join(testdir, b'.testtimes-')) as fp: |
1646 for line in fp: | 1647 for line in fp: |
1647 ts = line.split() | 1648 ts = line.split() |
1648 times.append((ts[0], [float(t) for t in ts[1:]])) | 1649 times.append((ts[0], [float(t) for t in ts[1:]])) |
1649 except IOError as err: | 1650 except IOError as err: |
1650 if err.errno != errno.ENOENT: | 1651 if err.errno != errno.ENOENT: |
1660 if test not in skipped: | 1661 if test not in skipped: |
1661 ts = saved.setdefault(test, []) | 1662 ts = saved.setdefault(test, []) |
1662 ts.append(real) | 1663 ts.append(real) |
1663 ts[:] = ts[-maxruns:] | 1664 ts[:] = ts[-maxruns:] |
1664 | 1665 |
1665 fd, tmpname = tempfile.mkstemp(prefix='.testtimes', | 1666 fd, tmpname = tempfile.mkstemp(prefix=b'.testtimes', |
1666 dir=testdir, text=True) | 1667 dir=testdir, text=True) |
1667 with os.fdopen(fd, 'w') as fp: | 1668 with os.fdopen(fd, 'w') as fp: |
1668 for name, ts in sorted(saved.iteritems()): | 1669 for name, ts in sorted(saved.items()): |
1669 fp.write('%s %s\n' % (name, ' '.join(['%.3f' % (t,) for t in ts]))) | 1670 fp.write('%s %s\n' % (name, ' '.join(['%.3f' % (t,) for t in ts]))) |
1670 timepath = os.path.join(testdir, '.testtimes') | 1671 timepath = os.path.join(testdir, b'.testtimes') |
1671 try: | 1672 try: |
1672 os.unlink(timepath) | 1673 os.unlink(timepath) |
1673 except OSError: | 1674 except OSError: |
1674 pass | 1675 pass |
1675 try: | 1676 try: |
1737 t.appendChild(cd) | 1738 t.appendChild(cd) |
1738 s.appendChild(t) | 1739 s.appendChild(t) |
1739 xuf.write(doc.toprettyxml(indent=' ', encoding='utf-8')) | 1740 xuf.write(doc.toprettyxml(indent=' ', encoding='utf-8')) |
1740 | 1741 |
1741 if self._runner.options.json: | 1742 if self._runner.options.json: |
1742 jsonpath = os.path.join(self._runner._testdir, 'report.json') | 1743 jsonpath = os.path.join(self._runner._testdir, b'report.json') |
1743 with open(jsonpath, 'w') as fp: | 1744 with open(jsonpath, 'w') as fp: |
1744 timesd = {} | 1745 timesd = {} |
1745 for tdata in result.times: | 1746 for tdata in result.times: |
1746 test = tdata[0] | 1747 test = tdata[0] |
1747 timesd[test] = tdata[1:] | 1748 timesd[test] = tdata[1:] |
1752 ('failure', result.failures), | 1753 ('failure', result.failures), |
1753 ('skip', result.skipped)] | 1754 ('skip', result.skipped)] |
1754 for res, testcases in groups: | 1755 for res, testcases in groups: |
1755 for tc, __ in testcases: | 1756 for tc, __ in testcases: |
1756 if tc.name in timesd: | 1757 if tc.name in timesd: |
1758 diff = result.faildata.get(tc.name, b'') | |
1757 tres = {'result': res, | 1759 tres = {'result': res, |
1758 'time': ('%0.3f' % timesd[tc.name][2]), | 1760 'time': ('%0.3f' % timesd[tc.name][2]), |
1759 'cuser': ('%0.3f' % timesd[tc.name][0]), | 1761 'cuser': ('%0.3f' % timesd[tc.name][0]), |
1760 'csys': ('%0.3f' % timesd[tc.name][1]), | 1762 'csys': ('%0.3f' % timesd[tc.name][1]), |
1761 'start': ('%0.3f' % timesd[tc.name][3]), | 1763 'start': ('%0.3f' % timesd[tc.name][3]), |
1762 'end': ('%0.3f' % timesd[tc.name][4]), | 1764 'end': ('%0.3f' % timesd[tc.name][4]), |
1763 'diff': result.faildata.get(tc.name, | 1765 'diff': diff.decode('unicode_escape'), |
1764 ''), | |
1765 } | 1766 } |
1766 else: | 1767 else: |
1767 # blacklisted test | 1768 # blacklisted test |
1768 tres = {'result': res} | 1769 tres = {'result': res} |
1769 | 1770 |