/
githubmirror
/
salt
Обзор
Документация
Войти
/
githubmirror
/
salt
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
tests/pytests/unit/netapi/test_netapi_client_runner.py
136 строк
4 KB
Daniel A. Wozniak
Make FakeRunner test doubles context managers
19 июн 2026, 01:47
19 июн 2026, 01:47
28d34f9
Код
Авторство
О чём код?
""" Regression tests for NetapiClient.runner timeout coercion (issue #68653). The salt-api HTTP form encodes all values as strings, so a request like ``-d timeout=600`` arrives at ``NetapiClient.runner`` as ``timeout="600"``. The downstream ``salt.utils.event._get_event`` does ``timeout_at = start + wait`` which raises ``TypeError`` when ``wait`` is a string. ``runner`` now coerces the value to ``float`` at the boundary so HTTP-form callers can specify a timeout without crashing the runner. """ import pytest import salt.netapi from tests.support.mock import patch @pytest.fixture def netapi_client(master_opts): return salt.netapi.NetapiClient(master_opts) def test_runner_coerces_string_timeout_to_float(netapi_client): """ NetapiClient.runner must not raise TypeError when given a string timeout from the HTTP form, and must forward a numeric value to RunnerClient.cmd_sync (issue #68653). """ captured = {} class FakeRunner: def __init__(self, opts): self.opts = opts def __enter__(self): return self def __exit__(self, *exc): return False def cmd_sync(self, low, timeout=None, full_return=False): captured["timeout"] = timeout captured["low"] = low captured["full_return"] = full_return return {"return": "ok"} with patch("salt.runner.RunnerClient", FakeRunner): ret = netapi_client.runner("test.arg", timeout="600") assert ret == {"return": "ok"} assert captured["timeout"] == 600.0 assert isinstance(captured["timeout"], float) assert captured["low"]["fun"] == "test.arg" def test_runner_coerces_fractional_string_timeout(netapi_client): """ Fractional string timeouts must be preserved as float (the v1 of the fix used ``int()`` which truncated ``"0.5"`` to ``0``; v2 corrected to ``float()``). """ captured = {} class FakeRunner: def __init__(self, opts): pass def __enter__(self): return self def __exit__(self, *exc): return False def cmd_sync(self, low, timeout=None, full_return=False): captured["timeout"] = timeout return {"return": "ok"} with patch("salt.runner.RunnerClient", FakeRunner): netapi_client.runner("test.arg", timeout="0.5") assert captured["timeout"] == 0.5 def test_runner_preserves_none_timeout(netapi_client): """ ``timeout=None`` must pass through unchanged so the downstream default (``opts["rest_timeout"]``) still applies. """ captured = {} class FakeRunner: def __init__(self, opts): pass def __enter__(self): return self def __exit__(self, *exc): return False def cmd_sync(self, low, timeout=None, full_return=False): captured["timeout"] = timeout return {"return": "ok"} with patch("salt.runner.RunnerClient", FakeRunner): netapi_client.runner("test.arg") assert captured["timeout"] is None def test_runner_passes_numeric_timeout_unchanged_value(netapi_client): """ A numeric (int/float) timeout still ends up as a float with the same value — the coercion is idempotent. """ captured = {} class FakeRunner: def __init__(self, opts): pass def __enter__(self): return self def __exit__(self, *exc): return False def cmd_sync(self, low, timeout=None, full_return=False): captured["timeout"] = timeout return {"return": "ok"} with patch("salt.runner.RunnerClient", FakeRunner): netapi_client.runner("test.arg", timeout=42) assert captured["timeout"] == 42.0 assert isinstance(captured["timeout"], float)