Move the /tasks/* sub-route out of _dispatch into _dispatch_task_route (query passed explicitly; the files/tree/thread branches use it), move the push-subscription DELETE branch out of _dispatch_project into _project_push_subscription_delete, and turn the goal-validation block of _create_task into the pure module function _validate_task_goal_options (returns error string instead of sending 400, caller sends it unchanged). Statements are moved verbatim except indentation and the goal send+return -> return-error transform; no behaviour change. server.py module split intentionally not done: it remains a larger, higher-risk refactor. Add test_longfunc_split covering the pure goal validator's success paths and all eight error strings.
92 lines
3.4 KiB
Python
92 lines
3.4 KiB
Python
"""长函数小步拆分单测:只测从 _create_task 抽出的纯函数。
|
||
|
||
不跑真实模型回合、不联网、不碰 DB:_validate_task_goal_options
|
||
只读 body/prompt/plan,错误串须与抽取前 _create_task 内联分支
|
||
发出的 400 文案逐字一致(改动文案即本文件失败)。
|
||
本文件不含任何真实密钥、token、证书或私钥。
|
||
"""
|
||
|
||
import sys
|
||
import unittest
|
||
from pathlib import Path
|
||
|
||
try:
|
||
from cloud.server import (
|
||
CloudControlPlaneHandler,
|
||
_validate_task_goal_options,
|
||
)
|
||
except ImportError: # discover -s cloud/tests 时把项目根目录补进 sys.path
|
||
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
|
||
from cloud.server import (
|
||
CloudControlPlaneHandler,
|
||
_validate_task_goal_options,
|
||
)
|
||
|
||
|
||
class ValidateTaskGoalOptionsTestCase(unittest.TestCase):
|
||
def test_new_goal_mode(self):
|
||
self.assertEqual(
|
||
_validate_task_goal_options(
|
||
{"goal_mode": 1}, "做 X", None, 0),
|
||
(1, "做 X", None, 0, None))
|
||
|
||
def test_goal_command_target_is_new_goal_mode(self):
|
||
self.assertEqual(
|
||
_validate_task_goal_options(
|
||
{}, "做 X", "做 X", 0),
|
||
(1, "做 X", None, 0, None))
|
||
|
||
def test_new_goal_mode_conflicts(self):
|
||
self.assertEqual(
|
||
_validate_task_goal_options(
|
||
{"goal_mode": 1}, "做 X", None, 1)[4],
|
||
"plan 模式与 goal 模式冲突(只读 vs 改文件)")
|
||
self.assertEqual(
|
||
_validate_task_goal_options(
|
||
{"goal_mode": 1, "verify_command": "make test"},
|
||
"做 X", None, 0)[4],
|
||
"goal 模式不需要验收命令(达标由模型宣告)")
|
||
|
||
def test_old_goal_defaults(self):
|
||
self.assertEqual(
|
||
_validate_task_goal_options({}, "p", None, 0),
|
||
(0, None, None, 3, None))
|
||
|
||
def test_old_goal_explicit(self):
|
||
self.assertEqual(
|
||
_validate_task_goal_options(
|
||
{"goal": "G", "verify_command": "make test",
|
||
"goal_max_rounds": 5}, "p", None, 0),
|
||
(0, "G", "make test", 5, None))
|
||
|
||
def test_old_goal_errors(self):
|
||
# (body, plan, want_error):plan+verify 冲突用例传 plan=1,
|
||
# 其余 plan=0。
|
||
cases = [
|
||
({"goal": 123}, 0, "goal must be a string"),
|
||
({"verify_command": 123}, 0, "verify_command must be a string"),
|
||
({"verify_command": "make test"}, 1,
|
||
"plan 模式与 goal 模式冲突(只读 vs 改文件)"),
|
||
({"goal_max_rounds": "x"}, 0,
|
||
"goal_max_rounds must be an integer"),
|
||
({"goal_max_rounds": 0}, 0, "goal_max_rounds must be >= 1"),
|
||
({"goal_max_rounds": 101}, 0, "goal_max_rounds 超过上限 100 轮"),
|
||
]
|
||
for body, plan, want in cases:
|
||
self.assertEqual(
|
||
_validate_task_goal_options(body, "p", None, plan)[4],
|
||
want, body)
|
||
|
||
def test_split_helpers_exist(self):
|
||
# 结构锚点:两个路由助手须挂在 handler 上(行为由既有
|
||
# dispatch/任务/订阅测试覆盖,本文件不重复搭 HTTP 骨架)。
|
||
self.assertTrue(callable(
|
||
getattr(CloudControlPlaneHandler, "_dispatch_task_route")))
|
||
self.assertTrue(callable(
|
||
getattr(CloudControlPlaneHandler,
|
||
"_project_push_subscription_delete")))
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|