Files
lda-wf/tests/wf_server/test_local_static_server.py
T

213 lines
7.0 KiB
Python

from __future__ import annotations
import ast
from pathlib import Path
from wf_api.models import RawWorkflowPlan
from wf_core import END
from wf_server import build_local_static_workflow_server
def _constant_plan() -> RawWorkflowPlan:
return RawWorkflowPlan.model_validate(
{
"name": "server_constant",
"input_schema": {"type": "object", "properties": {}},
"state_schema": {
"type": "object",
"properties": {
"result": {"type": "string", "reducer": "wf.std.replace"}
},
},
"output_schema": {
"type": "object",
"properties": {"result": {"type": "string"}},
"required": ["result"],
},
"outcomes": ["ok"],
"start": "constant",
"nodes": [
{
"id": "constant",
"type": "node",
"node": "wf.std.constant",
"input": [
{
"value": "hello from server",
"target": {"root": "local", "parts": ["value"]},
}
],
"output": [
{
"source": {"root": "local", "parts": ["value"]},
"target": {"root": "state", "parts": ["result"]},
}
],
}
],
"edges": [{"from": "constant", "outcome": "ok", "to": END}],
"output": [
{
"path": {"root": "state", "parts": ["result"]},
"target": {"root": "local", "parts": ["result"]},
}
],
}
)
def test_wf_server_context_imports_no_wfmcp_service() -> None:
path = Path("src/wf_server/context.py")
tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
violations: list[str] = []
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom) and node.module is not None:
if node.module == "wf_mcp.broker" or node.module.endswith(".core"):
violations.append(f"{node.lineno}: from {node.module} import ...")
elif isinstance(node, ast.Import):
for alias in node.names:
if alias.name in {"wf_mcp.broker", "wf_mcp.broker.service.core"}:
violations.append(f"{node.lineno}: import {alias.name}")
assert violations == []
async def test_local_static_server_runs_deployment_and_persists_run(tmp_path) -> None:
server = build_local_static_workflow_server(tmp_path / "store")
api = server.api
plan = _constant_plan()
artifact_result = await api.create_artifact_from_plan(
artifact_id="server_constant",
version=1,
title="Server Constant",
plan=plan,
outcomes=["ok"],
source_bindings={},
)
deployment_result = await api.save_deployment(
{
"id": "server_constant.default",
"artifact_id": "server_constant",
"artifact_version": 1,
"bindings": {},
}
)
run_result = await api.run_deployment(
deployment_id="server_constant.default",
workflow_input={},
)
assert artifact_result["artifact_id"] == "server_constant"
assert deployment_result["deployment_id"] == "server_constant.default"
assert run_result["status"] == "completed"
output = run_result["output"]
assert output is not None
assert output["result"] == "hello from server"
run_id = run_result["run_id"]
assert isinstance(run_id, str)
assert (
server.stores.run_store.get_run(run_id).id == run_id
)
async def test_local_static_server_inspects_and_reads_bounded_trace(tmp_path) -> None:
server = build_local_static_workflow_server(tmp_path / "store")
api = server.api
plan = _constant_plan()
await api.create_artifact_from_plan(
artifact_id="server_trace",
version=1,
title="Server Trace",
plan=plan.model_copy(update={"name": "server_trace"}),
outcomes=["ok"],
source_bindings={},
)
await api.save_deployment(
{
"id": "server_trace.default",
"artifact_id": "server_trace",
"artifact_version": 1,
"bindings": {},
}
)
run_result = await api.run_deployment(
deployment_id="server_trace.default", workflow_input={}
)
run_id = run_result["run_id"]
assert isinstance(run_id, str)
summary = await api.inspect_run(run_id=run_id)
trace = await api.read_run_trace(
run_id=run_id,
trace_range=server.trace_range(start=0, limit=1),
)
assert "trace" not in summary
assert summary["trace_count"] >= 1
assert trace["trace_start"] == 0
assert trace["trace_limit"] == 1
assert len(trace["trace"]) == 1
async def test_local_static_wf_std_deployment_runs_without_source_binding(
tmp_path,
) -> None:
server = build_local_static_workflow_server(tmp_path / "store")
api = server.api
plan = _constant_plan()
artifact_result = await api.create_artifact_from_plan(
artifact_id="server_constant_no_binding",
version=1,
title="Server Constant No Binding",
plan=plan.model_copy(update={"name": "server_constant_no_binding"}),
outcomes=["ok"],
source_bindings={},
)
deployment_result = await api.save_deployment(
{
"id": "server_constant_no_binding.default",
"artifact_id": "server_constant_no_binding",
"artifact_version": 1,
"bindings": {},
}
)
run_result = await api.run_deployment(
deployment_id="server_constant_no_binding.default",
workflow_input={},
)
assert artifact_result["artifact_id"] == "server_constant_no_binding"
assert deployment_result["deployment_id"] == "server_constant_no_binding.default"
assert run_result["status"] == "completed"
output = run_result["output"]
assert output is not None
assert output["result"] == "hello from server"
def test_local_static_server_has_no_source_registry_admin(tmp_path) -> None:
server = build_local_static_workflow_server(tmp_path / "store")
assert server.source_registry_admin is None
def test_local_static_builtins_are_platform_sources(tmp_path) -> None:
server = build_local_static_workflow_server(tmp_path)
wf_std = server.context.specs.capability_sources["wf.std"]
assert wf_std.policy.platform is True
assert wf_std.policy.binding_required is False
def test_local_static_server_exposes_wf_source_platform_source(tmp_path) -> None:
server = build_local_static_workflow_server(tmp_path)
source = server.context.specs.capability_sources["wf.source"]
assert source.policy.platform is True
assert source.policy.binding_required is False
assert "wf.source.read_resource" in source.capabilities.node_specs