93 lines
2.9 KiB
Python
93 lines
2.9 KiB
Python
"""点数预检/熔断/暂停/删除 专项测试。"""
|
|
from sqlmodel import Session, SQLModel, create_engine
|
|
|
|
from app.models import (Agent, Campaign, CampaignRun, PointAccount, Segment)
|
|
from app.points_guard import points_preflight, should_break_run
|
|
|
|
|
|
def _session():
|
|
engine = create_engine("sqlite://", connect_args={"check_same_thread": False})
|
|
SQLModel.metadata.create_all(engine)
|
|
return Session(engine)
|
|
|
|
|
|
def _campaign(session, owner_id=1, org_id=1):
|
|
camp = Campaign(name="测试任务", owner_user_id=owner_id, organization_id=org_id)
|
|
session.add(camp)
|
|
session.commit()
|
|
session.refresh(camp)
|
|
return camp
|
|
|
|
|
|
# ---------------- 启动预检 ----------------
|
|
|
|
def test_preflight_blocks_when_balance_below_estimate():
|
|
with _session() as s:
|
|
camp = _campaign(s)
|
|
s.add(PointAccount(user_id=1, organization_id=1, balance_points=1000))
|
|
s.commit()
|
|
result = points_preflight(s, camp, estimated_points=100_000)
|
|
assert not result["ok"]
|
|
assert "点数不足" in result["blocker"]
|
|
assert "20% 缓冲" in result["blocker"]
|
|
assert result["info"]["required_points"] == 120_000
|
|
|
|
|
|
def test_preflight_passes_with_buffer():
|
|
with _session() as s:
|
|
camp = _campaign(s)
|
|
s.add(PointAccount(user_id=1, organization_id=1, balance_points=130_000))
|
|
s.commit()
|
|
result = points_preflight(s, camp, estimated_points=100_000)
|
|
assert result["ok"]
|
|
assert result["info"]["required_points"] == 120_000
|
|
|
|
|
|
def test_preflight_blocks_at_exact_boundary():
|
|
with _session() as s:
|
|
camp = _campaign(s)
|
|
s.add(PointAccount(user_id=1, organization_id=1, balance_points=119_999))
|
|
s.commit()
|
|
assert not points_preflight(s, camp, 100_000)["ok"]
|
|
s.get(PointAccount, 1).balance_points = 120_000
|
|
s.commit()
|
|
assert points_preflight(s, camp, 100_000)["ok"]
|
|
|
|
|
|
# ---------------- 运行中熔断判断 ----------------
|
|
|
|
def test_break_on_balance_error():
|
|
brk, _ = should_break_run({"type": "", "detail": "点数余额不足,至少需要 10 点数"})
|
|
assert brk
|
|
|
|
|
|
def test_break_on_auth_error():
|
|
brk, _ = should_break_run({"type": "billing", "detail": ""})
|
|
assert brk
|
|
brk2, _ = should_break_run({"type": "", "detail": "Error code: 401 - Invalid API Key"})
|
|
assert brk2
|
|
|
|
|
|
def test_no_break_on_transient_error():
|
|
brk, _ = should_break_run({"type": "", "detail": "timeout: 请求超时"})
|
|
assert not brk
|
|
brk2, _ = should_break_run(None)
|
|
assert not brk2
|
|
|
|
|
|
# ---------------- run pause_requested 字段 ----------------
|
|
|
|
def test_run_pause_fields_exist():
|
|
with _session() as s:
|
|
camp = _campaign(s)
|
|
run = CampaignRun(campaign_id=camp.id, status="running")
|
|
s.add(run)
|
|
s.commit()
|
|
s.refresh(run)
|
|
assert run.pause_requested is False
|
|
run.pause_requested = True
|
|
s.add(run)
|
|
s.commit()
|
|
s.refresh(run)
|
|
assert run.pause_requested is True
|