fix(ci): align runtime contract tests

This commit is contained in:
jxxghp
2026-08-25 18:21:32 +08:00
parent b914e8b6e4
commit fe06ea8c55
7 changed files with 69 additions and 61 deletions
@@ -6,7 +6,7 @@
"repeat": 3,
"targets": {
"app.startup.lifecycle": {
"loaded_app_module_count": 362,
"loaded_app_module_count": 364,
"max_ms": 904.069,
"median_ms": 898.164,
"min_ms": 896.39,
@@ -17,7 +17,7 @@
]
},
"app.factory": {
"loaded_app_module_count": 374,
"loaded_app_module_count": 376,
"max_ms": 923.165,
"median_ms": 921.768,
"min_ms": 921.249,
@@ -28,7 +28,7 @@
]
},
"app.main": {
"loaded_app_module_count": 376,
"loaded_app_module_count": 378,
"max_ms": 1069.392,
"median_ms": 1037.036,
"min_ms": 1027.603,
+10 -2
View File
@@ -6,10 +6,18 @@ from unittest.mock import AsyncMock, MagicMock
import pytest
from fastapi import FastAPI
from app.adapters.network import http as http_utils
from app.runtime.tasks import configure_task_registry, get_task_registry
from app.startup import lifecycle
from app.startup.initializers import modules as modules_initializer
from app.adapters.network import http as http_utils
from app.runtime.tasks import get_task_registry
@pytest.fixture(autouse=True)
def _isolate_task_registry():
"""生命周期用例结束后恢复未启动宿主时的默认任务登记器。"""
configure_task_registry(None)
yield
configure_task_registry(None)
def _assert_completed_once(mock: MagicMock) -> None:
+2 -2
View File
@@ -147,7 +147,7 @@ def test_alipan_download_writes_sanitized_filename(tmp_path: Path) -> None:
return_value=_noop_progress,
),
patch(
"app.modules.filemanager.storages.alipan.global_vars.is_transfer_stopped",
"app.modules.filemanager.storages.alipan.runtime_stop_state.consume_transfer_stop",
return_value=False,
),
patch("app.modules.filemanager.storages.alipan.RequestUtils") as request_utils,
@@ -187,7 +187,7 @@ def test_u115_download_writes_sanitized_filename(tmp_path: Path) -> None:
return_value=_noop_progress,
),
patch(
"app.modules.filemanager.storages.u115.global_vars.is_transfer_stopped",
"app.modules.filemanager.storages.u115.runtime_stop_state.consume_transfer_stop",
return_value=False,
),
):
+4 -4
View File
@@ -25,7 +25,7 @@ def test_fetch_downloads_updates_context_downloads(monkeypatch):
return [SimpleNamespace(path="/downloads/movie.mkv", progress=100)]
monkeypatch.setattr(fetch_downloads_module, "ActionChain", FakeActionChain)
monkeypatch.setattr(fetch_downloads_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(fetch_downloads_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
context = ActionContext(
downloads=[
@@ -65,7 +65,7 @@ def test_fetch_torrents_filters_special_season_zero(monkeypatch):
]
monkeypatch.setattr(fetch_torrents_module, "SearchChain", FakeSearchChain)
monkeypatch.setattr(fetch_torrents_module.global_vars, "is_workflow_stopped", lambda _workflow_id: False)
monkeypatch.setattr(fetch_torrents_module.runtime_stop_state, "is_workflow_stopped", lambda _workflow_id: False)
action = FetchTorrentsAction("fetch-torrents")
action.job_done = lambda *_args, **_kwargs: None
@@ -103,7 +103,7 @@ def test_scrape_file_keeps_workflow_action_context(monkeypatch):
monkeypatch.setattr(scrape_file_module, "StorageChain", FakeStorageChain)
monkeypatch.setattr(scrape_file_module, "MediaChain", FakeMediaChain)
monkeypatch.setattr(scrape_file_module, "ScrapingChain", FakeScrapingChain)
monkeypatch.setattr(scrape_file_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(scrape_file_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(ScrapeFileAction, "check_cache", lambda self, workflow_id, key: False)
monkeypatch.setattr(ScrapeFileAction, "save_cache", lambda self, workflow_id, data: None)
@@ -150,7 +150,7 @@ def test_scrape_file_does_not_cache_failed_music_scrape(monkeypatch):
monkeypatch.setattr(scrape_file_module, "MediaChain", FakeMediaChain)
monkeypatch.setattr(scrape_file_module, "ScrapingChain", FakeScrapingChain)
monkeypatch.setattr(
scrape_file_module.global_vars,
scrape_file_module.runtime_stop_state,
"is_workflow_stopped",
lambda workflow_id: False,
)
+45 -45
View File
@@ -146,12 +146,12 @@ def test_workflow_executor_preserves_trigger_context(monkeypatch):
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(
workflow_module.global_vars,
"workflow_resume",
workflow_module.runtime_stop_state,
"resume_workflow",
lambda _workflow_id: None,
)
monkeypatch.setattr(
workflow_module.global_vars,
workflow_module.runtime_stop_state,
"is_workflow_stopped",
lambda _workflow_id: False,
)
@@ -192,8 +192,8 @@ def test_workflow_executor_resumes_downstream_nodes(monkeypatch):
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -217,8 +217,8 @@ def test_workflow_executor_restores_structured_context(monkeypatch):
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -235,8 +235,8 @@ def test_workflow_executor_reports_incremental_progress(monkeypatch):
fake_manager = _FakeWorkflowManager(calls)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(
_build_workflow(),
@@ -275,8 +275,8 @@ def test_workflow_executor_skips_false_condition_branch(monkeypatch):
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -328,8 +328,8 @@ def test_workflow_executor_all_success_join_waits_parallel_branches(monkeypatch)
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -370,8 +370,8 @@ def test_workflow_executor_any_success_join_runs_after_available_branch(monkeypa
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -402,8 +402,8 @@ def test_workflow_executor_all_done_join_can_continue_after_failure(monkeypatch)
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -441,8 +441,8 @@ def test_workflow_executor_exclusive_branch_uses_first_matching_flow(monkeypatch
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -478,8 +478,8 @@ def test_workflow_executor_passes_declared_inputs(monkeypatch):
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -519,8 +519,8 @@ def test_workflow_executor_uses_contract_inputs(monkeypatch):
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -546,8 +546,8 @@ def test_workflow_executor_persists_structured_state(monkeypatch):
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(
_build_workflow(actions=[{"id": "A", "type": "FakeAction", "name": "动作A", "data": {}}], flows=[]),
@@ -579,8 +579,8 @@ def test_workflow_executor_restores_outputs_from_execution_state(monkeypatch):
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -606,8 +606,8 @@ def test_workflow_executor_keeps_execution_state_dict_for_non_json_leaf(monkeypa
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(
_build_workflow(actions=[{"id": "A", "type": "FakeAction", "name": "动作A", "data": {}}], flows=[]),
@@ -638,8 +638,8 @@ def test_workflow_chain_process_serializes_circular_context(monkeypatch):
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module, "get_chain_workflow_port", lambda: fake_oper)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
success, message = workflow_module.WorkflowChain.process(workflow_id=1)
@@ -686,8 +686,8 @@ def test_workflow_executor_concurrency_key_serializes_parallel_nodes(monkeypatch
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -724,8 +724,8 @@ def test_workflow_executor_filter_action_replaces_artifact_outputs(monkeypatch):
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -775,8 +775,8 @@ def test_workflow_executor_filter_action_replaces_with_empty_outputs(monkeypatch
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
executor = workflow_module.WorkflowExecutor(workflow)
executor.execute()
@@ -792,8 +792,8 @@ def test_workflow_executor_stop_is_not_success(monkeypatch):
fake_manager = _FakeWorkflowManager(calls)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: fake_manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.global_vars, "is_workflow_stopped", lambda workflow_id: True)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: True)
executor = workflow_module.WorkflowExecutor(_build_workflow())
executor.execute()
@@ -841,9 +841,9 @@ def test_workflow_manager_shutdown_retains_blocked_execution_for_retry(monkeypat
flows=[],
)
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: manager)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda _workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda _workflow_id: None)
monkeypatch.setattr(
workflow_module.global_vars,
workflow_module.runtime_stop_state,
"is_workflow_stopped",
lambda _workflow_id: False,
)
@@ -947,8 +947,8 @@ def test_workflow_chain_rejects_execution_before_persisting_running_state(monkey
raise AssertionError("拒绝准入时不得恢复工作流")
monkeypatch.setattr(
workflow_module.global_vars,
"workflow_resume",
workflow_module.runtime_stop_state,
"resume_workflow",
unexpected_resume,
)
@@ -979,7 +979,7 @@ def test_workflow_chain_releases_admitted_owner_when_start_fails(monkeypatch):
workflowoper = FailingWorkflowOper(_build_workflow())
monkeypatch.setattr(workflow_module, "get_workflow_manager", lambda: manager)
monkeypatch.setattr(workflow_module, "get_chain_workflow_port", lambda: workflowoper)
monkeypatch.setattr(workflow_module.global_vars, "workflow_resume", lambda _workflow_id: None)
monkeypatch.setattr(workflow_module.runtime_stop_state, "resume_workflow", lambda _workflow_id: None)
with pytest.raises(RuntimeError, match="start failed"):
workflow_module.WorkflowChain.process(workflow_id=1)
@@ -1059,7 +1059,7 @@ def test_workflow_manager_retries_action_until_success(monkeypatch):
manager = object.__new__(workflow_package.WorkFlowManager)
manager._actions = {"RetryAction": RetryAction}
monkeypatch.setattr(workflow_package.global_vars, "is_workflow_stopped", lambda workflow_id: False)
monkeypatch.setattr(workflow_package.runtime_stop_state, "is_workflow_stopped", lambda workflow_id: False)
result = manager.execute(
workflow_id=1,
+1 -1
View File
@@ -27,7 +27,7 @@ class FetchRssActionTest(unittest.TestCase):
]
with patch("app.workflow.actions.fetch_rss.RssHelper") as rss_helper, \
patch("app.workflow.actions.fetch_rss.global_vars.is_workflow_stopped", return_value=False):
patch("app.workflow.actions.fetch_rss.runtime_stop_state.is_workflow_stopped", return_value=False):
rss_helper.return_value.parse.return_value = rss_items
context = FetchRssAction("fetch-rss").execute(
+4 -4
View File
@@ -56,7 +56,7 @@ def test_fetch_rss_reads_proxy_from_chain_snapshot(monkeypatch):
"get_chain_runtime_config_snapshot",
lambda: _runtime_config(),
)
monkeypatch.setattr(fetch_rss_module.global_vars, "is_workflow_stopped", lambda _: False)
monkeypatch.setattr(fetch_rss_module.runtime_stop_state, "is_workflow_stopped", lambda _: False)
FetchRssAction("rss").execute(
workflow_id=1,
@@ -89,7 +89,7 @@ def test_scan_file_filters_extensions_from_chain_snapshot(monkeypatch):
"get_chain_runtime_config_snapshot",
lambda: _runtime_config(),
)
monkeypatch.setattr(scan_file_module.global_vars, "is_workflow_stopped", lambda _: False)
monkeypatch.setattr(scan_file_module.runtime_stop_state, "is_workflow_stopped", lambda _: False)
context = ScanFileAction("scan").execute(
workflow_id=1,
@@ -120,7 +120,7 @@ def test_add_subscribe_uses_superuser_from_chain_snapshot(monkeypatch):
"get_chain_runtime_config_snapshot",
lambda: _runtime_config(superuser="snapshot-owner"),
)
monkeypatch.setattr(add_subscribe_module.global_vars, "is_workflow_stopped", lambda _: False)
monkeypatch.setattr(add_subscribe_module.runtime_stop_state, "is_workflow_stopped", lambda _: False)
monkeypatch.setattr(
add_subscribe_module,
"get_chain_subscribe_port",
@@ -158,7 +158,7 @@ def test_fetch_medias_internal_api_uses_chain_snapshot(monkeypatch):
"get_chain_runtime_config_snapshot",
lambda: _runtime_config(),
)
monkeypatch.setattr(fetch_medias_module.global_vars, "is_workflow_stopped", lambda _: False)
monkeypatch.setattr(fetch_medias_module.runtime_stop_state, "is_workflow_stopped", lambda _: False)
action = FetchMediasAction("medias")
action._FetchMediasAction__inner_sources = [