fix: harden scheduler and login desktop runtime

This commit is contained in:
Rixuan Shao
2026-07-14 15:23:29 +08:00
parent bdadd363df
commit 16afdcef07
7 changed files with 116 additions and 30 deletions
@@ -125,6 +125,11 @@ class DeploymentContractTests(unittest.TestCase):
self.assertIn('"/creator-micro/" in page.url', server)
self.assertIn('"qr_ready": qr_ready', server)
def test_login_desktop_uses_fastapi_lifespan(self):
server = (SOURCE_ROOT / "login_desktop_server.py").read_text(encoding="utf-8")
self.assertIn("lifespan=lifespan", server)
self.assertNotIn("@app.on_event", server)
def test_login_desktop_exposes_cropped_qr_endpoint(self):
server = (SOURCE_ROOT / "login_desktop_server.py").read_text(encoding="utf-8")
self.assertIn('@app.get("/qr")', server)
+25
View File
@@ -1,3 +1,4 @@
import asyncio
import os
import unittest
from datetime import datetime, timezone
@@ -126,6 +127,30 @@ class SendStateTests(unittest.TestCase):
self.assertEqual(["confirmed", "pending"], prepared[0]["targets"])
def test_overlapping_task_run_is_skipped_without_traceback(self):
config = {
"multiTask": False,
"taskCount": 1,
"sendStrategy": {},
"messageTemplate": "",
"hitokotoTypes": [],
}
user = {"enabled": True, "username": "demo", "targets": ["friend"]}
with (
patch.object(tasks, "get_config", return_value=config),
patch.object(tasks, "get_userData", return_value=[user]),
patch.object(tasks, "_prepare_active_users_for_run", return_value=[user]),
patch.object(
tasks,
"task_run_lock",
side_effect=tasks.TaskRunAlreadyInProgress("already running"),
),
patch.object(tasks, "run_browser_tasks") as run_browser,
):
asyncio.run(tasks.runTasks())
run_browser.assert_not_called()
def test_message_choice_avoids_previous_and_last_when_possible(self):
with patch.object(
msg_builder,
+34 -1
View File
@@ -1,4 +1,5 @@
import errno
import asyncio
import errno
import os
import tempfile
import time
@@ -104,6 +105,38 @@ class WebUiSafetyTests(unittest.TestCase):
self.assertEqual(200, response.status_code, path)
self.assertEqual("no-store", response.headers["cache-control"])
def test_login_desktop_timeout_is_wrapped_as_runtime_error(self):
with patch.object(app_module.urllib.request, "urlopen", side_effect=TimeoutError("timed out")):
with self.assertRaisesRegex(RuntimeError, "login-desktop unavailable: timed out"):
app_module.call_login_desktop("/open-login", method="POST", payload={})
def test_login_desktop_open_uses_extended_startup_timeout(self):
client = TestClient(app_module.app)
with (
patch.object(app_module, "current_user", return_value="admin"),
patch.object(app_module, "validate_csrf", return_value=True),
patch.object(app_module, "call_login_desktop", return_value={}) as call_login,
):
response = client.post("/login-desktop/open", data={"csrf_token": "test"})
self.assertEqual(200, response.status_code)
call_login.assert_called_once_with("/open-login", method="POST", payload={}, timeout=90)
def test_websocket_relay_cleans_up_pending_tasks(self):
cleaned_up = []
async def completes():
return None
async def waits_forever():
try:
await asyncio.Event().wait()
finally:
cleaned_up.append(True)
asyncio.run(app_module._run_websocket_relays(completes(), waits_forever()))
self.assertEqual([True], cleaned_up)
def test_login_desktop_urls_honor_container_environment(self):
with (
patch.dict(