muse-agent-example/tests/单元/test_预算与配置.py
zizi 367d01db21 W06 模型宿主、角色、预算与流式合同:模型宿主合同、角色策略冻结、预算预留结算与流式回合证据。
按 R2 串行阶段整理提交;包内文件为该阶段交付(含后续小增量),状态以工作包清单为准。
2026-09-10 19:25:41 +08:00

86 lines
3.2 KiB
Python

"""预算时间与金额、配置引用的确定性合同。"""
from datetime import datetime, timedelta
from decimal import Decimal
from zoneinfo import ZoneInfo
import pytest
from muse.任务运行.配置版本 import 凭据引用, 提供方配置, 运行配置内容, 配置版本错误
from muse.任务运行.预算管理 import 任务预算计划, 归属窗口, 角色预算, 预算错误, 额度策略
@pytest.mark.parametrize(
"hour,expected",
[(0, 0), (4, 0), (5, 5), (9, 5), (10, 10), (14, 10), (15, 15), (19, 15), (20, 20), (23, 20)],
ids=["00", "04", "05", "09", "10", "14", "15", "19", "20", "23"],
)
def test_五小时额度窗口承接每日边界__2852b5(hour: int, expected: int) -> None:
当前 = datetime(2026, 7, 16, hour, 30, tzinfo=ZoneInfo("Asia/Shanghai"))
窗口 = 归属窗口(当前)
assert 窗口.起点.strftime("%Y-%m-%dT%H") == f"2026-07-16T{expected:02}"
assert 窗口.终点 - 窗口.起点 == timedelta(hours=4 if hour >= 20 else 5)
@pytest.mark.parametrize(
"hour,minute,seconds",
[(3, 0, 7200), (19, 30, 1800), (21, 0, 10800), (23, 59, 60)],
ids=["morning", "20-boundary", "midnight", "last-minute"],
)
def test_下一窗口等待秒数按原日界线计算__7790f8(hour: int, minute: int, seconds: int) -> None:
当前 = datetime(2026, 9, 9, hour, minute, tzinfo=ZoneInfo("Asia/Shanghai"))
assert (归属窗口(当前).终点 - 当前).total_seconds() == seconds
def test_预算计划保留调用计划并按单次上限预留__a60003() -> None:
角色 = (
角色预算("writer", 45, 150, Decimal("5")),
角色预算("detector", 24, 150, Decimal("5")),
角色预算("judge", 45, 150, Decimal("5")),
)
计划 = 任务预算计划(
Decimal("570"), 角色, "approval-1", datetime(2030, 1, 1, tzinfo=ZoneInfo("UTC"))
)
assert 计划.最坏预留 == Decimal("570.000000")
assert 计划.冻结()["角色"][0]["计划次数"] == 45
with pytest.raises(预算错误):
任务预算计划(Decimal("569.99"), 角色, "approval-1", 计划.截止时间)
@pytest.mark.parametrize(
"amount",
[Decimal("NaN"), Decimal("-1"), Decimal("Infinity")],
ids=["nan", "negative", "infinite"],
)
def test_预算拒绝不确定或负数金额__a60001(amount: Decimal) -> None:
with pytest.raises(预算错误):
额度策略("quota", "1", amount, 6000)
def test_配置凭据只保留引用且调用参数不可藏入明文__a60002() -> None:
引用 = 凭据引用("api", "环境变量", "MUSE_PROVIDER_KEY")
内容 = 运行配置内容(
"direct",
"1",
"role-policy-1",
"release-1",
"quota-1",
{"writer": {"provider": "provider", "model": "model", "thinking": "high"}},
(引用,),
(提供方配置("provider", "responses", "https://provider.invalid/v1/responses", "api"),),
"price-1",
)
assert 内容.冻结()["凭据"][0]["位置"] == "MUSE_PROVIDER_KEY"
with pytest.raises(配置版本错误):
运行配置内容(
"direct",
"1",
"policy",
"release",
"quota",
{"writer": {"api_key": "synthetic-secret"}},
(),
(),
"price-1",
)