控制台改为选项卡,并支持封禁节点与下发计算任务。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -95,6 +95,97 @@ class CoreFlowTest(unittest.TestCase):
|
||||
denied = self.client.post("/api/v1/node/heartbeat", json={"sn": "NODE-A"})
|
||||
self.assertEqual(denied.status_code, 403, denied.text)
|
||||
|
||||
def test_banned_node_rejects_heartbeat(self) -> None:
|
||||
self._register("0xban", "NODE-BAN", "100")
|
||||
online = self.client.post("/api/v1/node/heartbeat", json={"sn": "NODE-BAN"})
|
||||
self.assertEqual(online.status_code, 200, online.text)
|
||||
banned = self.client.post(
|
||||
"/api/v1/admin/nodes/NODE-BAN/ban",
|
||||
headers=self._admin_headers(),
|
||||
json={"is_banned": True},
|
||||
)
|
||||
self.assertEqual(banned.status_code, 200, banned.text)
|
||||
self.assertTrue(banned.json()["is_banned"])
|
||||
self.assertEqual(banned.json()["status"], "offline")
|
||||
denied = self.client.post("/api/v1/node/heartbeat", json={"sn": "NODE-BAN"})
|
||||
self.assertEqual(denied.status_code, 403, denied.text)
|
||||
self.assertEqual(denied.json()["detail"], "节点已封禁")
|
||||
released = self.client.post(
|
||||
"/api/v1/admin/nodes/NODE-BAN/ban",
|
||||
headers=self._admin_headers(),
|
||||
json={"is_banned": False},
|
||||
)
|
||||
self.assertEqual(released.status_code, 200, released.text)
|
||||
self.assertFalse(released.json()["is_banned"])
|
||||
again = self.client.post("/api/v1/node/heartbeat", json={"sn": "NODE-BAN"})
|
||||
self.assertEqual(again.status_code, 200, again.text)
|
||||
|
||||
def test_admin_can_dispatch_and_collect_task_results(self) -> None:
|
||||
self._register("0xtask1", "NODE-TASK-1", "100")
|
||||
self._register("0xtask2", "NODE-TASK-2", "100")
|
||||
self.client.post("/api/v1/node/heartbeat", json={"sn": "NODE-TASK-1"})
|
||||
self.client.post("/api/v1/node/heartbeat", json={"sn": "NODE-TASK-2"})
|
||||
headers = self._admin_headers()
|
||||
missing = self.client.post(
|
||||
"/api/v1/admin/tasks/create",
|
||||
headers=headers,
|
||||
json={"task_type": "not_a_task", "payload": {}},
|
||||
)
|
||||
self.assertEqual(missing.status_code, 400, missing.text)
|
||||
broadcast = self.client.post(
|
||||
"/api/v1/admin/tasks/create",
|
||||
headers=headers,
|
||||
json={"task_type": "alpha_mining", "payload": {"operators": ["rank"], "population": 32}},
|
||||
)
|
||||
self.assertEqual(broadcast.status_code, 200, broadcast.text)
|
||||
self.assertEqual(len(broadcast.json()), 2)
|
||||
self.assertEqual({row["status"] for row in broadcast.json()}, {"pending"})
|
||||
targeted = self.client.post(
|
||||
"/api/v1/admin/tasks/create",
|
||||
headers=headers,
|
||||
json={
|
||||
"task_type": "lora_training",
|
||||
"target_node_sn": "NODE-TASK-1",
|
||||
"payload": {"base_model": "qwen2.5-7b", "rank": 8},
|
||||
},
|
||||
)
|
||||
self.assertEqual(targeted.status_code, 200, targeted.text)
|
||||
task = targeted.json()[0]
|
||||
self.assertEqual(task["target_node_sn"], "NODE-TASK-1")
|
||||
claimed = self.client.get("/api/v1/node/NODE-TASK-1/tasks")
|
||||
self.assertEqual(claimed.status_code, 200, claimed.text)
|
||||
handed = next(row for row in claimed.json() if row["task_id"] == task["task_id"])
|
||||
self.assertEqual(handed["status"], "processing")
|
||||
reported = self.client.post(
|
||||
"/api/v1/node/task/report",
|
||||
json={
|
||||
"sn": "NODE-TASK-1",
|
||||
"task_id": task["task_id"],
|
||||
"success": True,
|
||||
"nonce": handed["payload"]["nonce"],
|
||||
"result": {"formula": "rank(ts_mean(close, 12))", "patch_bytes": 4096},
|
||||
},
|
||||
)
|
||||
self.assertEqual(reported.status_code, 200, reported.text)
|
||||
listed = self.client.get("/api/v1/admin/tasks/list", headers=headers)
|
||||
self.assertEqual(listed.status_code, 200, listed.text)
|
||||
done = next(row for row in listed.json() if row["task_id"] == task["task_id"])
|
||||
self.assertEqual(done["status"], "completed")
|
||||
self.assertEqual(done["result_preview"], "rank(ts_mean(close, 12))")
|
||||
self._register("0xtask3", "NODE-TASK-3", "100")
|
||||
self.client.post("/api/v1/node/heartbeat", json={"sn": "NODE-TASK-3"})
|
||||
self.client.post(
|
||||
"/api/v1/admin/nodes/NODE-TASK-3/ban",
|
||||
headers=headers,
|
||||
json={"is_banned": True},
|
||||
)
|
||||
blocked = self.client.post(
|
||||
"/api/v1/admin/tasks/create",
|
||||
headers=headers,
|
||||
json={"task_type": "stress_test", "target_node_sn": "NODE-TASK-3", "payload": {"matrix": 128}},
|
||||
)
|
||||
self.assertEqual(blocked.status_code, 409, blocked.text)
|
||||
|
||||
def test_task_report_requires_nonce(self) -> None:
|
||||
self._register("0xdef", "NODE-T", "50")
|
||||
self.client.post("/api/v1/node/heartbeat", json={"sn": "NODE-T"})
|
||||
|
||||
Reference in New Issue
Block a user