Download tests/test_task_websocket_status_push.py from webhook/codex: direct link, hf CLI and curl.
- Browser
- Download file 6.47 kB
-
https://huggingface.co/spaces/webhook/codex/resolve/main/tests/test_task_websocket_status_push.py
- Command line
-
hf download hf://spaces/webhook/codex/tests/test_task_websocket_status_push.py
-
curl -L -o test_task_websocket_status_push.py https://huggingface.co/spaces/webhook/codex/resolve/main/tests/test_task_websocket_status_push.py
6.47 kB
| import asyncio | |
| import threading | |
| from fastapi import WebSocketDisconnect | |
| from src.web import task_manager as task_manager_module | |
| from src.web.routes import websocket as websocket_routes | |
| from src.web.task_manager import TaskManager | |
| class DummyWebSocket: | |
| def __init__(self): | |
| self.sent = [] | |
| self.accepted = False | |
| self._incoming: asyncio.Queue = asyncio.Queue() | |
| async def accept(self): | |
| self.accepted = True | |
| async def send_json(self, message): | |
| self.sent.append(message) | |
| async def receive_json(self): | |
| item = await self._incoming.get() | |
| if isinstance(item, Exception): | |
| raise item | |
| return item | |
| async def disconnect(self): | |
| await self._incoming.put(WebSocketDisconnect()) | |
| def _reset_task_manager_state(): | |
| task_manager_module._log_queues.clear() | |
| task_manager_module._log_locks.clear() | |
| task_manager_module._ws_connections.clear() | |
| task_manager_module._ws_sent_index.clear() | |
| task_manager_module._task_status.clear() | |
| task_manager_module._task_cancelled.clear() | |
| task_manager_module._batch_status.clear() | |
| task_manager_module._batch_logs.clear() | |
| task_manager_module._batch_locks.clear() | |
| def test_update_status_broadcasts_terminal_failed_with_error_when_loop_available(): | |
| async def scenario(): | |
| _reset_task_manager_state() | |
| manager = TaskManager() | |
| manager.set_loop(asyncio.get_running_loop()) | |
| ws = DummyWebSocket() | |
| manager.register_websocket("task-failed", ws) | |
| manager.update_status("task-failed", "failed") | |
| await asyncio.sleep(0.05) | |
| assert ws.sent, "expected websocket status push for failed status" | |
| failed_messages = [m for m in ws.sent if m.get("type") == "status" and m.get("status") == "failed"] | |
| assert failed_messages, "expected failed status message" | |
| assert failed_messages[-1].get("error"), "failed status must include error" | |
| assert manager.get_status("task-failed").get("error") | |
| asyncio.run(scenario()) | |
| def test_update_status_broadcasts_terminal_completed_payload_when_loop_available(): | |
| async def scenario(): | |
| _reset_task_manager_state() | |
| manager = TaskManager() | |
| manager.set_loop(asyncio.get_running_loop()) | |
| ws = DummyWebSocket() | |
| manager.register_websocket("task-completed", ws) | |
| manager.update_status("task-completed", "completed", email="done@example.com") | |
| await asyncio.sleep(0.05) | |
| completed_messages = [m for m in ws.sent if m.get("type") == "status" and m.get("status") == "completed"] | |
| assert completed_messages, "expected completed status message" | |
| assert completed_messages[-1].get("email") == "done@example.com" | |
| assert completed_messages[-1].get("updated_at") | |
| asyncio.run(scenario()) | |
| def test_task_websocket_sends_initial_status_snapshot(): | |
| async def scenario(): | |
| _reset_task_manager_state() | |
| manager = TaskManager() | |
| manager.update_status("task-initial", "running", message="booting") | |
| ws = DummyWebSocket() | |
| original = websocket_routes.task_manager | |
| websocket_routes.task_manager = manager | |
| try: | |
| task = asyncio.create_task(websocket_routes.task_websocket(ws, "task-initial")) | |
| await asyncio.sleep(0.01) | |
| await ws.disconnect() | |
| await task | |
| finally: | |
| websocket_routes.task_manager = original | |
| assert ws.accepted | |
| status_messages = [m for m in ws.sent if m.get("type") == "status"] | |
| assert status_messages, "expected initial status snapshot on connect" | |
| assert status_messages[0].get("status") == "running" | |
| assert status_messages[0].get("message") == "booting" | |
| asyncio.run(scenario()) | |
| def test_task_websocket_receives_terminal_update_after_connect(): | |
| async def scenario(): | |
| _reset_task_manager_state() | |
| manager = TaskManager() | |
| manager.set_loop(asyncio.get_running_loop()) | |
| ws = DummyWebSocket() | |
| original = websocket_routes.task_manager | |
| websocket_routes.task_manager = manager | |
| try: | |
| task = asyncio.create_task(websocket_routes.task_websocket(ws, "task-live")) | |
| await asyncio.sleep(0.01) | |
| manager.update_status("task-live", "failed", error="boom") | |
| await asyncio.sleep(0.05) | |
| await ws.disconnect() | |
| await task | |
| finally: | |
| websocket_routes.task_manager = original | |
| terminal_messages = [m for m in ws.sent if m.get("type") == "status" and m.get("status") == "failed"] | |
| assert terminal_messages, "expected live failed status over websocket" | |
| assert terminal_messages[-1].get("error") == "boom" | |
| asyncio.run(scenario()) | |
| def test_update_status_broadcasts_from_worker_thread_when_loop_available(): | |
| async def scenario(): | |
| _reset_task_manager_state() | |
| manager = TaskManager() | |
| manager.set_loop(asyncio.get_running_loop()) | |
| ws = DummyWebSocket() | |
| manager.register_websocket("task-threaded", ws) | |
| worker = threading.Thread( | |
| target=lambda: manager.update_status( | |
| "task-threaded", | |
| "completed", | |
| email="thread@example.com" | |
| ) | |
| ) | |
| worker.start() | |
| worker.join() | |
| await asyncio.sleep(0.05) | |
| completed_messages = [ | |
| m for m in ws.sent | |
| if m.get("type") == "status" and m.get("status") == "completed" | |
| ] | |
| assert completed_messages, "expected threaded status push over websocket" | |
| assert completed_messages[-1].get("email") == "thread@example.com" | |
| assert completed_messages[-1].get("message") | |
| asyncio.run(scenario()) | |
| def test_update_status_terminal_defaults_include_useful_fields(): | |
| _reset_task_manager_state() | |
| manager = TaskManager() | |
| manager.update_status("task-term", "completed") | |
| completed = manager.get_status("task-term") | |
| assert completed["message"] | |
| manager.update_status("task-term", "failed") | |
| failed = manager.get_status("task-term") | |
| assert failed["message"] | |
| assert failed["error"] | |
| manager.update_status("task-term", "cancelled") | |
| cancelled = manager.get_status("task-term") | |
| assert cancelled["message"] | |
| manager.update_status("task-term", "cancelling") | |
| cancelling = manager.get_status("task-term") | |
| assert cancelling["message"] | |