annotate tests/test-stdio.py @ 45043:be58fb1eaa73

procutil: make stdout line-buffered on Windows if connected to TTY Windows doesn’t support line buffering. Previously, we worked around that by setting the stream unbuffered. Instead, we can use our own line buffering we already use on Python 3.
author Manuel Jacob <me@manueljacob.de>
date Sat, 04 Jul 2020 11:41:39 +0200
parents c7d109c400a4
children 359884685eab
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
1 #!/usr/bin/env python
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
2 """
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
3 Tests the buffering behavior of stdio streams in `mercurial.utils.procutil`.
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
4 """
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
5 from __future__ import absolute_import
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
6
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
7 import contextlib
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
8 import os
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
9 import subprocess
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
10 import sys
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
11 import unittest
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
12
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
13 from mercurial import pycompat
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
14
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
15
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
16 CHILD_PROCESS = r'''
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
17 import os
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
18
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
19 from mercurial import dispatch
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
20 from mercurial.utils import procutil
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
21
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
22 dispatch.initstdio()
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
23 procutil.stdout.write(b'aaa')
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
24 os.write(procutil.stdout.fileno(), b'[written aaa]')
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
25 procutil.stdout.write(b'bbb\n')
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
26 os.write(procutil.stdout.fileno(), b'[written bbb\\n]')
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
27 '''
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
28 UNBUFFERED = b'aaa[written aaa]bbb\n[written bbb\\n]'
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
29 LINE_BUFFERED = b'[written aaa]aaabbb\n[written bbb\\n]'
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
30 FULLY_BUFFERED = b'[written aaa][written bbb\\n]aaabbb\n'
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
31
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
32
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
33 @contextlib.contextmanager
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
34 def _closing(fds):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
35 try:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
36 yield
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
37 finally:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
38 for fd in fds:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
39 try:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
40 os.close(fd)
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
41 except EnvironmentError:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
42 pass
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
43
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
44
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
45 @contextlib.contextmanager
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
46 def _pipes():
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
47 rwpair = os.pipe()
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
48 with _closing(rwpair):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
49 yield rwpair
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
50
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
51
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
52 @contextlib.contextmanager
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
53 def _ptys():
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
54 if pycompat.iswindows:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
55 raise unittest.SkipTest("PTYs are not supported on Windows")
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
56 import pty
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
57 import tty
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
58
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
59 rwpair = pty.openpty()
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
60 with _closing(rwpair):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
61 tty.setraw(rwpair[0])
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
62 yield rwpair
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
63
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
64
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
65 class TestStdout(unittest.TestCase):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
66 def _test(self, rwpair_generator, expected_output, python_args=[]):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
67 with rwpair_generator() as (stdout_receiver, child_stdout), open(
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
68 os.devnull, 'rb'
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
69 ) as child_stdin:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
70 proc = subprocess.Popen(
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
71 [sys.executable] + python_args + ['-c', CHILD_PROCESS],
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
72 stdin=child_stdin,
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
73 stdout=child_stdout,
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
74 stderr=None,
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
75 )
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
76 retcode = proc.wait()
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
77 self.assertEqual(retcode, 0)
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
78 self.assertEqual(os.read(stdout_receiver, 1024), expected_output)
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
79
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
80 def test_stdout_pipes(self):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
81 self._test(_pipes, FULLY_BUFFERED)
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
82
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
83 def test_stdout_ptys(self):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
84 self._test(_ptys, LINE_BUFFERED)
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
85
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
86 def test_stdout_pipes_unbuffered(self):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
87 self._test(_pipes, UNBUFFERED, python_args=['-u'])
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
88
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
89 def test_stdout_ptys_unbuffered(self):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
90 self._test(_ptys, UNBUFFERED, python_args=['-u'])
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
91
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
92 if not pycompat.ispy3 and not pycompat.iswindows:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
93 # On Python 2 on non-Windows, we manually open stdout in line-buffered
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
94 # mode if connected to a TTY. We should check if Python was configured
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
95 # to use unbuffered stdout, but it's hard to do that.
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
96 test_stdout_ptys_unbuffered = unittest.expectedFailure(
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
97 test_stdout_ptys_unbuffered
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
98 )
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
99
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
100
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
101 if __name__ == '__main__':
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
102 import silenttestrunner
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
103
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
104 silenttestrunner.main(__name__)