Marco Ricci commited on 2026-06-14 10:05:10
Zeige 1 geänderte Dateien mit 14 Einfügungen und 13 Löschungen.
The tests for various unhappy paths or misbehavior of the SSH agent now run against the stubbed SSH agent, instead of requiring an external SSH agent (and failing or skipping if that external agent is unavailable). The tests need to intercept all I/O from the agent anyway, so there is little point in requiring to connect to an external agent but then not doing any I/O with the agent. It just introduces another unrelated and unnecessary failure mode (e.g., SSH_AUTH_SOCK not set up). We put the fixture for forcing use of the stubbed SSH agent at the top level of the `ssh_agent` module tests, because that currently seems to be the only place where we need to force use of an internal agent over an external one.
| ... | ... |
@@ -38,6 +38,19 @@ if sys.version_info < (3, 11): |
| 38 | 38 |
from exceptiongroup import ExceptionGroup |
| 39 | 39 |
|
| 40 | 40 |
|
| 41 |
+@pytest.fixture |
|
| 42 |
+def use_stub_agent() -> Iterator[None]: |
|
| 43 |
+ """Enforce use of the stubbed SSH agent.""" |
|
| 44 |
+ with pytest.MonkeyPatch.context() as monkeypatch: |
|
| 45 |
+ monkeypatch.setattr( |
|
| 46 |
+ ssh_agent.SSHAgentClient, |
|
| 47 |
+ "SOCKET_PROVIDERS", |
|
| 48 |
+ (_types.BuiltinSSHAgentSocketProvider.STUB_AGENT,), |
|
| 49 |
+ ) |
|
| 50 |
+ monkeypatch.delenv("SSH_AUTH_SOCK", raising=False)
|
|
| 51 |
+ yield |
|
| 52 |
+ |
|
| 53 |
+ |
|
| 41 | 54 |
class Parametrize(types.SimpleNamespace): |
| 42 | 55 |
BAD_ENTRY_POINTS = pytest.mark.parametrize( |
| 43 | 56 |
"additional_entry_points", |
| ... | ... |
@@ -1154,6 +1167,7 @@ class TestOtherConstructorFeatures: |
| 1154 | 1167 |
ssh_agent.SSHAgentClient(socket=conn) |
| 1155 | 1168 |
|
| 1156 | 1169 |
|
| 1170 |
+@pytest.mark.usefixtures("use_stub_agent")
|
|
| 1157 | 1171 |
class TestAgentErrorResponses: |
| 1158 | 1172 |
"""Test actually talking to the SSH agent: errors from the SSH agent.""" |
| 1159 | 1173 |
|
| ... | ... |
@@ -1190,11 +1204,9 @@ class TestAgentErrorResponses: |
| 1190 | 1204 |
@Parametrize.TRUNCATED_AGENT_RESPONSES |
| 1191 | 1205 |
def test_truncated_server_response( |
| 1192 | 1206 |
self, |
| 1193 |
- running_ssh_agent: data.RunningSSHAgentInfo, |
|
| 1194 | 1207 |
response: bytes, |
| 1195 | 1208 |
) -> None: |
| 1196 | 1209 |
"""Fail on truncated responses from the SSH agent.""" |
| 1197 |
- del running_ssh_agent |
|
| 1198 | 1210 |
client = ssh_agent.SSHAgentClient() |
| 1199 | 1211 |
response_stream = io.BytesIO(response) |
| 1200 | 1212 |
|
| ... | ... |
@@ -1214,7 +1226,6 @@ class TestAgentErrorResponses: |
| 1214 | 1226 |
@Parametrize.LIST_KEYS_ERROR_RESPONSES |
| 1215 | 1227 |
def test_list_keys_error_responses( |
| 1216 | 1228 |
self, |
| 1217 |
- running_ssh_agent: data.RunningSSHAgentInfo, |
|
| 1218 | 1229 |
response_code: _types.SSH_AGENT, |
| 1219 | 1230 |
response: bytes | bytearray, |
| 1220 | 1231 |
exc_type: type[Exception], |
| ... | ... |
@@ -1230,7 +1241,6 @@ class TestAgentErrorResponses: |
| 1230 | 1241 |
- The agent response is overlong. |
| 1231 | 1242 |
|
| 1232 | 1243 |
""" |
| 1233 |
- del running_ssh_agent |
|
| 1234 | 1244 |
with self._setup_agent_and_request_handler({
|
| 1235 | 1245 |
data.AgentProtocolRequest( |
| 1236 | 1246 |
_types.SSH_AGENTC.REQUEST_IDENTITIES, b"" |
| ... | ... |
@@ -1243,7 +1253,6 @@ class TestAgentErrorResponses: |
| 1243 | 1253 |
@Parametrize.SIGN_ERROR_RESPONSES |
| 1244 | 1254 |
def test_sign_error_responses( |
| 1245 | 1255 |
self, |
| 1246 |
- running_ssh_agent: data.RunningSSHAgentInfo, |
|
| 1247 | 1256 |
key: bytes | bytearray, |
| 1248 | 1257 |
check: bool, |
| 1249 | 1258 |
response_code: _types.SSH_AGENT, |
| ... | ... |
@@ -1260,7 +1269,6 @@ class TestAgentErrorResponses: |
| 1260 | 1269 |
failed. |
| 1261 | 1270 |
|
| 1262 | 1271 |
""" |
| 1263 |
- del running_ssh_agent |
|
| 1264 | 1272 |
Pair: TypeAlias = _types.SSHKeyCommentPair |
| 1265 | 1273 |
com = b"no comment" |
| 1266 | 1274 |
loaded_keys = [ |
| ... | ... |
@@ -1285,7 +1293,6 @@ class TestAgentErrorResponses: |
| 1285 | 1293 |
@Parametrize.REQUEST_ERROR_RESPONSES |
| 1286 | 1294 |
def test_request_error_responses( |
| 1287 | 1295 |
self, |
| 1288 |
- running_ssh_agent: data.RunningSSHAgentInfo, |
|
| 1289 | 1296 |
request_code: _types.SSH_AGENTC, |
| 1290 | 1297 |
response_code: _types.SSH_AGENT, |
| 1291 | 1298 |
exc_type: type[Exception], |
| ... | ... |
@@ -1300,8 +1307,6 @@ class TestAgentErrorResponses: |
| 1300 | 1307 |
failed. |
| 1301 | 1308 |
|
| 1302 | 1309 |
""" |
| 1303 |
- del running_ssh_agent |
|
| 1304 |
- |
|
| 1305 | 1310 |
# TODO(the-13th-letter): Rewrite using parenthesized |
| 1306 | 1311 |
# with-statements. |
| 1307 | 1312 |
# https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9 |
| ... | ... |
@@ -1313,11 +1318,9 @@ class TestAgentErrorResponses: |
| 1313 | 1318 |
@Parametrize.QUERY_EXTENSIONS_MALFORMED_RESPONSES |
| 1314 | 1319 |
def test_query_extensions_malformed_responses( |
| 1315 | 1320 |
self, |
| 1316 |
- running_ssh_agent: data.RunningSSHAgentInfo, |
|
| 1317 | 1321 |
response_data: bytes, |
| 1318 | 1322 |
) -> None: |
| 1319 | 1323 |
"""Fail on malformed responses while querying extensions.""" |
| 1320 |
- del running_ssh_agent |
|
| 1321 | 1324 |
with self._setup_agent_and_request_handler({
|
| 1322 | 1325 |
data.AgentProtocolRequest( |
| 1323 | 1326 |
_types.SSH_AGENTC.EXTENSION, |
| ... | ... |
@@ -1430,7 +1433,6 @@ class TestAgentErrorResponses: |
| 1430 | 1433 |
) |
| 1431 | 1434 |
def test_tolerating_extra_success_after_extension_response( |
| 1432 | 1435 |
self, |
| 1433 |
- running_ssh_agent: data.RunningSSHAgentInfo, |
|
| 1434 | 1436 |
success_after_query: bool, |
| 1435 | 1437 |
extensions: list[str] | data.AgentProtocolResponse, |
| 1436 | 1438 |
) -> None: |
| ... | ... |
@@ -1450,7 +1452,6 @@ class TestAgentErrorResponses: |
| 1450 | 1452 |
[OPENSSH_BZ3967]: https://bugzilla.mindrot.org/show_bug.cgi?id=3967 |
| 1451 | 1453 |
|
| 1452 | 1454 |
""" |
| 1453 |
- del running_ssh_agent |
|
| 1454 | 1455 |
query_response = ( |
| 1455 | 1456 |
extensions |
| 1456 | 1457 |
if isinstance(extensions, data.AgentProtocolResponse) |
| 1457 | 1458 |