Marco Ricci commited on 2026-07-04 21:10:03
Zeige 3 geänderte Dateien mit 42 Einfügungen und 113 Löschungen.
Implement the "missing system support for the SSH agent communication channel" setup code via the now centralized `tests.data.SystemSupportAction` enum, instead of duplicating the setup steps everywhere. This means adding the correct `SystemSupportAction` value to the `MISSING_AGENT_SUPPORT` parametrization set. In particular, since this parametrization set is already used in two different test modules, put it into `tests.machinery.pytest.Parametrize`.
| ... | ... |
@@ -36,7 +36,11 @@ from typing_extensions import assert_never, overload |
| 36 | 36 |
import tests.data |
| 37 | 37 |
import tests.machinery |
| 38 | 38 |
from derivepassphrase import _types, ssh_agent |
| 39 |
-from derivepassphrase._internals import cli_helpers, cli_machinery |
|
| 39 |
+from derivepassphrase._internals import ( |
|
| 40 |
+ cli_helpers, |
|
| 41 |
+ cli_machinery, |
|
| 42 |
+ cli_messages, |
|
| 43 |
+) |
|
| 40 | 44 |
from derivepassphrase.ssh_agent import socketprovider |
| 41 | 45 |
|
| 42 | 46 |
__all__ = () |
| ... | ... |
@@ -216,6 +220,33 @@ class Parametrize(types.SimpleNamespace): |
| 216 | 220 |
), |
| 217 | 221 |
], |
| 218 | 222 |
) |
| 223 |
+ MISSING_AGENT_SUPPORT = pytest.mark.parametrize( |
|
| 224 |
+ ["provider", "sys_action", "exception", "message"], |
|
| 225 |
+ [ |
|
| 226 |
+ pytest.param( |
|
| 227 |
+ _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX, |
|
| 228 |
+ tests.data.SystemSupportAction.UNSET_AF_UNIX_AND_ENSURE_USE, |
|
| 229 |
+ socketprovider.UnixDomainSocketsNotAvailableError, |
|
| 230 |
+ str( |
|
| 231 |
+ cli_messages.TranslatedString( |
|
| 232 |
+ cli_messages.WarnMsgTemplate.NO_UNIX_DOMAIN_SOCKETS |
|
| 233 |
+ ) |
|
| 234 |
+ ), |
|
| 235 |
+ id="unix_domain_sockets", |
|
| 236 |
+ ), |
|
| 237 |
+ pytest.param( |
|
| 238 |
+ _types.BuiltinSSHAgentSocketProvider.WINDOWS_NAMED_PIPE, |
|
| 239 |
+ tests.data.SystemSupportAction.UNSET_WINDLL_AND_ENSURE_USE, |
|
| 240 |
+ socketprovider.WindowsNamedPipesNotAvailableError, |
|
| 241 |
+ str( |
|
| 242 |
+ cli_messages.TranslatedString( |
|
| 243 |
+ cli_messages.WarnMsgTemplate.NO_WINDOWS_NAMED_PIPES |
|
| 244 |
+ ) |
|
| 245 |
+ ), |
|
| 246 |
+ id="windows_named_pipes", |
|
| 247 |
+ ), |
|
| 248 |
+ ], |
|
| 249 |
+ ) |
|
| 219 | 250 |
|
| 220 | 251 |
|
| 221 | 252 |
# Monkeypatchings |
| ... | ... |
@@ -13,18 +13,14 @@ subsystems.) |
| 13 | 13 |
from __future__ import annotations |
| 14 | 14 |
|
| 15 | 15 |
import contextlib |
| 16 |
-import ctypes |
|
| 17 | 16 |
import json |
| 18 |
-import socket |
|
| 19 | 17 |
import textwrap |
| 20 |
-import types |
|
| 21 | 18 |
from typing import TYPE_CHECKING, ClassVar |
| 22 | 19 |
|
| 23 | 20 |
import pytest |
| 24 | 21 |
|
| 25 |
-from derivepassphrase import _types, cli, ssh_agent |
|
| 26 |
-from derivepassphrase._internals import cli_helpers, cli_messages |
|
| 27 |
-from derivepassphrase.ssh_agent import socketprovider |
|
| 22 |
+from derivepassphrase import _types, cli |
|
| 23 |
+from derivepassphrase._internals import cli_helpers |
|
| 28 | 24 |
from tests import data, machinery |
| 29 | 25 |
from tests.machinery import pytest as pytest_machinery |
| 30 | 26 |
|
| ... | ... |
@@ -36,7 +32,7 @@ DUMMY_PASSPHRASE = data.DUMMY_PASSPHRASE |
| 36 | 32 |
DUMMY_CONFIG_SETTINGS = data.DUMMY_CONFIG_SETTINGS |
| 37 | 33 |
|
| 38 | 34 |
|
| 39 |
-class Parametrize(types.SimpleNamespace): |
|
| 35 |
+class Parametrize(pytest_machinery.Parametrize): |
|
| 40 | 36 |
"""Common test parametrizations.""" |
| 41 | 37 |
|
| 42 | 38 |
UNICODE_NORMALIZATION_ERROR_INPUTS = pytest.mark.parametrize( |
| ... | ... |
@@ -218,31 +214,6 @@ class Parametrize(types.SimpleNamespace): |
| 218 | 214 |
), |
| 219 | 215 |
], |
| 220 | 216 |
) |
| 221 |
- MISSING_AGENT_SUPPORT = pytest.mark.parametrize( |
|
| 222 |
- ["provider", "exception", "message"], |
|
| 223 |
- [ |
|
| 224 |
- pytest.param( |
|
| 225 |
- _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX, |
|
| 226 |
- socketprovider.UnixDomainSocketsNotAvailableError, |
|
| 227 |
- str( |
|
| 228 |
- cli_messages.TranslatedString( |
|
| 229 |
- cli_messages.WarnMsgTemplate.NO_UNIX_DOMAIN_SOCKETS |
|
| 230 |
- ) |
|
| 231 |
- ), |
|
| 232 |
- id="unix_domain_sockets", |
|
| 233 |
- ), |
|
| 234 |
- pytest.param( |
|
| 235 |
- _types.BuiltinSSHAgentSocketProvider.WINDOWS_NAMED_PIPE, |
|
| 236 |
- socketprovider.WindowsNamedPipesNotAvailableError, |
|
| 237 |
- str( |
|
| 238 |
- cli_messages.TranslatedString( |
|
| 239 |
- cli_messages.WarnMsgTemplate.NO_WINDOWS_NAMED_PIPES |
|
| 240 |
- ) |
|
| 241 |
- ), |
|
| 242 |
- id="windows_named_pipes", |
|
| 243 |
- ), |
|
| 244 |
- ], |
|
| 245 |
- ) |
|
| 246 | 217 |
|
| 247 | 218 |
|
| 248 | 219 |
class TestPassphraseUnicodeNormalization: |
| ... | ... |
@@ -389,39 +360,17 @@ class TestUserConfigurationFileOther: |
| 389 | 360 |
class TestSSHAgentAvailability: |
| 390 | 361 |
"""Tests concerning the availability of the SSH agent.""" |
| 391 | 362 |
|
| 392 |
- # TODO(the-13th-letter): Decouple tests from exact knowledge of how |
|
| 393 |
- # to unsupport a certain socket provider. Coordinate with |
|
| 394 |
- # tests.test_derivepassphrase_ssh_agent.test_000_basic.TestConstructorFailures. |
|
| 395 |
- def _unsupport_provider_and_force_use( |
|
| 396 |
- self, |
|
| 397 |
- provider: _types.BuiltinSSHAgentSocketProvider, |
|
| 398 |
- monkeypatch: pytest.MonkeyPatch, |
|
| 399 |
- ) -> None: |
|
| 400 |
- """Remove support for the named socket provider.""" |
|
| 401 |
- if ( |
|
| 402 |
- provider |
|
| 403 |
- == _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX |
|
| 404 |
- ): |
|
| 405 |
- monkeypatch.delattr(socket, "AF_UNIX", raising=False) |
|
| 406 |
- elif ( |
|
| 407 |
- provider == _types.BuiltinSSHAgentSocketProvider.WINDOWS_NAMED_PIPE |
|
| 408 |
- ): |
|
| 409 |
- monkeypatch.delattr(ctypes, "WinDLL", raising=False) |
|
| 410 |
- else: |
|
| 411 |
- pytest.fail(f"Don't know how to remove support for {provider!r}.")
|
|
| 412 |
- monkeypatch.setattr( |
|
| 413 |
- ssh_agent.SSHAgentClient, "SOCKET_PROVIDERS", [provider] |
|
| 414 |
- ) |
|
| 415 |
- |
|
| 416 | 363 |
@Parametrize.MISSING_AGENT_SUPPORT |
| 417 | 364 |
def test_missing_agent_support( |
| 418 | 365 |
self, |
| 419 | 366 |
caplog: pytest.LogCaptureFixture, |
| 420 | 367 |
provider: _types.BuiltinSSHAgentSocketProvider, |
| 368 |
+ sys_action: data.SystemSupportAction, |
|
| 421 | 369 |
exception: type[NotImplementedError], |
| 422 | 370 |
message: str, |
| 423 | 371 |
) -> None: |
| 424 | 372 |
"""Querying the SSH agent without support fails.""" |
| 373 |
+ del provider |
|
| 425 | 374 |
del exception |
| 426 | 375 |
runner = machinery.CliRunner(mix_stderr=False) |
| 427 | 376 |
# TODO(the-13th-letter): Rewrite using parenthesized |
| ... | ... |
@@ -439,7 +388,7 @@ class TestSSHAgentAvailability: |
| 439 | 388 |
monkeypatch.setenv( |
| 440 | 389 |
"SSH_AUTH_SOCK", "the value doesn't even matter" |
| 441 | 390 |
) |
| 442 |
- self._unsupport_provider_and_force_use(provider, monkeypatch) |
|
| 391 |
+ sys_action(monkeypatch) |
|
| 443 | 392 |
result = runner.invoke( |
| 444 | 393 |
cli.derivepassphrase_vault, |
| 445 | 394 |
["--key", "--config"], |
| ... | ... |
@@ -8,12 +8,9 @@ from __future__ import annotations |
| 8 | 8 |
|
| 9 | 9 |
import base64 |
| 10 | 10 |
import contextlib |
| 11 |
-import ctypes |
|
| 12 | 11 |
import importlib.metadata |
| 13 | 12 |
import re |
| 14 |
-import socket |
|
| 15 | 13 |
import sys |
| 16 |
-import types |
|
| 17 | 14 |
from typing import TYPE_CHECKING, Final, cast |
| 18 | 15 |
|
| 19 | 16 |
import click |
| ... | ... |
@@ -23,7 +20,7 @@ from hypothesis import strategies |
| 23 | 20 |
from typing_extensions import TypeAlias |
| 24 | 21 |
|
| 25 | 22 |
from derivepassphrase import _types, ssh_agent, vault |
| 26 |
-from derivepassphrase._internals import cli_helpers, cli_messages |
|
| 23 |
+from derivepassphrase._internals import cli_helpers |
|
| 27 | 24 |
from derivepassphrase.ssh_agent import socketprovider |
| 28 | 25 |
from tests import data, machinery |
| 29 | 26 |
from tests.data import callables |
| ... | ... |
@@ -57,7 +54,7 @@ def use_stub_agent() -> Generator[None, None, None]: |
| 57 | 54 |
yield |
| 58 | 55 |
|
| 59 | 56 |
|
| 60 |
-class Parametrize(types.SimpleNamespace): |
|
| 57 |
+class Parametrize(pytest_machinery.Parametrize): |
|
| 61 | 58 |
BAD_ENTRY_POINTS = pytest.mark.parametrize( |
| 62 | 59 |
"additional_entry_points", |
| 63 | 60 |
[ |
| ... | ... |
@@ -338,31 +335,6 @@ class Parametrize(types.SimpleNamespace): |
| 338 | 335 |
), |
| 339 | 336 |
], |
| 340 | 337 |
) |
| 341 |
- MISSING_AGENT_SUPPORT = pytest.mark.parametrize( |
|
| 342 |
- ["provider", "exception", "message"], |
|
| 343 |
- [ |
|
| 344 |
- pytest.param( |
|
| 345 |
- _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX, |
|
| 346 |
- socketprovider.UnixDomainSocketsNotAvailableError, |
|
| 347 |
- str( |
|
| 348 |
- cli_messages.TranslatedString( |
|
| 349 |
- cli_messages.WarnMsgTemplate.NO_UNIX_DOMAIN_SOCKETS |
|
| 350 |
- ) |
|
| 351 |
- ), |
|
| 352 |
- id="unix_domain_sockets", |
|
| 353 |
- ), |
|
| 354 |
- pytest.param( |
|
| 355 |
- _types.BuiltinSSHAgentSocketProvider.WINDOWS_NAMED_PIPE, |
|
| 356 |
- socketprovider.WindowsNamedPipesNotAvailableError, |
|
| 357 |
- str( |
|
| 358 |
- cli_messages.TranslatedString( |
|
| 359 |
- cli_messages.WarnMsgTemplate.NO_WINDOWS_NAMED_PIPES |
|
| 360 |
- ) |
|
| 361 |
- ), |
|
| 362 |
- id="windows_named_pipes", |
|
| 363 |
- ), |
|
| 364 |
- ], |
|
| 365 |
- ) |
|
| 366 | 338 |
PUBLIC_KEY_DATA = pytest.mark.parametrize( |
| 367 | 339 |
"public_key_struct", |
| 368 | 340 |
list(data.SUPPORTED_KEYS.values()), |
| ... | ... |
@@ -1156,30 +1128,6 @@ class TestSuitableKeys: |
| 1156 | 1128 |
class TestConstructorFailures: |
| 1157 | 1129 |
"""Test actually talking to the SSH agent: constructor failures.""" |
| 1158 | 1130 |
|
| 1159 |
- # TODO(the-13th-letter): Decouple tests from exact knowledge of how |
|
| 1160 |
- # to unsupport a certain socket provider. Coordinate with |
|
| 1161 |
- # tests.test_derivepassphrase_cli.test_000_basic.TestSSHAgentAvailability. |
|
| 1162 |
- def _unsupport_provider_and_force_use( |
|
| 1163 |
- self, |
|
| 1164 |
- provider: _types.BuiltinSSHAgentSocketProvider, |
|
| 1165 |
- monkeypatch: pytest.MonkeyPatch, |
|
| 1166 |
- ) -> None: |
|
| 1167 |
- """Remove support for the named socket provider.""" |
|
| 1168 |
- if ( |
|
| 1169 |
- provider |
|
| 1170 |
- == _types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX |
|
| 1171 |
- ): |
|
| 1172 |
- monkeypatch.delattr(socket, "AF_UNIX", raising=False) |
|
| 1173 |
- elif ( |
|
| 1174 |
- provider == _types.BuiltinSSHAgentSocketProvider.WINDOWS_NAMED_PIPE |
|
| 1175 |
- ): |
|
| 1176 |
- monkeypatch.delattr(ctypes, "WinDLL", raising=False) |
|
| 1177 |
- else: |
|
| 1178 |
- pytest.fail(f"Don't know how to remove support for {provider!r}.")
|
|
| 1179 |
- monkeypatch.setattr( |
|
| 1180 |
- ssh_agent.SSHAgentClient, "SOCKET_PROVIDERS", [provider] |
|
| 1181 |
- ) |
|
| 1182 |
- |
|
| 1183 | 1131 |
def test_constructor_bad_running_agent( |
| 1184 | 1132 |
self, |
| 1185 | 1133 |
running_ssh_agent: data.RunningSSHAgentInfo, |
| ... | ... |
@@ -1199,6 +1147,7 @@ class TestConstructorFailures: |
| 1199 | 1147 |
def test_constructor_no_support( |
| 1200 | 1148 |
self, |
| 1201 | 1149 |
provider: _types.BuiltinSSHAgentSocketProvider, |
| 1150 |
+ sys_action: data.SystemSupportAction, |
|
| 1202 | 1151 |
exception: type[NotImplementedError], |
| 1203 | 1152 |
message: str, |
| 1204 | 1153 |
) -> None: |
| ... | ... |
@@ -1209,7 +1158,7 @@ class TestConstructorFailures: |
| 1209 | 1158 |
monkeypatch.setenv( |
| 1210 | 1159 |
"SSH_AUTH_SOCK", "the value doesn't even matter" |
| 1211 | 1160 |
) |
| 1212 |
- self._unsupport_provider_and_force_use(provider, monkeypatch) |
|
| 1161 |
+ sys_action(monkeypatch) |
|
| 1213 | 1162 |
with pytest.raises(exception): |
| 1214 | 1163 |
ssh_agent.SSHAgentClient(socket=provider) |
| 1215 | 1164 |
|
| 1216 | 1165 |