tests/test-stdio.py
author Raphaël Gomès <rgomes@octobus.net>
Mon, 30 Sep 2024 17:45:10 +0200
changeset 52034 b55f653a0b34
parent 49297 402f9f0f9387
permissions -rwxr-xr-x
rust-utils: move the `filesystem_now` function to a util This is going to be useful for an upcoming `hg update` fastpath.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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__)