Skip to content

Commit 6e93e80

Browse files
committed
test for setting log level
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
1 parent 9111bff commit 6e93e80

2 files changed

Lines changed: 169 additions & 0 deletions

File tree

tests/conftest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,23 @@
1616
from pylibsshext.logging import ANSIBLE_PYLIBSSH_TRACE
1717
from pylibsshext.session import Session
1818

19+
from pylibsshext import __libssh_version__
20+
1921

2022
_DIR_PRIV_RW_OWNER = 0o700
2123
_FILE_PRIV_RW_OWNER = 0o600
2224

2325

26+
@pytest.fixture
27+
def libssh_version_tuple():
28+
"""
29+
Get the libssh version as a tuple of (major, minor, patch).
30+
31+
This is useful for simple comparison and conditioning tests based on this value.
32+
"""
33+
return tuple(map(int, (__libssh_version__.split('.'))))
34+
35+
2436
@pytest.fixture
2537
def free_port_num():
2638
"""Detect a free port number using a temporary ephemeral port.

tests/integration/logging_test.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
"""Tests suite for logging."""
2+
3+
import contextlib as _ctx
4+
import logging
5+
6+
import pytest
7+
8+
from pylibsshext.errors import LibsshSessionException
9+
from pylibsshext.logging import ANSIBLE_PYLIBSSH_NOLOG, ANSIBLE_PYLIBSSH_TRACE
10+
from pylibsshext.session import Session
11+
12+
13+
LOCALHOST = '127.0.0.1'
14+
BAD_LOG_LEVEL = 99
15+
16+
17+
@pytest.fixture(autouse=True)
18+
def _only_capture_project_logs(caplog: pytest.LogCaptureFixture) -> None:
19+
"""Hide unrelated log entries from capture."""
20+
caplog.set_level(ANSIBLE_PYLIBSSH_NOLOG + 1) # root logger
21+
caplog.set_level(
22+
logging.NOTSET,
23+
logger='ansible-pylibssh',
24+
) # don't block things early
25+
caplog.clear()
26+
27+
28+
def test_session_log_level_warning(
29+
caplog: pytest.LogCaptureFixture,
30+
free_port_num: int,
31+
libssh_version_tuple,
32+
) -> None:
33+
"""
34+
Test setting the log level to WARNING.
35+
36+
It should show "Connection refused" on libssh 0.11.0 and newer.
37+
But no debug/ainfo/trace messages.
38+
"""
39+
ssh_session = Session()
40+
# keeping these in sync makes sure the log levels are not "lost"
41+
# in the processing. Technically, setting the log level in libssh
42+
# is not needed as the default is logging everything but filtering
43+
# is done on the python side
44+
ssh_session.set_log_level(logging.WARNING)
45+
caplog.set_level(logging.WARNING)
46+
47+
# the connection will fail but first log lands before that
48+
with _ctx.suppress(LibsshSessionException):
49+
ssh_session.connect(host=LOCALHOST, port=free_port_num)
50+
51+
log_records = caplog.records
52+
53+
# This message is available only in libssh 0.11.0 and newer
54+
expected_substring = 'ssh_client_connection_callback: Connection refused'
55+
if libssh_version_tuple >= (0, 11, 0):
56+
assert any(
57+
record.levelname == 'WARNING' and expected_substring in record.msg
58+
for record in log_records
59+
)
60+
61+
# No INFO and higher log messages should show up at this log level
62+
assert all(record.levelname != 'INFO' for record in log_records)
63+
assert all(record.levelname != 'DEBUG' for record in log_records)
64+
assert all(record.levelname != 'TRACE' for record in log_records)
65+
66+
67+
def test_session_log_level_debug(
68+
caplog: pytest.LogCaptureFixture,
69+
free_port_num: int,
70+
libssh_version_tuple,
71+
) -> None:
72+
"""
73+
Test setting the log level to DEBUG.
74+
75+
It should reveal copyright information. But no trace messages.
76+
"""
77+
ssh_session = Session()
78+
ssh_session.set_log_level(logging.DEBUG)
79+
caplog.set_level(logging.DEBUG)
80+
81+
# the connection will fail but first log lands before that
82+
with _ctx.suppress(LibsshSessionException):
83+
ssh_session.connect(host=LOCALHOST, port=free_port_num)
84+
85+
log_records = caplog.records
86+
87+
expected_copyright_substring = 'and libssh contributors.'
88+
# This log message is shown at different log levels
89+
# in different libssh versions. Changed at 657d9143d1 (before 0.11.0)
90+
expected_copyright_log_level = 'DEBUG'
91+
if libssh_version_tuple < (0, 10, 4):
92+
expected_copyright_log_level = 'INFO'
93+
assert any(
94+
record.levelname == expected_copyright_log_level
95+
and expected_copyright_substring in record.msg
96+
for record in log_records
97+
)
98+
99+
# No TRACE log messages should show up at this log level
100+
assert all(record.levelname != 'TRACE' for record in log_records)
101+
102+
103+
def test_session_log_level_no_log(
104+
caplog: pytest.LogCaptureFixture,
105+
free_port_num: int,
106+
) -> None:
107+
"""Test setting the log level to NOLOG should be quiet."""
108+
ssh_session = Session()
109+
ssh_session.set_log_level(ANSIBLE_PYLIBSSH_NOLOG)
110+
caplog.set_level(ANSIBLE_PYLIBSSH_NOLOG)
111+
112+
# the connection will fail but first log lands before that
113+
with _ctx.suppress(LibsshSessionException):
114+
ssh_session.connect(host=LOCALHOST, port=free_port_num)
115+
116+
assert not caplog.records
117+
118+
119+
def test_session_log_level_trace(
120+
caplog: pytest.LogCaptureFixture,
121+
free_port_num: int,
122+
) -> None:
123+
"""Test setting the log level to TRACE should provide all of the logs."""
124+
ssh_session = Session()
125+
ssh_session.set_log_level(ANSIBLE_PYLIBSSH_TRACE)
126+
caplog.set_level(ANSIBLE_PYLIBSSH_TRACE)
127+
128+
with _ctx.suppress(LibsshSessionException):
129+
ssh_session.connect(host=LOCALHOST, port=free_port_num)
130+
131+
expected_poll_message = 'ssh_socket_pollcallback: Poll callback on socket'
132+
assert expected_poll_message in caplog.text
133+
134+
135+
def test_session_log_level_not_set(
136+
caplog: pytest.LogCaptureFixture,
137+
free_port_num: int,
138+
) -> None:
139+
"""Test setting the log level to NOTSET = all messages should be logged too."""
140+
ssh_session = Session()
141+
ssh_session.set_log_level(logging.NOTSET)
142+
caplog.set_level(logging.NOTSET)
143+
144+
with _ctx.suppress(LibsshSessionException):
145+
ssh_session.connect(host=LOCALHOST, port=free_port_num)
146+
147+
expected_poll_message = 'ssh_socket_pollcallback: Poll callback on socket'
148+
assert expected_poll_message in caplog.text
149+
150+
151+
def test_session_log_level_bad():
152+
"""Test that setting the log level to an unsupported value is rejected."""
153+
ssh_session = Session()
154+
155+
error_msg = r'^Invalid log level \[99\]$'
156+
with pytest.raises(LibsshSessionException, match=error_msg):
157+
ssh_session.set_log_level(BAD_LOG_LEVEL)

0 commit comments

Comments
 (0)