annotate tests/test-stdio.py @ 50400:95acba2c29f6

encoding: avoid quadratic time complexity when json-encoding non-UTF8 strings Apparently the code uses "+=" with a bytes object, which is linear-time, so the whole encoding is quadratic-time. This patch makes us use a bytearray object, instead, which has a(n amortized-)constant-time append operation. The encoding is still not particularly fast, but at least a 10MB file takes tens of seconds, not many hours to encode.
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Mon, 06 Mar 2023 11:27:57 +0000
parents 402f9f0f9387
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
47500
23f5ed6dbcb1 run-tests: stop writing a `python3` symlink pointing to python2
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 45830
diff changeset
1 #!/usr/bin/env python
45038
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
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
6 import contextlib
45068
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
7 import errno
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
8 import os
48870
df56e6bd37f6 py3: use pickle directly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 47500
diff changeset
9 import pickle
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
10 import signal
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
11 import subprocess
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
12 import sys
45097
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
13 import tempfile
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
14 import unittest
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
15
45148
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
16 from mercurial import pycompat, util
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
17
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
18
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
19 TEST_BUFFERING_CHILD_SCRIPT = r'''
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
20 import os
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 from mercurial import dispatch
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
23 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
24
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
25 dispatch.initstdio()
45044
359884685eab tests: generalize common test case code in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45043
diff changeset
26 procutil.{stream}.write(b'aaa')
359884685eab tests: generalize common test case code in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45043
diff changeset
27 os.write(procutil.{stream}.fileno(), b'[written aaa]')
359884685eab tests: generalize common test case code in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45043
diff changeset
28 procutil.{stream}.write(b'bbb\n')
359884685eab tests: generalize common test case code in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45043
diff changeset
29 os.write(procutil.{stream}.fileno(), b'[written bbb\\n]')
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
30 '''
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
31 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
32 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
33 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
34
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
35
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
36 TEST_LARGE_WRITE_CHILD_SCRIPT = r'''
45104
eb26a9cf7821 procutil: avoid use of deprecated tempfile.mktemp()
Manuel Jacob <me@manueljacob.de>
parents: 45097
diff changeset
37 import os
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
38 import signal
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
39 import sys
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
40
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
41 from mercurial import dispatch
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
42 from mercurial.utils import procutil
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
43
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
44 signal.signal(signal.SIGINT, lambda *x: None)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
45 dispatch.initstdio()
45097
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
46 write_result = procutil.{stream}.write(b'x' * 1048576)
45104
eb26a9cf7821 procutil: avoid use of deprecated tempfile.mktemp()
Manuel Jacob <me@manueljacob.de>
parents: 45097
diff changeset
47 with os.fdopen(
eb26a9cf7821 procutil: avoid use of deprecated tempfile.mktemp()
Manuel Jacob <me@manueljacob.de>
parents: 45097
diff changeset
48 os.open({write_result_fn!r}, os.O_WRONLY | getattr(os, 'O_TEMPORARY', 0)),
eb26a9cf7821 procutil: avoid use of deprecated tempfile.mktemp()
Manuel Jacob <me@manueljacob.de>
parents: 45097
diff changeset
49 'w',
eb26a9cf7821 procutil: avoid use of deprecated tempfile.mktemp()
Manuel Jacob <me@manueljacob.de>
parents: 45097
diff changeset
50 ) as write_result_f:
45097
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
51 write_result_f.write(str(write_result))
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
52 '''
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
53
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
54
45148
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
55 TEST_BROKEN_PIPE_CHILD_SCRIPT = r'''
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
56 import os
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
57 import pickle
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
58
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
59 from mercurial import dispatch
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
60 from mercurial.utils import procutil
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
61
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
62 dispatch.initstdio()
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
63 procutil.stdin.read(1) # wait until parent process closed pipe
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
64 try:
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
65 procutil.{stream}.write(b'test')
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
66 procutil.{stream}.flush()
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
67 except EnvironmentError as e:
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
68 with os.fdopen(
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
69 os.open(
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
70 {err_fn!r},
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
71 os.O_WRONLY
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
72 | getattr(os, 'O_BINARY', 0)
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
73 | getattr(os, 'O_TEMPORARY', 0),
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
74 ),
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
75 'wb',
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
76 ) as err_f:
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
77 pickle.dump(e, err_f)
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
78 # Exit early to suppress further broken pipe errors at interpreter shutdown.
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
79 os._exit(0)
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
80 '''
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
81
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
82
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
83 @contextlib.contextmanager
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
84 def _closing(fds):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
85 try:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
86 yield
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
87 finally:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
88 for fd in fds:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
89 try:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
90 os.close(fd)
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
91 except EnvironmentError:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
92 pass
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
93
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
94
45147
c2c862b9b544 tests: make pipes / PTYs non-inheritable in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45104
diff changeset
95 # In the following, we set the FDs non-inheritable mainly to make it possible
c2c862b9b544 tests: make pipes / PTYs non-inheritable in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45104
diff changeset
96 # for tests to close the receiving end of the pipe / PTYs.
c2c862b9b544 tests: make pipes / PTYs non-inheritable in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45104
diff changeset
97
c2c862b9b544 tests: make pipes / PTYs non-inheritable in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45104
diff changeset
98
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
99 @contextlib.contextmanager
45096
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
100 def _devnull():
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
101 devnull = os.open(os.devnull, os.O_WRONLY)
45147
c2c862b9b544 tests: make pipes / PTYs non-inheritable in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45104
diff changeset
102 # We don't have a receiving end, so it's not worth the effort on Python 2
c2c862b9b544 tests: make pipes / PTYs non-inheritable in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45104
diff changeset
103 # on Windows to make the FD non-inheritable.
45096
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
104 with _closing([devnull]):
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
105 yield (None, devnull)
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
106
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
107
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
108 @contextlib.contextmanager
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
109 def _pipes():
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
110 rwpair = os.pipe()
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
111 with _closing(rwpair):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
112 yield rwpair
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
113
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
114
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
115 @contextlib.contextmanager
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
116 def _ptys():
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
117 if pycompat.iswindows:
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
118 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
119 import pty
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
120 import tty
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
121
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
122 rwpair = pty.openpty()
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
123 with _closing(rwpair):
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
124 tty.setraw(rwpair[0])
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
125 yield rwpair
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
126
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
127
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
128 def _readall(fd, buffer_size, initial_buf=None):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
129 buf = initial_buf or []
45068
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
130 while True:
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
131 try:
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
132 s = os.read(fd, buffer_size)
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
133 except OSError as e:
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
134 if e.errno == errno.EIO:
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
135 # If the child-facing PTY got closed, reading from the
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
136 # parent-facing PTY raises EIO.
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
137 break
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
138 raise
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
139 if not s:
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
140 break
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
141 buf.append(s)
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
142 return b''.join(buf)
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
143
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
144
45044
359884685eab tests: generalize common test case code in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45043
diff changeset
145 class TestStdio(unittest.TestCase):
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
146 def _test(
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
147 self,
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
148 child_script,
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
149 stream,
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
150 rwpair_generator,
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
151 check_output,
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
152 python_args=[],
45097
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
153 post_child_check=None,
45148
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
154 stdin_generator=None,
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
155 ):
45044
359884685eab tests: generalize common test case code in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45043
diff changeset
156 assert stream in ('stdout', 'stderr')
45148
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
157 if stdin_generator is None:
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
158 stdin_generator = open(os.devnull, 'rb')
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
159 with rwpair_generator() as (
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
160 stream_receiver,
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
161 child_stream,
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
162 ), stdin_generator as child_stdin:
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
163 proc = subprocess.Popen(
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
164 [sys.executable] + python_args + ['-c', child_script],
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
165 stdin=child_stdin,
45044
359884685eab tests: generalize common test case code in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45043
diff changeset
166 stdout=child_stream if stream == 'stdout' else None,
359884685eab tests: generalize common test case code in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45043
diff changeset
167 stderr=child_stream if stream == 'stderr' else None,
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
168 )
45068
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
169 try:
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
170 os.close(child_stream)
45096
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
171 if stream_receiver is not None:
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
172 check_output(stream_receiver, proc)
45069
9172fd511999 tests: terminate subprocess in test-stdio.py in case of exception
Manuel Jacob <me@manueljacob.de>
parents: 45068
diff changeset
173 except: # re-raises
9172fd511999 tests: terminate subprocess in test-stdio.py in case of exception
Manuel Jacob <me@manueljacob.de>
parents: 45068
diff changeset
174 proc.terminate()
9172fd511999 tests: terminate subprocess in test-stdio.py in case of exception
Manuel Jacob <me@manueljacob.de>
parents: 45068
diff changeset
175 raise
45068
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
176 finally:
8cd18aba5e6c tests: proof test-stdio.py against buffer fill-up
Manuel Jacob <me@manueljacob.de>
parents: 45045
diff changeset
177 retcode = proc.wait()
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
178 self.assertEqual(retcode, 0)
45097
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
179 if post_child_check is not None:
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
180 post_child_check()
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
181
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
182 def _test_buffering(
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
183 self, stream, rwpair_generator, expected_output, python_args=[]
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
184 ):
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
185 def check_output(stream_receiver, proc):
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
186 self.assertEqual(_readall(stream_receiver, 1024), expected_output)
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
187
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
188 self._test(
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
189 TEST_BUFFERING_CHILD_SCRIPT.format(stream=stream),
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
190 stream,
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
191 rwpair_generator,
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
192 check_output,
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
193 python_args,
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
194 )
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
195
45096
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
196 def test_buffering_stdout_devnull(self):
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
197 self._test_buffering('stdout', _devnull, None)
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
198
45070
bc05c13e246f tests: make names in test-stdio.py more distinctive
Manuel Jacob <me@manueljacob.de>
parents: 45069
diff changeset
199 def test_buffering_stdout_pipes(self):
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
200 self._test_buffering('stdout', _pipes, FULLY_BUFFERED)
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
201
45070
bc05c13e246f tests: make names in test-stdio.py more distinctive
Manuel Jacob <me@manueljacob.de>
parents: 45069
diff changeset
202 def test_buffering_stdout_ptys(self):
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
203 self._test_buffering('stdout', _ptys, LINE_BUFFERED)
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
204
45096
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
205 def test_buffering_stdout_devnull_unbuffered(self):
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
206 self._test_buffering('stdout', _devnull, None, python_args=['-u'])
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
207
45070
bc05c13e246f tests: make names in test-stdio.py more distinctive
Manuel Jacob <me@manueljacob.de>
parents: 45069
diff changeset
208 def test_buffering_stdout_pipes_unbuffered(self):
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
209 self._test_buffering('stdout', _pipes, UNBUFFERED, python_args=['-u'])
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
210
45070
bc05c13e246f tests: make names in test-stdio.py more distinctive
Manuel Jacob <me@manueljacob.de>
parents: 45069
diff changeset
211 def test_buffering_stdout_ptys_unbuffered(self):
45078
a59aab6078eb tests: make subprocess handling reusable for different tests in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 45077
diff changeset
212 self._test_buffering('stdout', _ptys, UNBUFFERED, python_args=['-u'])
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
213
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
214 def _test_large_write(self, stream, rwpair_generator, python_args=[]):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
215 def check_output(stream_receiver, proc):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
216 if not pycompat.iswindows:
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
217 # On Unix, we can provoke a partial write() by interrupting it
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
218 # by a signal handler as soon as a bit of data was written.
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
219 # We test that write() is called until all data is written.
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
220 buf = [os.read(stream_receiver, 1)]
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
221 proc.send_signal(signal.SIGINT)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
222 else:
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
223 # On Windows, there doesn't seem to be a way to cause partial
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
224 # writes.
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
225 buf = []
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
226 self.assertEqual(
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
227 _readall(stream_receiver, 131072, buf), b'x' * 1048576
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
228 )
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
229
45097
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
230 def post_child_check():
49297
402f9f0f9387 tests: remove Python 2 special cases in test-stdio.py
Manuel Jacob <me@manueljacob.de>
parents: 49296
diff changeset
231 self.assertEqual(write_result_f.read(), '1048576')
45097
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
232
45104
eb26a9cf7821 procutil: avoid use of deprecated tempfile.mktemp()
Manuel Jacob <me@manueljacob.de>
parents: 45097
diff changeset
233 with tempfile.NamedTemporaryFile('r') as write_result_f:
45097
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
234 self._test(
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
235 TEST_LARGE_WRITE_CHILD_SCRIPT.format(
45104
eb26a9cf7821 procutil: avoid use of deprecated tempfile.mktemp()
Manuel Jacob <me@manueljacob.de>
parents: 45097
diff changeset
236 stream=stream, write_result_fn=write_result_f.name
45097
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
237 ),
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
238 stream,
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
239 rwpair_generator,
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
240 check_output,
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
241 python_args,
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
242 post_child_check=post_child_check,
dff208398ede tests: check that procutil.std{out,err}.write() returns correct result
Manuel Jacob <me@manueljacob.de>
parents: 45096
diff changeset
243 )
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
244
45096
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
245 def test_large_write_stdout_devnull(self):
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
246 self._test_large_write('stdout', _devnull)
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
247
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
248 def test_large_write_stdout_pipes(self):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
249 self._test_large_write('stdout', _pipes)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
250
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
251 def test_large_write_stdout_ptys(self):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
252 self._test_large_write('stdout', _ptys)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
253
45096
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
254 def test_large_write_stdout_devnull_unbuffered(self):
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
255 self._test_large_write('stdout', _devnull, python_args=['-u'])
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
256
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
257 def test_large_write_stdout_pipes_unbuffered(self):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
258 self._test_large_write('stdout', _pipes, python_args=['-u'])
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
259
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
260 def test_large_write_stdout_ptys_unbuffered(self):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
261 self._test_large_write('stdout', _ptys, python_args=['-u'])
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
262
45096
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
263 def test_large_write_stderr_devnull(self):
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
264 self._test_large_write('stderr', _devnull)
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
265
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
266 def test_large_write_stderr_pipes(self):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
267 self._test_large_write('stderr', _pipes)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
268
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
269 def test_large_write_stderr_ptys(self):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
270 self._test_large_write('stderr', _ptys)
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
271
45096
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
272 def test_large_write_stderr_devnull_unbuffered(self):
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
273 self._test_large_write('stderr', _devnull, python_args=['-u'])
e9e452eafbfb tests: add tests for when stdout or stderr is connected to `os.devnull`
Manuel Jacob <me@manueljacob.de>
parents: 45095
diff changeset
274
45095
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
275 def test_large_write_stderr_pipes_unbuffered(self):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
276 self._test_large_write('stderr', _pipes, python_args=['-u'])
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
277
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
278 def test_large_write_stderr_ptys_unbuffered(self):
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
279 self._test_large_write('stderr', _ptys, python_args=['-u'])
8e04607023e5 procutil: ensure that procutil.std{out,err}.write() writes all bytes
Manuel Jacob <me@manueljacob.de>
parents: 45078
diff changeset
280
45148
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
281 def _test_broken_pipe(self, stream):
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
282 assert stream in ('stdout', 'stderr')
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
283
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
284 def check_output(stream_receiver, proc):
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
285 os.close(stream_receiver)
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
286 proc.stdin.write(b'x')
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
287 proc.stdin.close()
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
288
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
289 def post_child_check():
48870
df56e6bd37f6 py3: use pickle directly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 47500
diff changeset
290 err = pickle.load(err_f)
45148
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
291 self.assertEqual(err.errno, errno.EPIPE)
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
292 self.assertEqual(err.strerror, "Broken pipe")
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
293
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
294 with tempfile.NamedTemporaryFile('rb') as err_f:
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
295 self._test(
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
296 TEST_BROKEN_PIPE_CHILD_SCRIPT.format(
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
297 stream=stream, err_fn=err_f.name
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
298 ),
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
299 stream,
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
300 _pipes,
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
301 check_output,
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
302 post_child_check=post_child_check,
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
303 stdin_generator=util.nullcontextmanager(subprocess.PIPE),
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
304 )
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
305
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
306 def test_broken_pipe_stdout(self):
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
307 self._test_broken_pipe('stdout')
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
308
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
309 def test_broken_pipe_stderr(self):
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
310 self._test_broken_pipe('stderr')
a37f290a7124 windows: always work around EINVAL in case of broken pipe for stdout / stderr
Manuel Jacob <me@manueljacob.de>
parents: 45147
diff changeset
311
45038
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
312
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
313 if __name__ == '__main__':
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
314 import silenttestrunner
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
315
c7d109c400a4 tests: add tests for buffering behavior of mercurial.utils.procutil.stdout
Manuel Jacob <me@manueljacob.de>
parents:
diff changeset
316 silenttestrunner.main(__name__)