Files
Simone b2b31f4b6e
Lint / pssa (push) Successful in 35s
Lint / python (push) Successful in 42s
test: add coverage for monitor/vm/winrm to reach 90%% gate
Bring monitor.py 49->99%%, vm.py 79->98%%, winrm.py 76->100%%. Total project coverage 80.10%% -> 90.69%%, satisfying the 90%% gate set in commit 451a61c.
2026-05-14 23:14:08 +02:00

196 lines
6.6 KiB
Python

"""Tests for WinRmTransport (pypsrp client mocked)."""
from __future__ import annotations
import sys
import types
from typing import Any
import pytest
from ci_orchestrator.transport.errors import TransportCommandError, TransportConnectError
from ci_orchestrator.transport.winrm import WinRmTransport
class _FakeClient:
def __init__(self, *args: Any, **kwargs: Any) -> None:
self.args = args
self.kwargs = kwargs
self.copies: list[tuple[str, str]] = []
self.fetches: list[tuple[str, str]] = []
self.scripts: list[str] = []
self.next_result: tuple[str, str, int] = ("ok", "", 0)
self.wsman = types.SimpleNamespace(close=lambda: None)
def execute_ps(self, script: str) -> tuple[str, str, int]:
self.scripts.append(script)
return self.next_result
def copy(self, local: str, remote: str) -> None:
self.copies.append((local, remote))
def fetch(self, remote: str, local: str) -> None:
self.fetches.append((remote, local))
def _install_fake_pypsrp(monkeypatch: pytest.MonkeyPatch, client: _FakeClient) -> None:
module = types.ModuleType("pypsrp")
client_module = types.ModuleType("pypsrp.client")
client_module.Client = lambda *a, **kw: client # type: ignore[attr-defined]
monkeypatch.setitem(sys.modules, "pypsrp", module)
monkeypatch.setitem(sys.modules, "pypsrp.client", client_module)
def test_run_returns_result(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
fake.next_result = ("hello\n", "", 0)
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
result = t.run("Write-Output 'hello'")
assert result.ok
assert result.stdout == "hello\n"
assert fake.scripts == ["Write-Output 'hello'"]
def test_run_raises_on_failure(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
fake.next_result = ("", "boom", 7)
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
with pytest.raises(TransportCommandError) as exc:
t.run("bad")
assert exc.value.returncode == 7
def test_run_check_false_does_not_raise(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
fake.next_result = ("", "boom", 7)
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
result = t.run("bad", check=False)
assert not result.ok
def test_copy_and_fetch(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
t.copy("local.txt", "C:/remote.txt")
t.fetch("C:/remote.txt", "downloaded.txt")
assert fake.copies == [("local.txt", "C:/remote.txt")]
assert fake.fetches == [("C:/remote.txt", "downloaded.txt")]
def test_is_ready_handles_connect_failure(monkeypatch: pytest.MonkeyPatch) -> None:
# Make the local import inside _connect succeed but Client raise.
module = types.ModuleType("pypsrp")
client_module = types.ModuleType("pypsrp.client")
def _boom(*_a: object, **_kw: object) -> None:
raise OSError("connection refused")
client_module.Client = _boom # type: ignore[attr-defined]
monkeypatch.setitem(sys.modules, "pypsrp", module)
monkeypatch.setitem(sys.modules, "pypsrp.client", client_module)
t = WinRmTransport("10.0.0.1", "user", "pwd")
assert t.is_ready() is False
# Direct .run should raise.
with pytest.raises(TransportConnectError):
t.run("x")
def test_close_and_context_manager(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
closed: list[bool] = []
fake.wsman = types.SimpleNamespace(close=lambda: closed.append(True))
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
with t as ctx:
assert ctx is t
assert closed == [True]
# close() on already-closed transport is a no-op.
t.close()
def test_close_swallows_wsman_exception(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
def _raise() -> None:
raise RuntimeError("boom")
fake.wsman = types.SimpleNamespace(close=_raise)
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
t.run("x") # connect once
t.close() # must not raise
def test_run_normalises_list_stderr(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
fake.next_result = ("out", ["a", "b"], 0) # type: ignore[assignment]
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
result = t.run("x")
assert result.stderr == "a\nb"
def test_run_normalises_non_iterable_stderr(monkeypatch: pytest.MonkeyPatch) -> None:
class _Weird:
def __str__(self) -> str:
return "weird-stderr"
fake = _FakeClient()
fake.next_result = ("out", _Weird(), 0) # type: ignore[assignment]
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
result = t.run("x")
assert "weird-stderr" in result.stderr
def test_run_execute_ps_raises_wrapped(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
def _boom(_s: str) -> Any:
raise RuntimeError("ps boom")
fake.execute_ps = _boom # type: ignore[assignment]
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
with pytest.raises(TransportConnectError) as exc:
t.run("x")
assert "execute_ps failed" in str(exc.value)
def test_copy_wraps_exception(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
def _boom(_l: str, _r: str) -> None:
raise OSError("copy down")
fake.copy = _boom # type: ignore[assignment]
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
with pytest.raises(TransportConnectError) as exc:
t.copy("a", "b")
assert "copy failed" in str(exc.value)
def test_fetch_wraps_exception(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
def _boom(_r: str, _l: str) -> None:
raise OSError("fetch down")
fake.fetch = _boom # type: ignore[assignment]
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
with pytest.raises(TransportConnectError) as exc:
t.fetch("a", "b")
assert "fetch failed" in str(exc.value)
def test_is_ready_true_when_run_succeeds(monkeypatch: pytest.MonkeyPatch) -> None:
fake = _FakeClient()
_install_fake_pypsrp(monkeypatch, fake)
t = WinRmTransport("10.0.0.1", "user", "pwd")
assert t.is_ready() is True