Files
AgentLab/backend/tests/test_job_runtime.py
T
ThearchyHelios 9d8b41430e 完善口径管理、主动调查与后台任务,修复通用问题
- 完善口径编辑、只读试运行、统一质量验证与执行语义指纹
- 增加可执行指标约束、有预算的主动调查和过程评测
- 提取发布检查、证据读取与起草服务,支持任务停止、重试和检查点恢复
- 增加版本传递影响分析,修复并发覆盖、敏感值遮罩、异常评分及页面状态问题
- 修复 SQLite 复合查询追溯和 microVM 可选依赖缺失处理
- 纳入当前设计文档及部署配置调整

验证:相关主回归 3822 项通过,4 项跳过、8 项预期失败;补充回归通过。
前端构建、文案检查及 git diff --check 通过。
全量检查仍有环境权限、PostgreSQL 可选依赖和既有部署配置、SQLite 文件基线差异导致的未通过项。
2026-11-06 17:14:45 +08:00

105 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""后台任务运行时上移到 core/job_runtime.py(docs/design/next-round/00-总方案.md X5)。
守三件事:老路径 data/catalog_job_runtime 拿到的是同一个模块(同一条队、同一批名字,起草、剖析的 import 不用改);
同源队里的事是开放的——新的一种登记一行就和起草、剖析排进同一条队、同源串行;没登记的 kind 当场报错,不会悄悄排成
一种谁都不认识的事。
"""
from __future__ import annotations
import asyncio
import pytest
from app.core import job_runtime
def test_the_old_path_is_the_same_module():
from app.data import catalog_job_runtime as old
from app.data.catalog_job_runtime import lanes
assert old is job_runtime
assert lanes is job_runtime.lanes
# 起草、剖析照旧从老路径导入,登记的几种事都在
import app.data.catalog_jobs # noqa: F401
import app.data.catalog_profile_jobs # noqa: F401
assert {"draft", "profile", "sync_draft", "import"} <= set(job_runtime.lane_kinds())
assert job_runtime.lane_label("profile") == "剖析"
def test_an_unregistered_kind_is_refused():
lanes = job_runtime.SourceLanes()
async def go() -> None:
with pytest.raises(ValueError, match="没有登记"):
await lanes.enter("src", "nonsense-kind")
asyncio.run(go())
def test_a_registered_label_cannot_change():
job_runtime.register_lane_kind("test-open-kind", "测试用")
job_runtime.register_lane_kind("test-open-kind", "测试用") # 同一个叫法再登记无害
with pytest.raises(ValueError, match="已经登记"):
job_runtime.register_lane_kind("test-open-kind", "别的叫法")
def test_a_new_kind_queues_behind_the_existing_ones_on_the_same_source():
"""新登记的一种(第 2 波的后台探查就是这样加进来的)和起草排进同一条队:同源串行,不同源并行。"""
import app.data.catalog_jobs # noqa: F401 - 登记 draft
job_runtime.register_lane_kind("test-introspect", "测试探查")
lanes = job_runtime.SourceLanes()
async def go() -> None:
first = await lanes.enter("src-a", "draft", "job-1")
second = await lanes.enter("src-a", "test-introspect", "job-2")
other = await lanes.enter("src-b", "test-introspect", "job-3")
assert first.granted.is_set() and not second.granted.is_set()
assert other.granted.is_set(), "不同源并行"
assert await lanes.ahead("src-a", "job-2") == ["draft"]
await first.release()
await asyncio.wait_for(second.wait(), timeout=1)
await second.release()
await other.release()
asyncio.run(go())
def test_a_job_without_a_lane_skips_the_queue():
"""lane_of 返回 None 的任务(以后不占源的评测)不进队、直接执行。"""
class _NoLane(job_runtime.JobRun):
kind = "draft"
def lane_of(self, job): # noqa: ANN001
return None
run = _NoLane("whatever")
assert run.lane_of(object()) is None
def test_starting_an_active_job_twice_does_not_orphan_the_first_task():
async def go():
calls = []
finish = asyncio.Event()
class Job:
def __init__(self, job_id):
self.job_id, self.task = job_id, None
async def run(self):
calls.append(self.job_id)
await finish.wait()
manager = job_runtime.JobManager(Job, label="幂等启动测试", name="test_start_once")
manager.start("one")
manager.start("one")
await asyncio.sleep(0)
assert calls == ["one"] and manager.running("one")
finish.set()
await manager.wait("one")
assert not manager.running("one")
asyncio.run(go())