mirror of
https://ghfast.top/https://github.com/aeroxw/easy-tdx.git
synced 2026-09-12 19:14:16 +08:00
ping_host 仅 except OSError,但握手期 _recv_exact_sock 抛的 TdxConnectionError 继承自 TdxError(Exception) 而非 OSError,逃出捕获后经 ping_all 的 fut.result() 重新抛出,导致非交易时间服务器 accept 后立即 FIN 时整个 easy-tdx ping 崩溃。 - ping_host: except (OSError, TdxConnectionError),对齐 docstring 返回 None - ping_all: fut.result() 加 try/except 防御层,单 host 失败只跳过不崩 - 新增 2 例回归测试
89 lines
2.9 KiB
Python
89 lines
2.9 KiB
Python
"""同步 transport 回归测试。"""
|
|
|
|
from unittest.mock import patch
|
|
|
|
from easy_tdx.exceptions import TdxConnectionError
|
|
from easy_tdx.transport.sync import TdxConnection, ping_all, ping_host
|
|
|
|
|
|
class _FakeSocket:
|
|
def __init__(self) -> None:
|
|
self.timeout: float | None = None
|
|
self.connected_to: tuple[str, int] | None = None
|
|
self.closed = False
|
|
|
|
def settimeout(self, timeout: float) -> None:
|
|
self.timeout = timeout
|
|
|
|
def connect(self, address: tuple[str, int]) -> None:
|
|
self.connected_to = address
|
|
|
|
def sendall(self, data: bytes) -> None:
|
|
pass
|
|
|
|
def close(self) -> None:
|
|
self.closed = True
|
|
|
|
|
|
def test_sync_connection_closes_socket_when_setup_fails() -> None:
|
|
sock = _FakeSocket()
|
|
conn = TdxConnection("127.0.0.1", port=7709, timeout=0.2)
|
|
|
|
with (
|
|
patch("easy_tdx.transport.sync.socket.socket", return_value=sock),
|
|
patch.object(
|
|
TdxConnection,
|
|
"_send_setup",
|
|
side_effect=TdxConnectionError("setup failed"),
|
|
),
|
|
):
|
|
try:
|
|
conn.connect()
|
|
except TdxConnectionError as exc:
|
|
assert "setup failed" in str(exc)
|
|
else: # pragma: no cover - 防御性断言
|
|
raise AssertionError("expected setup failure")
|
|
|
|
assert sock.timeout == 0.2
|
|
assert sock.connected_to == ("127.0.0.1", 7709)
|
|
assert sock.closed is True
|
|
assert conn._sock is None
|
|
|
|
|
|
def test_ping_host_returns_none_when_server_closes_during_handshake() -> None:
|
|
"""握手期服务器关闭连接(_recv_exact_sock 抛 TdxConnectionError)应返回 None。
|
|
|
|
回归:ping_host 旧版仅 except OSError,未捕获 TdxConnectionError(继承自
|
|
TdxError(Exception) 而非 OSError),导致单个服务器握手失败就让整个
|
|
ping_all / `easy-tdx ping` 命令崩溃。非交易时间服务器 accept 后立即 FIN
|
|
时必现。
|
|
"""
|
|
sock = _FakeSocket()
|
|
with (
|
|
patch("easy_tdx.transport.sync.socket.socket", return_value=sock),
|
|
patch(
|
|
"easy_tdx.transport.sync._recv_exact_sock",
|
|
side_effect=TdxConnectionError("连接被服务器关闭"),
|
|
),
|
|
):
|
|
result = ping_host("192.0.2.1", port=7709, timeout=0.2)
|
|
|
|
assert result is None
|
|
assert sock.closed is True
|
|
|
|
|
|
def test_ping_all_skips_handshake_failure_without_crash() -> None:
|
|
"""ping_all 中任一服务器握手失败(TdxConnectionError)应被跳过,不崩溃。"""
|
|
|
|
def fake_ping(host: str, port: int, timeout: float) -> float | None:
|
|
if host == "bad":
|
|
raise TdxConnectionError("连接被服务器关闭")
|
|
return 0.05
|
|
|
|
with patch("easy_tdx.transport.sync.ping_host", side_effect=fake_ping):
|
|
results = ping_all(hosts=["good", "bad"], port=7709, timeout=0.2)
|
|
|
|
hosts_ok = [h for h, _ in results]
|
|
assert "good" in hosts_ok
|
|
assert "bad" not in hosts_ok
|