Files
hermes-agent/tests/hermes_cli/test_serve_windows_loop_factory.py

65 lines
1.8 KiB
Python

"""Windows serve must run uvicorn on a SelectorEventLoop.
Regression for #120164. uvicorn 0.41's ``asyncio_loop_factory`` returns
ProactorEventLoop on win32. Driving uvicorn's socket stack on the proactor loop
binds-but-never-accepts: READY prints, then ``Accept failed on a socket`` +
WinError 10014, exit 1, desktop ECONNREFUSED (regression of #50641, whose fix
trusted ``config.get_loop_factory()`` back when that still meant selector).
"""
import asyncio
import pytest
pytestmark = pytest.mark.platforms("windows")
class _ProactorConfig:
def get_loop_factory(self):
return asyncio.ProactorEventLoop
class _SelectorConfig:
def get_loop_factory(self):
return asyncio.SelectorEventLoop
def _capture_runner(monkeypatch):
captured = {}
def _fake_runner(main, **kwargs):
captured.update(kwargs)
main.close()
return None
monkeypatch.setattr("uvicorn._compat.asyncio_run", _fake_runner)
return captured
async def _noop():
return None
def test_proactor_factory_is_overridden_to_selector(monkeypatch):
from hermes_cli import web_server
captured = _capture_runner(monkeypatch)
web_server._run_serve(_noop, _ProactorConfig(), "127.0.0.1", 0)
factory = captured.get("loop_factory")
assert factory is not None, "expected an explicit loop_factory on win32"
loop = factory()
try:
assert isinstance(loop, asyncio.SelectorEventLoop), (
f"serve must not run on {type(loop).__name__} (#120164)"
)
finally:
loop.close()
def test_selector_factory_passes_through(monkeypatch):
from hermes_cli import web_server
captured = _capture_runner(monkeypatch)
web_server._run_serve(_noop, _SelectorConfig(), "127.0.0.1", 0)
assert captured.get("loop_factory") is asyncio.SelectorEventLoop