"""内联执行器测试。 重点是两件事:它**确实**同步跑完(违反 launch 不阻塞的约定),以及它对无法 支持的暂停能力**如实返回 False** 而不是假装成功。 """ from __future__ import annotations import asyncio from typing import Any from chongming_task.models import FailureKind from chongming_task.runtime.executors.base import ExecutionRequest from chongming_task.runtime.executors.inline import InlineExecutor def _request(target: Any, *args: Any) -> ExecutionRequest: return ExecutionRequest(task_id="t-inline", name="t-inline", target=target, args=args) def test_launch_runs_to_completion_before_returning() -> None: """这是它与 ``Executor`` 协议唯一的差异,也是它存在的意义。""" order: list[str] = [] def work(ctx: Any) -> str: del ctx order.append("task") return "done" handle = InlineExecutor().launch(_request(work)) order.append("after-launch") assert order == ["task", "after-launch"], "内联执行必须在 launch 返回前跑完" assert handle.running is False outcome = handle.wait() assert outcome is not None assert outcome.value == "done" def test_arguments_are_forwarded_after_the_context() -> None: def work(ctx: Any, left: int, right: int, *, scale: int = 1) -> int: del ctx return (left + right) * scale handle = InlineExecutor().launch( ExecutionRequest( task_id="t-inline-args", name="t-inline-args", target=work, args=(2, 3), kwargs={"scale": 10}, ) ) outcome = handle.wait() assert outcome is not None assert outcome.value == 50 def test_failure_is_reported_like_any_other_executor() -> None: def boom(ctx: Any) -> None: del ctx raise KeyError("missing") outcome = InlineExecutor().launch(_request(boom)).wait() assert outcome is not None assert not outcome.ok assert outcome.failure is not None assert outcome.failure.kind is FailureKind.EXCEPTION assert "KeyError" in outcome.failure.message assert outcome.failure.traceback is not None def test_pause_reports_false_because_it_cannot_be_honoured() -> None: """如实返回 False,调用方据此回滚为 RUNNING,而不是以为暂停成功了。""" handle = InlineExecutor().launch(_request(lambda ctx: "ok")) assert handle.pause(timeout=0.01) is False def test_resume_is_harmless_after_the_fact() -> None: handle = InlineExecutor().launch(_request(lambda ctx: "ok")) handle.resume() assert handle.running is False def test_stop_on_a_finished_inline_task_returns_its_real_outcome() -> None: """已结束的任务应当返回真实结果,而不是落进"兜底放弃"分支。""" handle = InlineExecutor().launch(_request(lambda ctx: 7)) outcome = handle.stop(graceful_timeout=1.0) assert outcome.ok assert outcome.value == 7 assert outcome.abandoned is False def test_context_is_injected() -> None: seen: dict[str, Any] = {} def work(ctx: Any) -> str: seen["task_id"] = ctx.task_id seen["token"] = ctx.token return "ok" handle = InlineExecutor().launch(_request(work)) assert seen["task_id"] == "t-inline" assert seen["token"] is handle.token def test_async_target_runs_to_completion_before_launch_returns() -> None: """``async def`` 任务在内联执行器下同样是同步跑完的(本线程起一个事件循环)。""" async def work(ctx: Any) -> int: await asyncio.sleep(0) return 42 handle = InlineExecutor().launch(_request(work)) assert handle.running is False outcome = handle.wait() assert outcome is not None assert outcome.ok assert outcome.value == 42