feat: P1 补齐(自动评审队列、自动化+分诊、并发 caps、运行时审批队列)

This commit is contained in:
host committed 2026-10-27 15:53:50 +08:00
1 parent 29efc6c61f
commit e0cecd70aa
18 files changed
+3474 -27

No files matched your search

+125
View File
@@ -0,0 +1,125 @@
"""并发上限服务端面单测(/workers 占用展示)。
覆盖:GET /workers 行里含 capacity 与 running;心跳上报 running
后列表可见;心跳未给 running 时保留旧值;非法 running 400;
未认证 401;/workers 读权限口径是任何已认证用户(与既有
_workers_list 一致,不按项目成员过滤)。
只用标准库 http.client,不跑真实模型,不联网。
"""
import http.client
import json
import os
import sys
import tempfile
import threading
import unittest
from pathlib import Path
try:
from cloud.auth import AuthStore
from cloud.server import create_server
except ImportError: # discover -s cloud/tests 时把项目根目录补进 sys.path
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from cloud.auth import AuthStore
from cloud.server import create_server
class CapsServerTestCase(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.db_path = os.path.join(self.tmp.name, "control.db")
self.auth = AuthStore(self.db_path)
self.owner_id, self.owner_key = self.auth.create_user("owner")
self.viewer_id, self.viewer_key = self.auth.create_user("viewer")
self.server = create_server(self.db_path, "127.0.0.1", 0)
self.port = self.server.server_address[1]
self.thread = threading.Thread(
target=self.server.serve_forever, daemon=True)
self.thread.start()
def tearDown(self):
self.server.shutdown()
self.server.server_close()
self.thread.join(timeout=5)
try:
self.auth.conn.close()
except Exception:
pass
self.tmp.cleanup()
def _req(self, method, path, body=None, key=None):
conn = http.client.HTTPConnection("127.0.0.1", self.port, timeout=10)
hdrs = {}
payload = None
if body is not None:
payload = json.dumps(body).encode("utf-8")
hdrs["Content-Type"] = "application/json"
if key is not None:
hdrs["X-API-Key"] = key
try:
conn.request(method, path, body=payload, headers=hdrs)
resp = conn.getresponse()
data = resp.read()
finally:
conn.close()
try:
parsed = json.loads(data.decode("utf-8")) if data else None
except ValueError:
parsed = None
return resp.status, parsed
def _workers(self, key):
status, body = self._req("GET", "/workers", key=key)
self.assertEqual(status, 200, body)
return {w["worker_id"]: w for w in body["workers"]}
def test_workers_list_shows_capacity_and_running(self):
status, body = self._req(
"POST", "/workers/heartbeat",
{"worker_id": "w1", "executor": "local",
"capacity": 4, "running": 2},
self.owner_key)
self.assertEqual(status, 200, body)
# 读权限:任何已认证用户可读(viewer 也能看到基础设施行)。
workers = self._workers(self.viewer_key)
self.assertEqual(workers["w1"]["capacity"], 4)
self.assertEqual(workers["w1"]["running"], 2)
def test_heartbeat_without_running_preserves_old(self):
self._req("POST", "/workers/heartbeat",
{"worker_id": "w1", "capacity": 2, "running": 1},
self.owner_key)
status, body = self._req(
"POST", "/workers/heartbeat", {"worker_id": "w1"},
self.owner_key)
self.assertEqual(status, 200, body)
self.assertEqual(body["running"], 1)
self.assertEqual(self._workers(self.owner_key)["w1"]["running"], 1)
def test_heartbeat_invalid_running_400(self):
status, _ = self._req(
"POST", "/workers/heartbeat",
{"worker_id": "w1", "running": "abc"}, self.owner_key)
self.assertEqual(status, 400)
status, _ = self._req(
"POST", "/workers/heartbeat",
{"worker_id": "w1", "running": -1}, self.owner_key)
self.assertEqual(status, 400)
def test_workers_requires_auth(self):
status, _ = self._req("GET", "/workers")
self.assertEqual(status, 401)
def test_heartbeat_registers_unknown_worker_with_defaults(self):
status, body = self._req(
"POST", "/workers/heartbeat", {"worker_id": "new1"},
self.owner_key)
self.assertEqual(status, 200, body)
self.assertEqual(body["capacity"], 1)
self.assertEqual(body["running"], 0)
if __name__ == "__main__":
unittest.main()