Show More
@@ -70,6 +70,8 b' import unittest' | |||||
70 | import uuid |
|
70 | import uuid | |
71 | import xml.dom.minidom as minidom |
|
71 | import xml.dom.minidom as minidom | |
72 |
|
72 | |||
|
73 | WINDOWS = os.name == r'nt' | |||
|
74 | ||||
73 | try: |
|
75 | try: | |
74 | import Queue as queue |
|
76 | import Queue as queue | |
75 | except ImportError: |
|
77 | except ImportError: | |
@@ -84,6 +86,7 b' except (ImportError, AttributeError):' | |||||
84 |
|
86 | |||
85 | shellquote = pipes.quote |
|
87 | shellquote = pipes.quote | |
86 |
|
88 | |||
|
89 | ||||
87 | processlock = threading.Lock() |
|
90 | processlock = threading.Lock() | |
88 |
|
91 | |||
89 | pygmentspresent = False |
|
92 | pygmentspresent = False | |
@@ -95,7 +98,7 b' try: # is pygments installed' | |||||
95 | import pygments.token as token |
|
98 | import pygments.token as token | |
96 | import pygments.style as style |
|
99 | import pygments.style as style | |
97 |
|
100 | |||
98 | if os.name == 'nt': |
|
101 | if WINDOWS: | |
99 | hgpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
|
102 | hgpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
100 | sys.path.append(hgpath) |
|
103 | sys.path.append(hgpath) | |
101 | try: |
|
104 | try: | |
@@ -151,6 +154,7 b' if pygmentspresent:' | |||||
151 |
|
154 | |||
152 | origenviron = os.environ.copy() |
|
155 | origenviron = os.environ.copy() | |
153 |
|
156 | |||
|
157 | ||||
154 | if sys.version_info > (3, 5, 0): |
|
158 | if sys.version_info > (3, 5, 0): | |
155 | PYTHON3 = True |
|
159 | PYTHON3 = True | |
156 | xrange = range # we use xrange in one place, and we'd rather not use range |
|
160 | xrange = range # we use xrange in one place, and we'd rather not use range | |
@@ -203,7 +207,7 b' if sys.version_info > (3, 5, 0):' | |||||
203 | osenvironb = environbytes(os.environ) |
|
207 | osenvironb = environbytes(os.environ) | |
204 |
|
208 | |||
205 | getcwdb = getattr(os, 'getcwdb') |
|
209 | getcwdb = getattr(os, 'getcwdb') | |
206 |
if not getcwdb or |
|
210 | if not getcwdb or WINDOWS: | |
207 | getcwdb = lambda: _sys2bytes(os.getcwd()) |
|
211 | getcwdb = lambda: _sys2bytes(os.getcwd()) | |
208 |
|
212 | |||
209 | elif sys.version_info >= (3, 0, 0): |
|
213 | elif sys.version_info >= (3, 0, 0): | |
@@ -270,7 +274,7 b' def checkportisavailable(port):' | |||||
270 | s.bind(('localhost', port)) |
|
274 | s.bind(('localhost', port)) | |
271 | return True |
|
275 | return True | |
272 | except socket.error as exc: |
|
276 | except socket.error as exc: | |
273 |
if |
|
277 | if WINDOWS and exc.errno == errno.WSAEACCES: | |
274 | return False |
|
278 | return False | |
275 | elif PYTHON3: |
|
279 | elif PYTHON3: | |
276 | # TODO: make a proper exception handler after dropping py2. This |
|
280 | # TODO: make a proper exception handler after dropping py2. This | |
@@ -709,7 +713,7 b' def parseargs(args, parser):' | |||||
709 | pathandattrs.append((b'rust/target/release/rhg', 'with_rhg')) |
|
713 | pathandattrs.append((b'rust/target/release/rhg', 'with_rhg')) | |
710 | for relpath, attr in pathandattrs: |
|
714 | for relpath, attr in pathandattrs: | |
711 | binpath = os.path.join(reporootdir, relpath) |
|
715 | binpath = os.path.join(reporootdir, relpath) | |
712 |
if |
|
716 | if not (WINDOWS or os.access(binpath, os.X_OK)): | |
713 | parser.error( |
|
717 | parser.error( | |
714 | '--local specified, but %r not found or ' |
|
718 | '--local specified, but %r not found or ' | |
715 | 'not executable' % binpath |
|
719 | 'not executable' % binpath | |
@@ -727,9 +731,9 b' def parseargs(args, parser):' | |||||
727 | sys.stderr.write('warning: --with-hg should specify an hg script\n') |
|
731 | sys.stderr.write('warning: --with-hg should specify an hg script\n') | |
728 | sys.stderr.flush() |
|
732 | sys.stderr.flush() | |
729 |
|
733 | |||
730 |
if (options.chg or options.with_chg) and |
|
734 | if (options.chg or options.with_chg) and WINDOWS: | |
731 | parser.error('chg does not work on %s' % os.name) |
|
735 | parser.error('chg does not work on %s' % os.name) | |
732 |
if (options.rhg or options.with_rhg) and |
|
736 | if (options.rhg or options.with_rhg) and WINDOWS: | |
733 | parser.error('rhg does not work on %s' % os.name) |
|
737 | parser.error('rhg does not work on %s' % os.name) | |
734 | if options.with_chg: |
|
738 | if options.with_chg: | |
735 | options.chg = False # no installation to temporary location |
|
739 | options.chg = False # no installation to temporary location | |
@@ -1308,7 +1312,7 b' class Test(unittest.TestCase):' | |||||
1308 | (br'\bHG_TXNID=TXN:[a-f0-9]{40}\b', br'HG_TXNID=TXN:$ID$'), |
|
1312 | (br'\bHG_TXNID=TXN:[a-f0-9]{40}\b', br'HG_TXNID=TXN:$ID$'), | |
1309 | ] |
|
1313 | ] | |
1310 | r.append((self._escapepath(self._testtmp), b'$TESTTMP')) |
|
1314 | r.append((self._escapepath(self._testtmp), b'$TESTTMP')) | |
1311 | if os.name == 'nt': |
|
1315 | if WINDOWS: | |
1312 | # JSON output escapes backslashes in Windows paths, so also catch a |
|
1316 | # JSON output escapes backslashes in Windows paths, so also catch a | |
1313 | # double-escape. |
|
1317 | # double-escape. | |
1314 | replaced = self._testtmp.replace(b'\\', br'\\') |
|
1318 | replaced = self._testtmp.replace(b'\\', br'\\') | |
@@ -1331,7 +1335,7 b' class Test(unittest.TestCase):' | |||||
1331 | return r |
|
1335 | return r | |
1332 |
|
1336 | |||
1333 | def _escapepath(self, p): |
|
1337 | def _escapepath(self, p): | |
1334 | if os.name == 'nt': |
|
1338 | if WINDOWS: | |
1335 | return b''.join( |
|
1339 | return b''.join( | |
1336 | c.isalpha() |
|
1340 | c.isalpha() | |
1337 | and b'[%s%s]' % (c.lower(), c.upper()) |
|
1341 | and b'[%s%s]' % (c.lower(), c.upper()) | |
@@ -1395,7 +1399,7 b' class Test(unittest.TestCase):' | |||||
1395 | env['HGTEST_UUIDFILE'] = uid_file |
|
1399 | env['HGTEST_UUIDFILE'] = uid_file | |
1396 | env['TESTNAME'] = self.name |
|
1400 | env['TESTNAME'] = self.name | |
1397 | env['HOME'] = _bytes2sys(self._testtmp) |
|
1401 | env['HOME'] = _bytes2sys(self._testtmp) | |
1398 | if os.name == 'nt': |
|
1402 | if WINDOWS: | |
1399 | env['REALUSERPROFILE'] = env['USERPROFILE'] |
|
1403 | env['REALUSERPROFILE'] = env['USERPROFILE'] | |
1400 | # py3.8+ ignores HOME: https://bugs.python.org/issue36264 |
|
1404 | # py3.8+ ignores HOME: https://bugs.python.org/issue36264 | |
1401 | env['USERPROFILE'] = env['HOME'] |
|
1405 | env['USERPROFILE'] = env['HOME'] | |
@@ -1444,7 +1448,7 b' class Test(unittest.TestCase):' | |||||
1444 | # This has the same effect as Py_LegacyWindowsStdioFlag in exewrapper.c, |
|
1448 | # This has the same effect as Py_LegacyWindowsStdioFlag in exewrapper.c, | |
1445 | # but this is needed for testing python instances like dummyssh, |
|
1449 | # but this is needed for testing python instances like dummyssh, | |
1446 | # dummysmtpd.py, and dumbhttp.py. |
|
1450 | # dummysmtpd.py, and dumbhttp.py. | |
1447 |
if PYTHON3 and |
|
1451 | if PYTHON3 and WINDOWS: | |
1448 | env['PYTHONLEGACYWINDOWSSTDIO'] = '1' |
|
1452 | env['PYTHONLEGACYWINDOWSSTDIO'] = '1' | |
1449 |
|
1453 | |||
1450 | # Modified HOME in test environment can confuse Rust tools. So set |
|
1454 | # Modified HOME in test environment can confuse Rust tools. So set | |
@@ -1609,8 +1613,7 b' class PythonTest(Test):' | |||||
1609 | # Quote the python(3) executable for Windows |
|
1613 | # Quote the python(3) executable for Windows | |
1610 | cmd = b'"%s" "%s"' % (PYTHON, self.path) |
|
1614 | cmd = b'"%s" "%s"' % (PYTHON, self.path) | |
1611 | vlog("# Running", cmd.decode("utf-8")) |
|
1615 | vlog("# Running", cmd.decode("utf-8")) | |
1612 | normalizenewlines = os.name == 'nt' |
|
1616 | result = self._runcommand(cmd, env, normalizenewlines=WINDOWS) | |
1613 | result = self._runcommand(cmd, env, normalizenewlines=normalizenewlines) |
|
|||
1614 | if self._aborted: |
|
1617 | if self._aborted: | |
1615 | raise KeyboardInterrupt() |
|
1618 | raise KeyboardInterrupt() | |
1616 |
|
1619 | |||
@@ -2083,7 +2086,7 b' class TTest(Test):' | |||||
2083 | flags = flags or b'' |
|
2086 | flags = flags or b'' | |
2084 | el = flags + b'(?:' + el + b')' |
|
2087 | el = flags + b'(?:' + el + b')' | |
2085 | # use \Z to ensure that the regex matches to the end of the string |
|
2088 | # use \Z to ensure that the regex matches to the end of the string | |
2086 | if os.name == 'nt': |
|
2089 | if WINDOWS: | |
2087 | return re.match(el + br'\r?\n\Z', l) |
|
2090 | return re.match(el + br'\r?\n\Z', l) | |
2088 | return re.match(el + br'\n\Z', l) |
|
2091 | return re.match(el + br'\n\Z', l) | |
2089 | except re.error: |
|
2092 | except re.error: | |
@@ -2144,7 +2147,7 b' class TTest(Test):' | |||||
2144 | el = el.encode('latin-1') |
|
2147 | el = el.encode('latin-1') | |
2145 | else: |
|
2148 | else: | |
2146 | el = el[:-7].decode('string-escape') + '\n' |
|
2149 | el = el[:-7].decode('string-escape') + '\n' | |
2147 |
if el == l or |
|
2150 | if el == l or WINDOWS and el[:-1] + b'\r\n' == l: | |
2148 | return True, True |
|
2151 | return True, True | |
2149 | if el.endswith(b" (re)\n"): |
|
2152 | if el.endswith(b" (re)\n"): | |
2150 | return (TTest.rematch(el[:-6], l) or retry), False |
|
2153 | return (TTest.rematch(el[:-6], l) or retry), False | |
@@ -2155,7 +2158,7 b' class TTest(Test):' | |||||
2155 | return (TTest.globmatch(el[:-8], l) or retry), False |
|
2158 | return (TTest.globmatch(el[:-8], l) or retry), False | |
2156 | if os.altsep: |
|
2159 | if os.altsep: | |
2157 | _l = l.replace(b'\\', b'/') |
|
2160 | _l = l.replace(b'\\', b'/') | |
2158 |
if el == _l or |
|
2161 | if el == _l or WINDOWS and el[:-1] + b'\r\n' == _l: | |
2159 | return True, True |
|
2162 | return True, True | |
2160 | return retry, True |
|
2163 | return retry, True | |
2161 |
|
2164 | |||
@@ -2222,7 +2225,7 b' class TestResult(unittest._TextTestResul' | |||||
2222 | # For some reason, redirecting stdout on Windows disables the ANSI |
|
2225 | # For some reason, redirecting stdout on Windows disables the ANSI | |
2223 | # color processing of stderr, which is what is used to print the |
|
2226 | # color processing of stderr, which is what is used to print the | |
2224 | # output. Therefore, both must be tty on Windows to enable color. |
|
2227 | # output. Therefore, both must be tty on Windows to enable color. | |
2225 | if os.name == 'nt': |
|
2228 | if WINDOWS: | |
2226 | isatty = isatty and sys.stdout.isatty() |
|
2229 | isatty = isatty and sys.stdout.isatty() | |
2227 | self.color = pygmentspresent and isatty |
|
2230 | self.color = pygmentspresent and isatty | |
2228 | elif options.color == 'never': |
|
2231 | elif options.color == 'never': | |
@@ -3099,7 +3102,7 b' class TestRunner(object):' | |||||
3099 | os.makedirs(tmpdir) |
|
3102 | os.makedirs(tmpdir) | |
3100 | else: |
|
3103 | else: | |
3101 | d = None |
|
3104 | d = None | |
3102 | if os.name == 'nt': |
|
3105 | if WINDOWS: | |
3103 | # without this, we get the default temp dir location, but |
|
3106 | # without this, we get the default temp dir location, but | |
3104 | # in all lowercase, which causes troubles with paths (issue3490) |
|
3107 | # in all lowercase, which causes troubles with paths (issue3490) | |
3105 | d = osenvironb.get(b'TMP', None) |
|
3108 | d = osenvironb.get(b'TMP', None) | |
@@ -3148,7 +3151,7 b' class TestRunner(object):' | |||||
3148 | # a python script and feed it to python.exe. Legacy stdio is force |
|
3151 | # a python script and feed it to python.exe. Legacy stdio is force | |
3149 | # enabled by hg.exe, and this is a more realistic way to launch hg |
|
3152 | # enabled by hg.exe, and this is a more realistic way to launch hg | |
3150 | # anyway. |
|
3153 | # anyway. | |
3151 |
if |
|
3154 | if WINDOWS and not self._hgcommand.endswith(b'.exe'): | |
3152 | self._hgcommand += b'.exe' |
|
3155 | self._hgcommand += b'.exe' | |
3153 |
|
3156 | |||
3154 | # set CHGHG, then replace "hg" command by "chg" |
|
3157 | # set CHGHG, then replace "hg" command by "chg" | |
@@ -3543,7 +3546,7 b' class TestRunner(object):' | |||||
3543 |
|
3546 | |||
3544 | # os.symlink() is a thing with py3 on Windows, but it requires |
|
3547 | # os.symlink() is a thing with py3 on Windows, but it requires | |
3545 | # Administrator rights. |
|
3548 | # Administrator rights. | |
3546 |
if getattr(os, 'symlink', None) and |
|
3549 | if getattr(os, 'symlink', None) and not WINDOWS: | |
3547 | msg = "# Making python executable in test path a symlink to '%s'" |
|
3550 | msg = "# Making python executable in test path a symlink to '%s'" | |
3548 | msg %= sysexecutable |
|
3551 | msg %= sysexecutable | |
3549 | vlog(msg) |
|
3552 | vlog(msg) | |
@@ -3643,7 +3646,7 b' class TestRunner(object):' | |||||
3643 | self._hgroot = hgroot |
|
3646 | self._hgroot = hgroot | |
3644 | os.chdir(hgroot) |
|
3647 | os.chdir(hgroot) | |
3645 | nohome = b'--home=""' |
|
3648 | nohome = b'--home=""' | |
3646 | if os.name == 'nt': |
|
3649 | if WINDOWS: | |
3647 | # The --home="" trick works only on OS where os.sep == '/' |
|
3650 | # The --home="" trick works only on OS where os.sep == '/' | |
3648 | # because of a distutils convert_path() fast-path. Avoid it at |
|
3651 | # because of a distutils convert_path() fast-path. Avoid it at | |
3649 | # least on Windows for now, deal with .pydistutils.cfg bugs |
|
3652 | # least on Windows for now, deal with .pydistutils.cfg bugs | |
@@ -3862,14 +3865,14 b' class TestRunner(object):' | |||||
3862 | sepb = _sys2bytes(os.pathsep) |
|
3865 | sepb = _sys2bytes(os.pathsep) | |
3863 | for p in osenvironb.get(b'PATH', dpb).split(sepb): |
|
3866 | for p in osenvironb.get(b'PATH', dpb).split(sepb): | |
3864 | name = os.path.join(p, program) |
|
3867 | name = os.path.join(p, program) | |
3865 |
if |
|
3868 | if WINDOWS or os.access(name, os.X_OK): | |
3866 | return _bytes2sys(name) |
|
3869 | return _bytes2sys(name) | |
3867 | return None |
|
3870 | return None | |
3868 |
|
3871 | |||
3869 | def _checktools(self): |
|
3872 | def _checktools(self): | |
3870 | """Ensure tools required to run tests are present.""" |
|
3873 | """Ensure tools required to run tests are present.""" | |
3871 | for p in self.REQUIREDTOOLS: |
|
3874 | for p in self.REQUIREDTOOLS: | |
3872 |
if |
|
3875 | if WINDOWS and not p.endswith(b'.exe'): | |
3873 | p += b'.exe' |
|
3876 | p += b'.exe' | |
3874 | found = self._findprogram(p) |
|
3877 | found = self._findprogram(p) | |
3875 | p = p.decode("utf-8") |
|
3878 | p = p.decode("utf-8") |
@@ -62,6 +62,8 b' def wintests():' | |||||
62 | >>> os.altsep = True |
|
62 | >>> os.altsep = True | |
63 | >>> _osname = os.name |
|
63 | >>> _osname = os.name | |
64 | >>> os.name = 'nt' |
|
64 | >>> os.name = 'nt' | |
|
65 | >>> _old_windows = run_tests.WINDOWS | |||
|
66 | >>> run_tests.WINDOWS = True | |||
65 |
|
67 | |||
66 | valid match on windows |
|
68 | valid match on windows | |
67 | >>> lm(b'g/a*/d (glob)\n', b'g\\abc/d\n') |
|
69 | >>> lm(b'g/a*/d (glob)\n', b'g\\abc/d\n') | |
@@ -80,6 +82,7 b' def wintests():' | |||||
80 | restore os.altsep |
|
82 | restore os.altsep | |
81 | >>> os.altsep = _osaltsep |
|
83 | >>> os.altsep = _osaltsep | |
82 | >>> os.name = _osname |
|
84 | >>> os.name = _osname | |
|
85 | >>> run_tests.WINDOWS = _old_windows | |||
83 | """ |
|
86 | """ | |
84 | pass |
|
87 | pass | |
85 |
|
88 |
General Comments 0
You need to be logged in to leave comments.
Login now