chore: push all design docs, V2 plan specs, and current working state
Includes AirPlan design documents, AircOding-alpha1-plan, AirPlanV2, AirPlan-ParaV2, AirPlan-Para V1 reference docs, and all working code changes across packages. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
491
AirPlan/docs/spec/AirPlanV2/test_p1_21.py
Executable file
491
AirPlan/docs/spec/AirPlanV2/test_p1_21.py
Executable file
@@ -0,0 +1,491 @@
|
||||
#!/usr/bin/env python3
|
||||
"""P1-21 ADR 变更级联失效 功能测试"""
|
||||
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent / "lib"))
|
||||
|
||||
|
||||
def test_task_node_adr_refs():
|
||||
"""测试 TaskNode.adr_refs 字段"""
|
||||
from air_runtime.task_graph import TaskNode
|
||||
|
||||
node = TaskNode(id="T-001", adr_refs=["ADR-0005", "ADR-0012"])
|
||||
assert node.adr_refs == ["ADR-0005", "ADR-0012"]
|
||||
|
||||
# 默认为空列表
|
||||
node2 = TaskNode(id="T-002")
|
||||
assert node2.adr_refs == []
|
||||
|
||||
print("✓ TaskNode.adr_refs 测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_invalidated_status():
|
||||
"""测试 INVALIDATED 状态"""
|
||||
from air_runtime.task_graph import TaskNode, TaskGraph
|
||||
|
||||
node = TaskNode(id="T-001", status="DONE", task="用 ffmpeg 实现解码器",
|
||||
adr_refs=["ADR-0005"])
|
||||
|
||||
# 直接设置 INVALIDATED
|
||||
node.status = "INVALIDATED"
|
||||
assert node.status == "INVALIDATED"
|
||||
|
||||
# _update_node 允许 INVALIDATED 覆盖 DONE
|
||||
graph = TaskGraph()
|
||||
graph.add_node(TaskNode(id="T-001", status="DONE", task="旧描述", adr_refs=["ADR-0005"]))
|
||||
graph._update_node(TaskNode(id="T-001", status="INVALIDATED", task="新描述", adr_refs=["ADR-0005"]))
|
||||
assert graph.nodes["T-001"].status == "INVALIDATED"
|
||||
|
||||
# _update_node 仍然保护 DONE 不被普通修改覆盖
|
||||
graph2 = TaskGraph()
|
||||
graph2.add_node(TaskNode(id="T-002", status="DONE", task="旧描述"))
|
||||
graph2._update_node(TaskNode(id="T-002", status="TODO", task="新描述"))
|
||||
assert graph2.nodes["T-002"].status == "DONE" # 被保护,不允许降级为 TODO
|
||||
|
||||
print("✓ INVALIDATED 状态测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_tasks_by_adr():
|
||||
"""测试 ADR→任务溯源链查询"""
|
||||
from air_runtime.task_graph import TaskGraph, TaskNode
|
||||
|
||||
graph = TaskGraph()
|
||||
graph.add_node(TaskNode(id="T-001", task="ffmpeg 解码器", adr_refs=["ADR-0005"]))
|
||||
graph.add_node(TaskNode(id="T-002", task="ffmpeg 编码器", adr_refs=["ADR-0005", "ADR-0010"]))
|
||||
graph.add_node(TaskNode(id="T-003", task="UI 界面", adr_refs=["ADR-0008"]))
|
||||
graph.add_node(TaskNode(id="T-004", task="日志模块", adr_refs=[]))
|
||||
|
||||
# ADR-0005 关联 T-001 和 T-002
|
||||
result = graph.tasks_by_adr("ADR-0005")
|
||||
assert len(result) == 2
|
||||
assert {n.id for n in result} == {"T-001", "T-002"}
|
||||
|
||||
# ADR-0010 只关联 T-002
|
||||
result2 = graph.tasks_by_adr("ADR-0010")
|
||||
assert len(result2) == 1
|
||||
assert result2[0].id == "T-002"
|
||||
|
||||
# 不存在的 ADR
|
||||
result3 = graph.tasks_by_adr("ADR-9999")
|
||||
assert len(result3) == 0
|
||||
|
||||
print("✓ ADR→任务溯源链查询测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_invalidate_by_adr():
|
||||
"""测试 ADR 变更级联失效"""
|
||||
from air_runtime.task_graph import TaskGraph, TaskNode, Edge, PlanDelta
|
||||
|
||||
graph = TaskGraph()
|
||||
# 已完成的 ffmpeg 任务
|
||||
graph.add_node(TaskNode(id="T-001", status="DONE", task="ffmpeg 解码器", adr_refs=["ADR-0005"]))
|
||||
graph.add_node(TaskNode(id="T-002", status="DONE", task="ffmpeg 编码器", adr_refs=["ADR-0005"]))
|
||||
# 进行中的 ffmpeg 任务
|
||||
graph.add_node(TaskNode(id="T-003", status="DISPATCHED", task="ffmpeg 流媒体", adr_refs=["ADR-0005"]))
|
||||
# ADR 直接关联的 TODO 任务
|
||||
graph.add_node(TaskNode(id="T-003b", status="TODO", task="ffmpeg 滤镜", adr_refs=["ADR-0005"]))
|
||||
# 下游任务(依赖上面的 ffmpeg 模块)
|
||||
graph.add_node(TaskNode(id="T-004", status="TODO", task="集成测试"))
|
||||
graph.add_node(TaskNode(id="T-005", status="TODO", task="部署"))
|
||||
# 无关任务
|
||||
graph.add_node(TaskNode(id="T-006", status="TODO", task="UI 优化", adr_refs=["ADR-0008"]))
|
||||
|
||||
graph.add_edge(Edge(source="T-001", target="T-004"))
|
||||
graph.add_edge(Edge(source="T-002", target="T-004"))
|
||||
graph.add_edge(Edge(source="T-004", target="T-005"))
|
||||
|
||||
delta = PlanDelta()
|
||||
report = graph.invalidate_by_adr("ADR-0005", delta)
|
||||
|
||||
# 已完成: T-001, T-002
|
||||
assert report.invalidated_completed == 2
|
||||
# 进行中: T-003
|
||||
assert report.terminated_in_progress == 1
|
||||
# 下游: T-004, T-005 (T-003b 是直接关联的 TODO,不属于 cascaded_downstream)
|
||||
# 注意:T-003b 直接关联 ADR-0005,作为 pending 标记为 INVALIDATED
|
||||
# 但它不属于 cascaded_downstream(级联的下游任务)
|
||||
# cascaded_downstream 仅计算 _find_downstream 返回的非 ADR 直接关联任务
|
||||
assert report.cascaded_downstream == 2
|
||||
# 总失效 = completed(2) + in_progress(1) + pending(1) + cascaded(2) = 6
|
||||
total_invalidated = len(report.invalidated_task_ids)
|
||||
assert total_invalidated == 6
|
||||
|
||||
# 验证状态已变为 INVALIDATED
|
||||
assert graph.nodes["T-001"].status == "INVALIDATED"
|
||||
assert graph.nodes["T-002"].status == "INVALIDATED"
|
||||
assert graph.nodes["T-003"].status == "INVALIDATED"
|
||||
assert graph.nodes["T-003b"].status == "INVALIDATED"
|
||||
assert graph.nodes["T-004"].status == "INVALIDATED"
|
||||
assert graph.nodes["T-005"].status == "INVALIDATED"
|
||||
|
||||
# 无关任务不受影响
|
||||
assert graph.nodes["T-006"].status == "TODO"
|
||||
|
||||
# 调度已冻结
|
||||
assert graph.dispatch_frozen == True
|
||||
|
||||
# ready_tasks 为空(冻结状态)
|
||||
assert graph.ready_tasks() == []
|
||||
|
||||
print(f"✓ ADR 变更级联失效测试通过 (完成={report.invalidated_completed}, "
|
||||
f"进行中={report.terminated_in_progress}, 下游={report.cascaded_downstream})")
|
||||
return True
|
||||
|
||||
|
||||
def test_dispatch_freeze_unfreeze():
|
||||
"""测试调度冻结和解冻"""
|
||||
from air_runtime.task_graph import TaskGraph, TaskNode
|
||||
|
||||
graph = TaskGraph()
|
||||
graph.add_node(TaskNode(id="T-001", status="TODO", task="任务1"))
|
||||
|
||||
# 正常状态
|
||||
assert graph.ready_tasks() == ["T-001"]
|
||||
|
||||
# 冻结
|
||||
graph.dispatch_frozen = True
|
||||
assert graph.ready_tasks() == []
|
||||
|
||||
# 解冻
|
||||
graph.unfreeze_dispatch()
|
||||
assert graph.dispatch_frozen == False
|
||||
assert graph.ready_tasks() == ["T-001"]
|
||||
|
||||
print("✓ 调度冻结/解冻测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_cascade_report():
|
||||
"""测试 CascadeReport 数据结构"""
|
||||
from air_runtime.task_graph import CascadeReport
|
||||
|
||||
report = CascadeReport(
|
||||
invalidated_completed=2,
|
||||
terminated_in_progress=1,
|
||||
cascaded_downstream=3,
|
||||
rollback_ref="airplan/adr-invalidate-2026-06-11",
|
||||
invalidated_task_ids=["T-001", "T-002", "T-003", "T-004", "T-005", "T-006"],
|
||||
)
|
||||
|
||||
assert report.invalidated_completed == 2
|
||||
assert report.terminated_in_progress == 1
|
||||
assert report.cascaded_downstream == 3
|
||||
assert report.rollback_ref.startswith("airplan/")
|
||||
assert len(report.invalidated_task_ids) == 6
|
||||
|
||||
print("✓ CascadeReport 测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_plan_delta_rollback_ref():
|
||||
"""测试 PlanDelta.rollback_ref"""
|
||||
from air_runtime.task_graph import PlanDelta
|
||||
|
||||
delta = PlanDelta(rollback_ref="airplan/adr-invalidate-2026-06-11")
|
||||
assert delta.rollback_ref == "airplan/adr-invalidate-2026-06-11"
|
||||
|
||||
# 默认为空字符串
|
||||
delta2 = PlanDelta()
|
||||
assert delta2.rollback_ref == ""
|
||||
|
||||
print("✓ PlanDelta.rollback_ref 测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_rvr_invalidated_cleanup_check():
|
||||
"""测试 AirRvr INVALIDATED 清理检查"""
|
||||
from air_runtime.review_runtime import ReviewRuntime
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
project_root = Path(tmpdir)
|
||||
rvr = ReviewRuntime(project_root)
|
||||
|
||||
# 无残留
|
||||
result = rvr.check_invalidated_cleanup(["T-001", "T-002"])
|
||||
assert result["cleaned"] == True
|
||||
assert result["residualCount"] == 0
|
||||
|
||||
# 创建残留的 result 文件
|
||||
result_dir = project_root / "AirPlan" / "state" / "airdo" / "tasks" / "T-001"
|
||||
result_dir.mkdir(parents=True, exist_ok=True)
|
||||
(result_dir / "result.json").write_text('{"taskId": "T-001", "status": "done"}')
|
||||
|
||||
result2 = rvr.check_invalidated_cleanup(["T-001"])
|
||||
assert result2["cleaned"] == False
|
||||
assert result2["residualCount"] == 1
|
||||
assert result2["residualDetails"][0]["taskId"] == "T-001"
|
||||
|
||||
print("✓ AirRvr INVALIDATED 清理检查测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_eng_handle_adr_invalidation():
|
||||
"""测试 Eng ADR 失效处理入口"""
|
||||
from air_runtime.modes.eng_mode import handle_adr_invalidation
|
||||
import json
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
project_root = Path(tmpdir)
|
||||
|
||||
# 初始化引擎
|
||||
from air_runtime.modes.eng_mode import enter_engine
|
||||
enter_engine(project_root)
|
||||
|
||||
# 创建 task-graph.json(含 ADR 引用)
|
||||
arc_dir = project_root / "AirPlan" / "state" / "airarc" / "reviews"
|
||||
arc_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
from air_runtime.task_graph import TaskGraph, TaskNode, Edge
|
||||
from air_runtime.modes.arc_mode import _export_task_graph_json
|
||||
|
||||
graph = TaskGraph()
|
||||
graph.add_node(TaskNode(id="T-001", status="DONE", task="ffmpeg 解码器", adr_refs=["ADR-0005"]))
|
||||
graph.add_node(TaskNode(id="T-002", status="TODO", task="集成测试"))
|
||||
graph.add_edge(Edge(source="T-001", target="T-002"))
|
||||
_export_task_graph_json(graph, arc_dir / "task-graph.json")
|
||||
|
||||
# 执行 ADR 失效
|
||||
result = handle_adr_invalidation(project_root, "ADR-0005")
|
||||
|
||||
assert "cascadeReport" in result
|
||||
assert result["cascadeReport"]["invalidatedCompleted"] == 1
|
||||
assert result["cascadeReport"]["cascadedDownstream"] == 1
|
||||
assert result["nextStep"] == "arc-replan-then-unfreeze"
|
||||
|
||||
# 验证 task-graph.json 已更新
|
||||
updated = TaskGraph.load(arc_dir / "task-graph.json")
|
||||
assert updated.nodes["T-001"].status == "INVALIDATED"
|
||||
assert updated.dispatch_frozen == True
|
||||
|
||||
print("✓ Eng ADR 失效处理测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_eng_unfreeze_after_replan():
|
||||
"""测试 Eng 解冻调度"""
|
||||
from air_runtime.modes.eng_mode import handle_adr_invalidation, unfreeze_after_replan
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
project_root = Path(tmpdir)
|
||||
|
||||
from air_runtime.modes.eng_mode import enter_engine
|
||||
enter_engine(project_root)
|
||||
|
||||
arc_dir = project_root / "AirPlan" / "state" / "airarc" / "reviews"
|
||||
arc_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
from air_runtime.task_graph import TaskGraph, TaskNode
|
||||
from air_runtime.modes.arc_mode import _export_task_graph_json
|
||||
|
||||
graph = TaskGraph()
|
||||
graph.add_node(TaskNode(id="T-001", status="DONE", task="ffmpeg 解码器", adr_refs=["ADR-0005"]))
|
||||
graph.dispatch_frozen = True
|
||||
_export_task_graph_json(graph, arc_dir / "task-graph.json")
|
||||
|
||||
# 解冻
|
||||
result = unfreeze_after_replan(project_root)
|
||||
|
||||
assert result["frozen"] == False
|
||||
|
||||
# 验证 task-graph.json 已解冻
|
||||
updated = TaskGraph.load(arc_dir / "task-graph.json")
|
||||
assert updated.dispatch_frozen == False
|
||||
|
||||
print("✓ Eng 解冻调度测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_ffmpeg_to_gstreamer_scenario():
|
||||
"""完整场景测试:ffmpeg → gstreamer 架构变更"""
|
||||
from air_runtime.task_graph import TaskGraph, TaskNode, Edge, PlanDelta
|
||||
|
||||
# 初始状态:ffmpeg 架构
|
||||
graph = TaskGraph()
|
||||
graph.add_node(TaskNode(id="T-001", status="DONE", task="用 ffmpeg 实现视频解码器",
|
||||
files_dirs="src/decoder.cpp", adr_refs=["ADR-0005"]))
|
||||
graph.add_node(TaskNode(id="T-002", status="DONE", task="用 ffmpeg 实现音频解码器",
|
||||
files_dirs="src/audio_decoder.cpp", adr_refs=["ADR-0005"]))
|
||||
graph.add_node(TaskNode(id="T-003", status="DONE", task="ffmpeg 流媒体传输",
|
||||
files_dirs="src/streaming.cpp", adr_refs=["ADR-0005", "ADR-0006"]))
|
||||
graph.add_node(TaskNode(id="T-004", status="TODO", task="解码器集成测试",
|
||||
files_dirs="tests/decoder_test.cpp"))
|
||||
graph.add_node(TaskNode(id="T-005", status="TODO", task="流媒体集成测试",
|
||||
files_dirs="tests/streaming_test.cpp"))
|
||||
graph.add_node(TaskNode(id="T-006", status="TODO", task="部署播放器",
|
||||
files_dirs="deploy/"))
|
||||
# 无关任务
|
||||
graph.add_node(TaskNode(id="T-007", status="DONE", task="用户界面",
|
||||
files_dirs="src/ui/", adr_refs=["ADR-0008"]))
|
||||
graph.add_node(TaskNode(id="T-008", status="TODO", task="UI 测试",
|
||||
files_dirs="tests/ui_test.cpp"))
|
||||
|
||||
graph.add_edge(Edge(source="T-001", target="T-004"))
|
||||
graph.add_edge(Edge(source="T-002", target="T-004"))
|
||||
graph.add_edge(Edge(source="T-003", target="T-005"))
|
||||
graph.add_edge(Edge(source="T-004", target="T-006"))
|
||||
graph.add_edge(Edge(source="T-005", target="T-006"))
|
||||
graph.add_edge(Edge(source="T-007", target="T-008"))
|
||||
|
||||
# ADR-0005 变更:ffmpeg → gstreamer
|
||||
delta = PlanDelta(rollback_ref="airplan/adr-invalidate-snapshot-001")
|
||||
report = graph.invalidate_by_adr("ADR-0005", delta)
|
||||
|
||||
# T-001, T-002, T-003 完成 → INVALIDATED
|
||||
assert report.invalidated_completed == 3
|
||||
# T-004, T-005, T-006 下游 → INVALIDATED
|
||||
assert report.cascaded_downstream == 3
|
||||
total_invalidated = len(report.invalidated_task_ids)
|
||||
assert total_invalidated == 6 # T-001~T-006 全部失效
|
||||
|
||||
# 无关任务不受影响
|
||||
assert graph.nodes["T-007"].status == "DONE"
|
||||
assert graph.nodes["T-008"].status == "TODO"
|
||||
|
||||
# 调度冻结
|
||||
assert graph.dispatch_frozen == True
|
||||
assert graph.ready_tasks() == []
|
||||
|
||||
# 模拟 Arc 重新生成 gstreamer 任务后解冻
|
||||
graph.add_node(TaskNode(id="T-101", status="TODO", task="用 gstreamer 实现视频解码器",
|
||||
files_dirs="src/decoder.cpp", adr_refs=["ADR-0005"]))
|
||||
graph.add_node(TaskNode(id="T-102", status="TODO", task="用 gstreamer 实现音频解码器",
|
||||
files_dirs="src/audio_decoder.cpp", adr_refs=["ADR-0005"]))
|
||||
graph.unfreeze_dispatch()
|
||||
|
||||
assert graph.dispatch_frozen == False
|
||||
# 新任务可以派发
|
||||
ready = [tid for tid, n in graph.nodes.items() if n.status == "TODO" and n.in_degree == 0]
|
||||
assert "T-101" in ready
|
||||
assert "T-102" in ready
|
||||
# T-008 有入度(依赖 T-007),不在 ready 中
|
||||
assert "T-008" not in ready
|
||||
|
||||
print(f"✓ ffmpeg→gstreamer 完整场景测试通过 (失效={total_invalidated}, 新任务可派发)")
|
||||
return True
|
||||
|
||||
|
||||
def test_apply_full_replace_preserves_dispatched():
|
||||
"""测试 apply_full_replace 保留 DISPATCHED 状态(不含 INVALIDATED)"""
|
||||
from air_runtime.task_graph import TaskGraph, TaskNode, Edge
|
||||
|
||||
old_graph = TaskGraph()
|
||||
old_graph.add_node(TaskNode(id="T-001", status="DONE", task="已完成"))
|
||||
old_graph.add_node(TaskNode(id="T-002", status="DISPATCHED", task="进行中"))
|
||||
old_graph.add_node(TaskNode(id="T-003", status="INVALIDATED", task="已失效"))
|
||||
|
||||
new_nodes = [
|
||||
TaskNode(id="T-001", status="TODO", task="已完成"),
|
||||
TaskNode(id="T-002", status="TODO", task="进行中"),
|
||||
TaskNode(id="T-003", status="TODO", task="已失效"),
|
||||
]
|
||||
|
||||
old_graph.apply_full_replace(new_nodes, [])
|
||||
|
||||
# DONE 和 DISPATCHED 被保留
|
||||
assert old_graph.nodes["T-001"].status == "DONE"
|
||||
assert old_graph.nodes["T-002"].status == "DISPATCHED"
|
||||
# INVALIDATED 不被保留(全量替换时重置为 TODO)
|
||||
assert old_graph.nodes["T-003"].status == "TODO"
|
||||
|
||||
print("✓ apply_full_replace 保留 DONE/DISPATCHED 测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def test_git_revert_with_real_repo():
|
||||
"""测试真实 git 仓库环境下的 revert"""
|
||||
import subprocess
|
||||
from air_runtime.modes.eng_mode import handle_adr_invalidation
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
project_root = Path(tmpdir)
|
||||
|
||||
# 初始化 git 仓库
|
||||
subprocess.run(["git", "init"], cwd=project_root, capture_output=True)
|
||||
subprocess.run(["git", "config", "user.email", "test@test.com"], cwd=project_root, capture_output=True)
|
||||
subprocess.run(["git", "config", "user.name", "Test"], cwd=project_root, capture_output=True)
|
||||
|
||||
# 创建文件并提交(模拟 T-001 的代码)
|
||||
(project_root / "src").mkdir()
|
||||
(project_root / "src" / "decoder.cpp").write_text("// ffmpeg decoder")
|
||||
subprocess.run(["git", "add", "."], cwd=project_root, capture_output=True)
|
||||
subprocess.run(["git", "commit", "-m", "feat: T-001 ffmpeg decoder"], cwd=project_root, capture_output=True)
|
||||
|
||||
# 初始化引擎和 task-graph
|
||||
from air_runtime.modes.eng_mode import enter_engine
|
||||
enter_engine(project_root)
|
||||
|
||||
arc_dir = project_root / "AirPlan" / "state" / "airarc" / "reviews"
|
||||
arc_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
from air_runtime.task_graph import TaskGraph, TaskNode
|
||||
from air_runtime.modes.arc_mode import _export_task_graph_json
|
||||
|
||||
graph = TaskGraph()
|
||||
graph.add_node(TaskNode(id="T-001", status="DONE", task="ffmpeg 解码器", adr_refs=["ADR-0005"]))
|
||||
_export_task_graph_json(graph, arc_dir / "task-graph.json")
|
||||
|
||||
# 执行 ADR 失效
|
||||
result = handle_adr_invalidation(project_root, "ADR-0005")
|
||||
|
||||
# 验证 revert 结果
|
||||
assert "revertResults" in result
|
||||
# 应该找到一个包含 "T-001" 的 commit 并尝试 revert
|
||||
revert = result["revertResults"][0]
|
||||
assert revert["taskId"] == "T-001"
|
||||
# commit 应该被找到
|
||||
assert revert["commit"] is not None
|
||||
|
||||
print("✓ 真实 git 环境下 revert 测试通过")
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 50)
|
||||
print("P1-21 ADR 变更级联失效 功能测试")
|
||||
print("=" * 50)
|
||||
|
||||
tests = [
|
||||
("TaskNode.adr_refs", test_task_node_adr_refs),
|
||||
("INVALIDATED 状态", test_invalidated_status),
|
||||
("ADR→任务溯源链", test_tasks_by_adr),
|
||||
("级联失效", test_invalidate_by_adr),
|
||||
("调度冻结/解冻", test_dispatch_freeze_unfreeze),
|
||||
("CascadeReport", test_cascade_report),
|
||||
("PlanDelta.rollback_ref", test_plan_delta_rollback_ref),
|
||||
("AirRvr 清理检查", test_rvr_invalidated_cleanup_check),
|
||||
("Eng ADR 失效处理", test_eng_handle_adr_invalidation),
|
||||
("Eng 解冻调度", test_eng_unfreeze_after_replan),
|
||||
("apply_full_replace 保留状态", test_apply_full_replace_preserves_dispatched),
|
||||
("真实 git revert", test_git_revert_with_real_repo),
|
||||
("ffmpeg→gstreamer 场景", test_ffmpeg_to_gstreamer_scenario),
|
||||
]
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
for name, test_fn in tests:
|
||||
try:
|
||||
test_fn()
|
||||
passed += 1
|
||||
except Exception as e:
|
||||
print(f"✗ {name} 失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
failed += 1
|
||||
|
||||
print("=" * 50)
|
||||
print(f"测试结果: {passed} 通过, {failed} 失败")
|
||||
print("=" * 50)
|
||||
|
||||
return failed == 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
Reference in New Issue
Block a user