bulid 63
This commit is contained in:
132
tests/test_multi_agent_routing.py
Normal file
132
tests/test_multi_agent_routing.py
Normal file
@@ -0,0 +1,132 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
from hockey_data.agent_bridge import VmixAgentHub
|
||||
from hockey_data.auth_bridge import HockeyUser
|
||||
from hockey_data.models import OperatorSession
|
||||
from tests.support import LocalTestDatabase
|
||||
|
||||
|
||||
class FakeWebSocket:
|
||||
def __init__(self) -> None:
|
||||
self.client = SimpleNamespace(host="127.0.0.1")
|
||||
self.sent: list[dict] = []
|
||||
self.closed = False
|
||||
|
||||
async def send_json(self, payload: dict) -> None:
|
||||
self.sent.append(payload)
|
||||
|
||||
async def close(self, **_kwargs) -> None:
|
||||
self.closed = True
|
||||
|
||||
|
||||
async def _ack_latest(hub: VmixAgentHub, device_id: str, ws: FakeWebSocket) -> dict:
|
||||
command = None
|
||||
for _ in range(100):
|
||||
await asyncio.sleep(0)
|
||||
commands = [item for item in ws.sent if item.get("type") == "vmix.command"]
|
||||
if commands:
|
||||
command = commands[-1]
|
||||
break
|
||||
assert command is not None
|
||||
await hub.receive_command_ack(
|
||||
device_id,
|
||||
{"type": "command.ack", "request_id": command["request_id"], "ok": True},
|
||||
)
|
||||
return command
|
||||
|
||||
|
||||
def test_multiple_agents_stay_enabled_and_runtime_routes_to_explicit_browser_agent(tmp_path: Path) -> None:
|
||||
database = LocalTestDatabase(tmp_path / "multi-agent.sqlite3")
|
||||
database.create_all()
|
||||
hub = VmixAgentHub(database) # type: ignore[arg-type]
|
||||
user = HockeyUser(id="multi-1", login="multi", display_name="Multi")
|
||||
ws_test = FakeWebSocket()
|
||||
ws_live = FakeWebSocket()
|
||||
|
||||
async def scenario() -> None:
|
||||
for device_id, secret, ws in (
|
||||
("GFX-MULTI-TEST", "t" * 40, ws_test),
|
||||
("GFX-MULTI-LIVE", "l" * 40, ws_live),
|
||||
):
|
||||
await hub.register(
|
||||
ws, # type: ignore[arg-type]
|
||||
{
|
||||
"device_id": device_id,
|
||||
"device_secret": secret,
|
||||
"device_name": device_id,
|
||||
"hostname": device_id,
|
||||
"agent_version": "1.4.0",
|
||||
"vmix": {"connected": True, "url": "http://127.0.0.1:8088/api/"},
|
||||
},
|
||||
)
|
||||
await hub.pair_device(device_id, user)
|
||||
|
||||
devices = await hub.list_for_user(user)
|
||||
assert set(devices["active_device_ids"]) == {"GFX-MULTI-TEST", "GFX-MULTI-LIVE"}
|
||||
|
||||
with database.session() as session:
|
||||
session.add(
|
||||
OperatorSession(
|
||||
session_token="multi-session",
|
||||
wfl_user_id=user.id,
|
||||
login_snapshot=user.login,
|
||||
tournament_external_id="1437",
|
||||
game_external_id="902918",
|
||||
status="active",
|
||||
)
|
||||
)
|
||||
|
||||
assert await hub.assign_match(
|
||||
wfl_user_id=user.id,
|
||||
tournament_external_id="1437",
|
||||
game_external_id="902918",
|
||||
device_id="GFX-MULTI-TEST",
|
||||
operator_session_token="multi-session",
|
||||
)
|
||||
assert await hub.assign_match(
|
||||
wfl_user_id=user.id,
|
||||
tournament_external_id="1437",
|
||||
game_external_id="902918",
|
||||
device_id="GFX-MULTI-LIVE",
|
||||
operator_session_token="multi-session",
|
||||
)
|
||||
|
||||
# Ignore pairing / assignment traffic and count only runtime vmix.command messages.
|
||||
before_test = len([item for item in ws_test.sent if item.get("type") == "vmix.command"])
|
||||
before_live = len([item for item in ws_live.sent if item.get("type") == "vmix.command"])
|
||||
|
||||
task_test = asyncio.create_task(
|
||||
hub.run_vmix_sequence_for_user(
|
||||
user,
|
||||
[{"Function": "OverlayInput1In", "Input": "score-key"}],
|
||||
device_id="GFX-MULTI-TEST",
|
||||
session_token="multi-session",
|
||||
)
|
||||
)
|
||||
command_test = await _ack_latest(hub, "GFX-MULTI-TEST", ws_test)
|
||||
result_test = await task_test
|
||||
assert result_test["device_id"] == "GFX-MULTI-TEST"
|
||||
assert command_test["command"]["Function"] == "OverlayInput1In"
|
||||
assert len([item for item in ws_test.sent if item.get("type") == "vmix.command"]) == before_test + 1
|
||||
assert len([item for item in ws_live.sent if item.get("type") == "vmix.command"]) == before_live
|
||||
|
||||
task_live = asyncio.create_task(
|
||||
hub.run_vmix_sequence_for_user(
|
||||
user,
|
||||
[{"Function": "OverlayInput1Out", "Input": "score-key"}],
|
||||
device_id="GFX-MULTI-LIVE",
|
||||
session_token="multi-session",
|
||||
)
|
||||
)
|
||||
command_live = await _ack_latest(hub, "GFX-MULTI-LIVE", ws_live)
|
||||
result_live = await task_live
|
||||
assert result_live["device_id"] == "GFX-MULTI-LIVE"
|
||||
assert command_live["command"]["Function"] == "OverlayInput1Out"
|
||||
assert len([item for item in ws_live.sent if item.get("type") == "vmix.command"]) == before_live + 1
|
||||
assert len([item for item in ws_test.sent if item.get("type") == "vmix.command"]) == before_test + 1
|
||||
|
||||
asyncio.run(scenario())
|
||||
Reference in New Issue
Block a user