chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:25 +08:00
commit db620d33df
5151 changed files with 925932 additions and 0 deletions
@@ -0,0 +1,189 @@
# Copyright (c) Microsoft. All rights reserved.
"""Unit tests for plan_workflow_registration.
Verifies the host-agnostic decision of which executors become durable entities
(agent executors) versus durable activities (everything else), and that agent
executors are carried whole so each host can register entities under the
executor id the orchestrator dispatches to.
"""
from unittest.mock import Mock
import pytest
from agent_framework import AgentExecutor, Executor, WorkflowExecutor
from agent_framework_durabletask import (
WorkflowRegistrationPlan,
collect_hosted_workflows,
plan_workflow_registration,
)
def _agent_executor(executor_id: str, agent_name: str) -> Mock:
agent = Mock()
agent.name = agent_name
executor = Mock(spec=AgentExecutor)
executor.id = executor_id
executor.agent = agent
return executor
def _activity_executor(executor_id: str) -> Mock:
executor = Mock(spec=Executor)
executor.id = executor_id
return executor
def _subworkflow_executor(executor_id: str, inner_workflow: Mock) -> Mock:
executor = Mock(spec=WorkflowExecutor)
executor.id = executor_id
executor.workflow = inner_workflow
return executor
def _workflow(name: str, executors: dict[str, Mock]) -> Mock:
workflow = Mock()
workflow.name = name
workflow.executors = executors
return workflow
class TestPlanWorkflowRegistration:
"""Test classification of workflow executors into durable primitives."""
def test_agent_executor_classified_as_entity(self) -> None:
"""An AgentExecutor is carried whole in agent_executors."""
agent_exec = _agent_executor("reviewer-node", "Reviewer")
workflow = Mock()
workflow.executors = {"reviewer-node": agent_exec}
plan = plan_workflow_registration(workflow)
assert plan.agent_executors == [agent_exec]
assert plan.activity_executors == []
def test_non_agent_executor_classified_as_activity(self) -> None:
"""A plain Executor is classified as an activity."""
activity_exec = _activity_executor("router-node")
workflow = Mock()
workflow.executors = {"router-node": activity_exec}
plan = plan_workflow_registration(workflow)
assert plan.agent_executors == []
assert plan.activity_executors == [activity_exec]
def test_mixed_executors_are_partitioned(self) -> None:
"""Agent and non-agent executors are split into the correct buckets."""
agent_exec = _agent_executor("agent-node", "Agent")
activity_exec = _activity_executor("activity-node")
workflow = Mock()
workflow.executors = {"agent-node": agent_exec, "activity-node": activity_exec}
plan = plan_workflow_registration(workflow)
assert plan.agent_executors == [agent_exec]
assert plan.activity_executors == [activity_exec]
def test_agent_executor_id_is_preserved_when_distinct_from_name(self) -> None:
"""The plan keeps the executor (and its id), not just the bare agent.
This is the core of the identity fix: dispatch targets the executor id,
so registration must be able to use the id even when it differs from
``agent.name``.
"""
agent_exec = _agent_executor("custom-executor-id", "ReusedAgentName")
workflow = Mock()
workflow.executors = {"custom-executor-id": agent_exec}
plan = plan_workflow_registration(workflow)
assert plan.agent_executors[0].id == "custom-executor-id"
assert plan.agent_executors[0].agent.name == "ReusedAgentName"
def test_returns_workflow_registration_plan(self) -> None:
"""The return value is a WorkflowRegistrationPlan."""
workflow = Mock()
workflow.executors = {}
plan = plan_workflow_registration(workflow)
assert isinstance(plan, WorkflowRegistrationPlan)
assert plan.agent_executors == []
assert plan.activity_executors == []
def test_subworkflow_executor_classified_separately(self) -> None:
"""A WorkflowExecutor goes to subworkflow_executors, not activities."""
inner = _workflow("inner", {})
sub_exec = _subworkflow_executor("sub-node", inner)
activity_exec = _activity_executor("router-node")
workflow = _workflow("outer", {"sub-node": sub_exec, "router-node": activity_exec})
plan = plan_workflow_registration(workflow)
assert plan.subworkflow_executors == [sub_exec]
assert plan.activity_executors == [activity_exec]
assert plan.agent_executors == []
class TestCollectHostedWorkflows:
"""Test the recursive walk over nested sub-workflows."""
def test_single_workflow_yields_itself(self) -> None:
workflow = _workflow("solo", {"node": _activity_executor("node")})
assert [w.name for w in collect_hosted_workflows(workflow)] == ["solo"]
def test_yields_nested_subworkflows_parent_first(self) -> None:
inner = _workflow("inner", {"leaf": _activity_executor("leaf")})
sub_exec = _subworkflow_executor("sub", inner)
outer = _workflow("outer", {"sub": sub_exec})
assert [w.name for w in collect_hosted_workflows(outer)] == ["outer", "inner"]
def test_dedupes_shared_subworkflow_by_name(self) -> None:
"""A sub-workflow reused by two nodes is yielded once."""
inner = _workflow("shared", {"leaf": _activity_executor("leaf")})
sub_a = _subworkflow_executor("a", inner)
sub_b = _subworkflow_executor("b", inner)
outer = _workflow("outer", {"a": sub_a, "b": sub_b})
assert [w.name for w in collect_hosted_workflows(outer)] == ["outer", "shared"]
def test_walks_multiple_levels(self) -> None:
leaf = _workflow("leaf_wf", {"x": _activity_executor("x")})
mid = _workflow("mid_wf", {"l": _subworkflow_executor("l", leaf)})
top = _workflow("top_wf", {"m": _subworkflow_executor("m", mid)})
assert [w.name for w in collect_hosted_workflows(top)] == ["top_wf", "mid_wf", "leaf_wf"]
def test_rejects_two_different_workflows_sharing_a_name(self) -> None:
"""Two different sub-workflow instances with the same name collide and raise."""
inner_a = _workflow("shared", {"x": _activity_executor("x")})
inner_b = _workflow("shared", {"y": _activity_executor("y")}) # different instance, same name
outer = _workflow("outer", {"a": _subworkflow_executor("a", inner_a), "b": _subworkflow_executor("b", inner_b)})
with pytest.raises(ValueError, match="collides"):
list(collect_hosted_workflows(outer))
def test_rejects_case_insensitive_name_collision(self) -> None:
"""Two different instances whose names differ only by case collide and raise.
The route ownership guard compares the durable orchestration name
case-insensitively, so case-only name variants must be rejected here or one
workflow's routes could operate on the other's instances.
"""
inner_a = _workflow("shared", {"x": _activity_executor("x")})
inner_b = _workflow("Shared", {"y": _activity_executor("y")}) # case-only difference
outer = _workflow("outer", {"a": _subworkflow_executor("a", inner_a), "b": _subworkflow_executor("b", inner_b)})
with pytest.raises(ValueError, match="collides"):
list(collect_hosted_workflows(outer))
def test_same_instance_reused_is_deduped_not_rejected(self) -> None:
"""The same sub-workflow instance referenced by two nodes (fan-out) is yielded once."""
inner = _workflow("shared", {"x": _activity_executor("x")})
outer = _workflow("outer", {"a": _subworkflow_executor("a", inner), "b": _subworkflow_executor("b", inner)})
assert [w.name for w in collect_hosted_workflows(outer)] == ["outer", "shared"]