This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 41eff9bd37c Fix flaky test_command_timeout_fail in SSH provider
(#65864)
41eff9bd37c is described below
commit 41eff9bd37c45ad42ddbd0271519ed416c89640e
Author: Dev-iL <[email protected]>
AuthorDate: Fri Jul 31 22:16:15 2026 +0300
Fix flaky test_command_timeout_fail in SSH provider (#65864)
---
providers/ssh/tests/unit/ssh/hooks/test_ssh.py | 49 ++++++++++++++++++--------
1 file changed, 35 insertions(+), 14 deletions(-)
diff --git a/providers/ssh/tests/unit/ssh/hooks/test_ssh.py
b/providers/ssh/tests/unit/ssh/hooks/test_ssh.py
index baf1847ec9a..3a6cf30528b 100644
--- a/providers/ssh/tests/unit/ssh/hooks/test_ssh.py
+++ b/providers/ssh/tests/unit/ssh/hooks/test_ssh.py
@@ -929,26 +929,47 @@ class TestSSHHook:
assert ret == (0, b"airflow\n", b"")
def test_command_timeout_fail(self):
- # cmd_timeout is forwarded to paramiko's exec_command, which uses it
both to open the
- # channel and to read the command output. It must therefore be large
enough to reliably
- # open the channel (otherwise a loaded runner raises "Timeout opening
channel." instead of
- # the AirflowException we expect) while staying smaller than the
command runtime so the
- # read loop times out. A sub-millisecond timeout makes channel opening
flaky.
hook = SSHHook(
ssh_conn_id="ssh_default",
conn_timeout=30,
- cmd_timeout=0.5,
+ cmd_timeout=0.001,
banner_timeout=100,
)
- with hook.get_conn() as client:
- with pytest.raises(AirflowException):
- hook.exec_ssh_client_command(
- client,
- "sleep 5",
- False,
- None,
- )
+ mock_channel = mock.MagicMock(spec=paramiko.Channel)
+ type(mock_channel).closed = mock.PropertyMock(return_value=False)
+ mock_channel.recv_ready.return_value = False
+ mock_channel.recv_stderr_ready.return_value = False
+ mock_channel.exit_status_ready.return_value = False
+ mock_channel.in_buffer = b""
+ mock_channel.in_stderr_buffer = b""
+
+ mock_stdout = mock.MagicMock(spec=paramiko.ChannelFile)
+ mock_stdout.channel = mock_channel
+ mock_stdin = mock.MagicMock(spec=paramiko.ChannelStdinFile)
+ mock_stderr = mock.MagicMock(spec=paramiko.ChannelStderrFile)
+ mock_stderr.channel = mock_channel
+
+ mock_client = mock.MagicMock(spec=paramiko.SSHClient)
+ mock_client.exec_command.return_value = (mock_stdin, mock_stdout,
mock_stderr)
+
+ def fake_select(rlist, wlist, xlist, timeout=None):
+ assert timeout == pytest.approx(0.001), f"Expected cmd_timeout
passed to select, got {timeout}"
+ return [], [], []
+
+ with mock.patch("airflow.providers.ssh.hooks.ssh.select",
side_effect=fake_select):
+ with pytest.raises(AirflowException, match="SSH command timed
out"):
+ hook.exec_ssh_client_command(mock_client, "sleep 1", False,
None)
+
+ assert mock_client.exec_command.call_args_list == [
+ mock.call(command="sleep 1", get_pty=False, timeout=0.001,
environment=None)
+ ]
+ assert mock.call() in mock_stdin.close.call_args_list
+ assert mock.call() in mock_channel.shutdown_write.call_args_list
+ assert mock.call() in mock_channel.shutdown_read.call_args_list
+ assert mock.call() in mock_channel.close.call_args_list
+ assert mock.call() in mock_stdout.close.call_args_list
+ assert mock.call() in mock_stderr.close.call_args_list
def test_command_timeout_not_set(self, monkeypatch):
hook = SSHHook(