Files
kernalix7--winpodx/tests/test_pod_recovery.py
T
wehub-resource-sync 3e779be6f3
CI / lint (push) Failing after 13m4s
CI / test (3.11, ubuntu-latest) (push) Failing after 2m4s
CI / test (3.13, ubuntu-latest) (push) Successful in 13m30s
CI / test (3.14, ubuntu-latest) (push) Successful in 17m21s
CI / test (3.12, ubuntu-latest) (push) Successful in 17m55s
CI / discover-apps-ps (push) Successful in 1m56s
CI / test (3.9, ubuntu-latest) (push) Successful in 13m17s
CI / test (3.10, ubuntu-latest) (push) Successful in 26m21s
CI / audit (push) Successful in 13m38s
Deploy site / deploy (push) Has been cancelled
CI / test (3.14, ubuntu-24.04-arm) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:37 +08:00

110 lines
3.5 KiB
Python

# SPDX-License-Identifier: MIT
"""Tests for `core.pod.recovery.try_recover_rdp` — agent-driven RDP recovery.
Covers the three terminal RecoveryAction outcomes plus the "RDP comes back
mid-window" success path. The agent transport + RDP probe + time.sleep are
mocked so the test runs in milliseconds even though the production flow
polls for up to 30 s.
"""
from __future__ import annotations
from unittest.mock import MagicMock, patch
from winpodx.core.config import Config
from winpodx.core.pod.recovery import (
RecoveryAction,
try_recover_rdp,
)
def _agent_health(available: bool, detail: str = "") -> MagicMock:
h = MagicMock()
h.available = available
h.detail = detail
return h
def _exec_result(rc: int = 0, stdout: str = "", stderr: str = "") -> MagicMock:
r = MagicMock()
r.rc = rc
r.stdout = stdout
r.stderr = stderr
return r
def test_recovery_succeeds_when_rdp_comes_back():
cfg = Config()
fake_transport = MagicMock()
fake_transport.health.return_value = _agent_health(True)
fake_transport.exec.return_value = _exec_result(rc=0)
with (
patch("winpodx.core.transport.agent.AgentTransport", return_value=fake_transport),
patch("winpodx.core.pod.recovery.check_rdp_port", return_value=True),
patch("winpodx.core.pod.recovery.time.sleep"),
):
result = try_recover_rdp(cfg)
assert result.success is True
assert result.action == RecoveryAction.RESTARTED_TERMSERVICE
fake_transport.exec.assert_called_once()
args, kwargs = fake_transport.exec.call_args
assert "TermService" in args[0]
def test_recovery_fails_with_agent_unreachable_when_health_down():
cfg = Config()
fake_transport = MagicMock()
fake_transport.health.return_value = _agent_health(False, detail="connection refused")
with patch("winpodx.core.transport.agent.AgentTransport", return_value=fake_transport):
result = try_recover_rdp(cfg)
assert result.success is False
assert result.action == RecoveryAction.AGENT_UNREACHABLE
assert "connection refused" in result.detail
fake_transport.exec.assert_not_called()
def test_recovery_fails_with_rdp_still_down_when_probe_never_clears():
cfg = Config()
fake_transport = MagicMock()
fake_transport.health.return_value = _agent_health(True)
fake_transport.exec.return_value = _exec_result(rc=0)
with (
patch("winpodx.core.transport.agent.AgentTransport", return_value=fake_transport),
patch("winpodx.core.pod.recovery.check_rdp_port", return_value=False),
patch("winpodx.core.pod.recovery.time.sleep"),
patch(
"winpodx.core.pod.recovery.time.monotonic",
side_effect=[0.0, 5.0, 15.0, 31.0],
),
):
result = try_recover_rdp(cfg)
assert result.success is False
assert result.action == RecoveryAction.RDP_STILL_DOWN
assert "still unreachable" in result.detail
def test_recovery_propagates_agent_exec_failure_as_agent_unreachable():
from winpodx.core.transport.base import TransportTimeoutError
cfg = Config()
fake_transport = MagicMock()
fake_transport.health.return_value = _agent_health(True)
fake_transport.exec.side_effect = TransportTimeoutError("exec hit 20s timeout")
with patch("winpodx.core.transport.agent.AgentTransport", return_value=fake_transport):
result = try_recover_rdp(cfg)
assert result.success is False
assert result.action == RecoveryAction.AGENT_UNREACHABLE
assert "20s timeout" in result.detail