Files
lda-wf/tests/wf_transport_rpc_http/test_rpc_models.py
T

155 lines
4.8 KiB
Python

from __future__ import annotations
from typing import Any, cast
import pytest
from pydantic import ValidationError
from wf_core.models.steps import InputExpressionBinding
from wf_transport_rpc_http.models import (
CreateScheduleParams,
InspectCapabilityParams,
ListCapabilitiesParams,
ReadRunTraceParams,
SetStepInputBindingsParams,
SetWorkflowOutputBindingsParams,
StartRunParams,
TraceRangeParams,
UpdateScheduleParams,
)
def test_trace_range_params_converts_to_api_trace_range() -> None:
trace_range = TraceRangeParams(start=2, limit=5).to_api_trace_range()
assert trace_range.start == 2
assert trace_range.limit == 5
def test_trace_range_params_rejects_invalid_values() -> None:
with pytest.raises(ValidationError):
TraceRangeParams(start=-1, limit=5)
with pytest.raises(ValidationError):
TraceRangeParams(start=0, limit=0)
with pytest.raises(ValidationError):
TraceRangeParams(start=0, limit=101)
def test_capability_params_are_explicit_models() -> None:
listed = ListCapabilitiesParams(query="echo", source_id="wf.std", limit=10)
inspected = InspectCapabilityParams(qualified_name="wf.std.constant")
assert listed.query == "echo"
assert listed.source_id == "wf.std"
assert listed.limit == 10
assert inspected.qualified_name == "wf.std.constant"
def test_run_params_are_explicit_models() -> None:
started = StartRunParams(
deployment_id="demo.default",
workflow_input={"message": "hello"},
trace_range=TraceRangeParams(start=0, limit=3),
)
trace = ReadRunTraceParams(
run_id="run_demo",
trace_range=TraceRangeParams(start=0, limit=1),
)
assert started.deployment_id == "demo.default"
assert started.workflow_input["message"] == "hello"
assert started.trace_range is not None
assert trace.run_id == "run_demo"
assert trace.trace_range.limit == 1
def test_update_schedule_params_match_create_numeric_constraints() -> None:
valid = UpdateScheduleParams(
schedule_id="schedule",
expected_revision=1,
max_active_runs=2,
lateness_allowance_s=0,
max_steps=10,
)
assert valid.max_active_runs == 2
assert valid.lateness_allowance_s == 0
assert valid.max_steps == 10
with pytest.raises(ValidationError):
UpdateScheduleParams(
schedule_id="schedule", expected_revision=1, max_active_runs=0
)
with pytest.raises(ValidationError):
UpdateScheduleParams(
schedule_id="schedule", expected_revision=1, lateness_allowance_s=-1
)
with pytest.raises(ValidationError):
UpdateScheduleParams(schedule_id="schedule", expected_revision=1, max_steps=0)
with pytest.raises(ValidationError):
UpdateScheduleParams(
schedule_id="schedule", expected_revision=1, max_steps=True
)
with pytest.raises(ValidationError):
UpdateScheduleParams(
schedule_id="schedule", expected_revision=1, max_steps=cast(Any, "10")
)
def test_schedule_policy_params_reject_unknown_values() -> None:
with pytest.raises(ValidationError):
CreateScheduleParams(
schedule_id="schedule",
deployment_id="deployment",
trigger={"kind": "oneshot", "at": "2026-09-08T12:00:00+00:00"},
overlap=cast(Any, "queue"),
)
with pytest.raises(ValidationError):
UpdateScheduleParams(
schedule_id="schedule", expected_revision=1, misfire=cast(Any, "replay")
)
def test_step_input_params_accept_composite_bindings_but_workflow_output_does_not() -> (
None
):
params = SetStepInputBindingsParams.model_validate(
{
"workspace_id": "concat",
"revision": 1,
"step_id": "call",
"bindings": [
{
"target": "items",
"expression": {
"kind": "array",
"items": [
{"kind": "path", "path": "state.value"},
{"kind": "literal", "value": "!"},
],
},
}
],
}
)
assert isinstance(params.bindings[0], InputExpressionBinding)
with pytest.raises(ValidationError):
SetWorkflowOutputBindingsParams.model_validate(
{
"workspace_id": "concat",
"revision": 1,
"bindings": [
{
"target": "items",
"expression": {
"kind": "literal",
"value": "not-a-workflow-output-binding",
},
}
],
}
)