1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
|
import fcntl
import termios
from mock import Mock, patch
from pytest import skip, mark
from invoke.terminals import pty_size, bytes_to_read, WINDOWS
# Skip on Windows CI, it may blow up on one of these tests
pytestmark = mark.skipif(
WINDOWS, reason="Low level terminal tests only work well on POSIX"
)
# NOTE: 'with character_buffered()' tests are in runners.py as it's a lot
# easier to test some aspects in a non-unit sense (e.g. a keyboard-interrupting
# Runner subclass). MEH.
class terminals:
class pty_size:
@patch("fcntl.ioctl", wraps=fcntl.ioctl)
def calls_fcntl_with_TIOCGWINSZ(self, ioctl):
# Test the default (Unix) implementation because that's all we
# can realistically do here.
pty_size()
assert ioctl.call_args_list[0][0][1] == termios.TIOCGWINSZ
@patch("sys.stdout")
@patch("fcntl.ioctl")
def defaults_to_80x24_when_stdout_not_a_tty(self, ioctl, stdout):
# Make sure stdout acts like a real stream (means failure is
# more obvious)
stdout.fileno.return_value = 1
# Ensure it fails the isatty() test too
stdout.isatty.return_value = False
# Test
assert pty_size() == (80, 24)
@patch("sys.stdout")
@patch("fcntl.ioctl")
def uses_default_when_stdout_lacks_fileno(self, ioctl, stdout):
# i.e. when accessing it throws AttributeError
stdout.fileno.side_effect = AttributeError
assert pty_size() == (80, 24)
@patch("sys.stdout")
@patch("fcntl.ioctl")
def uses_default_when_stdout_triggers_ioctl_error(self, ioctl, stdout):
ioctl.side_effect = TypeError
assert pty_size() == (80, 24)
class bytes_to_read_:
@patch("invoke.terminals.fcntl")
def returns_1_when_stream_lacks_fileno(self, fcntl):
# A fileno() that exists but returns a non-int is a quick way
# to fail util.has_fileno().
assert bytes_to_read(Mock(fileno=lambda: None)) == 1
assert not fcntl.ioctl.called
@patch("invoke.terminals.fcntl")
def returns_1_when_stream_has_fileno_but_is_not_a_tty(self, fcntl):
# It blows up otherwise anyways (struct.unpack gets mad because
# result isn't a string of the right length) but let's make
# ioctl die similarly to the real world case we're testing for
# here (#425)
fcntl.ioctl.side_effect = IOError(
"Operation not supported by device"
)
stream = Mock(isatty=lambda: False, fileno=lambda: 17) # arbitrary
assert bytes_to_read(stream) == 1
assert not fcntl.ioctl.called
def returns_FIONREAD_result_when_stream_is_a_tty(self):
skip()
def returns_1_on_windows(self):
skip()
|