chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from semantic_kernel.processes.kernel_process.kernel_process import KernelProcess
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_edge import KernelProcessEdge
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_state import KernelProcessState
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_step_info import KernelProcessStepInfo
|
||||
|
||||
|
||||
def test_initialization_with_valid_parameters():
|
||||
# Arrange
|
||||
state = MagicMock(spec=KernelProcessState)
|
||||
state.name = "valid_state"
|
||||
steps = [MagicMock(spec=KernelProcessStepInfo)]
|
||||
edges = {"step1": [MagicMock(spec=KernelProcessEdge)]}
|
||||
|
||||
# Act
|
||||
process = KernelProcess(state=state, steps=steps, edges=edges)
|
||||
|
||||
# Assert
|
||||
assert process.state == state
|
||||
assert process.steps == steps
|
||||
assert process.output_edges == edges
|
||||
|
||||
|
||||
def test_initialization_with_no_steps():
|
||||
# Arrange
|
||||
state = MagicMock(spec=KernelProcessState)
|
||||
state.name = "state_without_steps"
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(ValueError, match="steps cannot be None"):
|
||||
KernelProcess(state=state, steps=[])
|
||||
|
||||
|
||||
def test_initialization_with_no_state():
|
||||
# Arrange
|
||||
steps = [MagicMock(spec=KernelProcessStepInfo)]
|
||||
edges = {"step1": [MagicMock(spec=KernelProcessEdge)]}
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(ValueError, match="state cannot be None"):
|
||||
KernelProcess(state=None, steps=steps, edges=edges)
|
||||
|
||||
|
||||
def test_initialization_with_no_state_name():
|
||||
# Arrange
|
||||
state = MagicMock(spec=KernelProcessState)
|
||||
state.name = None # Invalid state name
|
||||
steps = [MagicMock(spec=KernelProcessStepInfo)]
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(ValueError, match="state.Name cannot be None"):
|
||||
KernelProcess(state=state, steps=steps)
|
||||
@@ -0,0 +1,53 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_edge import KernelProcessEdge
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_function_target import KernelProcessFunctionTarget
|
||||
|
||||
|
||||
def test_initialization():
|
||||
"""Test initialization of KernelProcessEdge with valid input."""
|
||||
source_step_id = "step_1"
|
||||
output_target = KernelProcessFunctionTarget(
|
||||
step_id="step_2", function_name="process_data", parameter_name="input_data", target_event_id="event_1"
|
||||
)
|
||||
edge = KernelProcessEdge(source_step_id=source_step_id, output_target=output_target)
|
||||
|
||||
assert edge.source_step_id == source_step_id
|
||||
assert edge.output_target == output_target
|
||||
|
||||
|
||||
def test_initialization_with_none_parameter_name():
|
||||
"""Test KernelProcessEdge initialization with a target having None as parameter_name."""
|
||||
source_step_id = "step_1"
|
||||
output_target = KernelProcessFunctionTarget(
|
||||
step_id="step_2", function_name="process_data", parameter_name=None, target_event_id="event_1"
|
||||
)
|
||||
edge = KernelProcessEdge(source_step_id=source_step_id, output_target=output_target)
|
||||
|
||||
assert edge.source_step_id == source_step_id
|
||||
assert edge.output_target.parameter_name is None
|
||||
|
||||
|
||||
def test_initialization_with_none_target_event_id():
|
||||
"""Test KernelProcessEdge initialization with a target having None as target_event_id."""
|
||||
source_step_id = "step_1"
|
||||
output_target = KernelProcessFunctionTarget(
|
||||
step_id="step_2", function_name="process_data", parameter_name="input_data", target_event_id=None
|
||||
)
|
||||
edge = KernelProcessEdge(source_step_id=source_step_id, output_target=output_target)
|
||||
|
||||
assert edge.source_step_id == source_step_id
|
||||
assert edge.output_target.target_event_id is None
|
||||
|
||||
|
||||
def test_initialization_with_empty_strings():
|
||||
"""Test KernelProcessEdge initialization with empty strings for step_id and function_name."""
|
||||
source_step_id = ""
|
||||
output_target = KernelProcessFunctionTarget(step_id="", function_name="", parameter_name="", target_event_id="")
|
||||
edge = KernelProcessEdge(source_step_id=source_step_id, output_target=output_target)
|
||||
|
||||
assert edge.source_step_id == ""
|
||||
assert edge.output_target.step_id == ""
|
||||
assert edge.output_target.function_name == ""
|
||||
assert edge.output_target.parameter_name == ""
|
||||
assert edge.output_target.target_event_id == ""
|
||||
@@ -0,0 +1,62 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import pytest
|
||||
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_event import (
|
||||
KernelProcessEvent,
|
||||
KernelProcessEventVisibility,
|
||||
)
|
||||
|
||||
|
||||
def test_initialization():
|
||||
# Arrange
|
||||
event_id = "event_001"
|
||||
event_data = {"key": "value"}
|
||||
|
||||
# Act
|
||||
event = KernelProcessEvent(id=event_id, data=event_data)
|
||||
|
||||
# Assert
|
||||
assert event.id == event_id
|
||||
assert event.data == event_data
|
||||
assert event.visibility == KernelProcessEventVisibility.Internal
|
||||
|
||||
|
||||
def test_initialization_with_visibility():
|
||||
# Arrange
|
||||
event_id = "event_002"
|
||||
event_data = [1, 2, 3]
|
||||
visibility = KernelProcessEventVisibility.Public
|
||||
|
||||
# Act
|
||||
event = KernelProcessEvent(id=event_id, data=event_data, visibility=visibility)
|
||||
|
||||
# Assert
|
||||
assert event.id == event_id
|
||||
assert event.data == event_data
|
||||
assert event.visibility == KernelProcessEventVisibility.Public
|
||||
|
||||
|
||||
def test_invalid_visibility():
|
||||
# Arrange
|
||||
event_id = "event_003"
|
||||
event_data = "sample data"
|
||||
invalid_visibility = "Hidden"
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(ValueError):
|
||||
KernelProcessEvent(id=event_id, data=event_data, visibility=invalid_visibility)
|
||||
|
||||
|
||||
def test_none_data_initialization():
|
||||
# Arrange
|
||||
event_id = "event_004"
|
||||
event_data = None
|
||||
|
||||
# Act
|
||||
event = KernelProcessEvent(id=event_id, data=event_data)
|
||||
|
||||
# Assert
|
||||
assert event.id == event_id
|
||||
assert event.data is None
|
||||
assert event.visibility == KernelProcessEventVisibility.Internal
|
||||
@@ -0,0 +1,66 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_function_target import KernelProcessFunctionTarget
|
||||
|
||||
|
||||
def test_initialization():
|
||||
# Arrange
|
||||
step_id = "step_001"
|
||||
function_name = "execute_task"
|
||||
parameter_name = "input_data"
|
||||
target_event_id = "event_001"
|
||||
|
||||
# Act
|
||||
target = KernelProcessFunctionTarget(
|
||||
step_id=step_id, function_name=function_name, parameter_name=parameter_name, target_event_id=target_event_id
|
||||
)
|
||||
|
||||
# Assert
|
||||
assert target.step_id == step_id
|
||||
assert target.function_name == function_name
|
||||
assert target.parameter_name == parameter_name
|
||||
assert target.target_event_id == target_event_id
|
||||
|
||||
|
||||
def test_initialization_with_defaults():
|
||||
# Arrange
|
||||
step_id = "step_002"
|
||||
function_name = "process_data"
|
||||
|
||||
# Act
|
||||
target = KernelProcessFunctionTarget(step_id=step_id, function_name=function_name)
|
||||
|
||||
# Assert
|
||||
assert target.step_id == step_id
|
||||
assert target.function_name == function_name
|
||||
assert target.parameter_name is None
|
||||
assert target.target_event_id is None
|
||||
|
||||
|
||||
def test_invalid_initialization():
|
||||
# Arrange
|
||||
step_id = 12345 # Invalid type
|
||||
function_name = "compute"
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(ValidationError):
|
||||
KernelProcessFunctionTarget(step_id=step_id, function_name=function_name)
|
||||
|
||||
|
||||
def test_partial_initialization_with_parameter_name():
|
||||
# Arrange
|
||||
step_id = "step_003"
|
||||
function_name = "calculate"
|
||||
parameter_name = "value"
|
||||
|
||||
# Act
|
||||
target = KernelProcessFunctionTarget(step_id=step_id, function_name=function_name, parameter_name=parameter_name)
|
||||
|
||||
# Assert
|
||||
assert target.step_id == step_id
|
||||
assert target.function_name == function_name
|
||||
assert target.parameter_name == parameter_name
|
||||
assert target.target_event_id is None
|
||||
@@ -0,0 +1,36 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_message_channel import KernelProcessMessageChannel
|
||||
from semantic_kernel.processes.local_runtime.local_event import KernelProcessEvent
|
||||
|
||||
|
||||
class MockKernelProcessMessageChannel(KernelProcessMessageChannel):
|
||||
async def emit_event(self, process_event: KernelProcessEvent) -> None:
|
||||
pass
|
||||
|
||||
|
||||
async def test_emit_event():
|
||||
# Arrange
|
||||
event = KernelProcessEvent(id="event_001", data={"key": "value"})
|
||||
channel = MockKernelProcessMessageChannel()
|
||||
channel.emit_event = AsyncMock()
|
||||
|
||||
# Act
|
||||
await channel.emit_event(event)
|
||||
|
||||
# Assert
|
||||
channel.emit_event.assert_awaited_once_with(event)
|
||||
|
||||
|
||||
async def test_emit_event_with_no_event():
|
||||
# Arrange
|
||||
channel = MockKernelProcessMessageChannel()
|
||||
channel.emit_event = AsyncMock()
|
||||
|
||||
# Act
|
||||
await channel.emit_event(None)
|
||||
|
||||
# Assert
|
||||
channel.emit_event.assert_awaited_once_with(None)
|
||||
@@ -0,0 +1,60 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_state import KernelProcessState
|
||||
|
||||
|
||||
def test_initialization_with_name_and_id():
|
||||
# Arrange
|
||||
name = "test_process"
|
||||
process_id = "1234"
|
||||
version = "1.0"
|
||||
|
||||
# Act
|
||||
state = KernelProcessState(name=name, version=version, id=process_id)
|
||||
|
||||
# Assert
|
||||
assert state.name == name
|
||||
assert state.id == process_id
|
||||
assert state.state is None
|
||||
assert state.version == version
|
||||
|
||||
|
||||
def test_initialization_with_name_only():
|
||||
# Arrange
|
||||
name = "test_process_without_id"
|
||||
version = "1.0"
|
||||
|
||||
# Act
|
||||
state = KernelProcessState(name=name, version=version)
|
||||
|
||||
# Assert
|
||||
assert state.name == name
|
||||
assert state.id is None
|
||||
assert state.state is None
|
||||
assert state.version == version
|
||||
|
||||
|
||||
def test_setting_state_value():
|
||||
# Arrange
|
||||
name = "test_process"
|
||||
state_value = {"key": "value"}
|
||||
|
||||
# Act
|
||||
state = KernelProcessState(name=name, version="1.0")
|
||||
state.state = state_value
|
||||
|
||||
# Assert
|
||||
assert state.state == state_value
|
||||
assert state.version == "1.0"
|
||||
|
||||
|
||||
def test_initialization_with_invalid_name():
|
||||
# Arrange
|
||||
name = 12345 # Invalid type for name
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(ValidationError):
|
||||
KernelProcessState(name=name, version="1.0")
|
||||
@@ -0,0 +1,86 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_step_state_metadata import (
|
||||
KernelProcessStateMetadata,
|
||||
KernelProcessStepStateMetadata,
|
||||
)
|
||||
|
||||
|
||||
def test_load_from_file_success(tmp_path: Path):
|
||||
state_data = {"$type": "Process", "id": "123", "name": "TestProcess", "versionInfo": "v1", "stepsState": {}}
|
||||
file_path = tmp_path / "test_state.json"
|
||||
file_path.write_text(json.dumps(state_data), encoding="utf-8")
|
||||
|
||||
result = KernelProcessStateMetadata.load_from_file(
|
||||
json_filename="test_state.json",
|
||||
directory=tmp_path,
|
||||
)
|
||||
|
||||
assert result is not None
|
||||
assert result.id == "123"
|
||||
assert result.name == "TestProcess"
|
||||
assert result.version_info == "v1"
|
||||
assert result.steps_state == {}
|
||||
|
||||
|
||||
def test_load_from_file_file_not_found(tmp_path: Path):
|
||||
result = KernelProcessStateMetadata.load_from_file(
|
||||
json_filename="non_existing.json",
|
||||
directory=tmp_path,
|
||||
)
|
||||
assert result is None
|
||||
|
||||
|
||||
def test_load_from_file_invalid_json(tmp_path: Path):
|
||||
file_path = tmp_path / "invalid.json"
|
||||
file_path.write_text("not a valid json content", encoding="utf-8")
|
||||
|
||||
result = KernelProcessStateMetadata.load_from_file(
|
||||
json_filename="invalid.json",
|
||||
directory=tmp_path,
|
||||
)
|
||||
assert result is None
|
||||
|
||||
|
||||
async def test_load_from_file_with_non_utf8_encoding(tmp_path: Path):
|
||||
state_data = {
|
||||
"$type": "Process",
|
||||
"id": "456",
|
||||
"name": "CaféProcess",
|
||||
"versionInfo": "v2",
|
||||
"stepsState": {},
|
||||
}
|
||||
file_path = tmp_path / "test_state_utf16.json"
|
||||
file_path.write_text(json.dumps(state_data), encoding="utf-16")
|
||||
|
||||
# Try to read with wrong encoding (utf-8), we expect a parse error -> None
|
||||
result_wrong_encoding = KernelProcessStateMetadata.load_from_file(
|
||||
json_filename="test_state_utf16.json",
|
||||
directory=tmp_path,
|
||||
encoding="utf-8",
|
||||
)
|
||||
assert result_wrong_encoding is None
|
||||
|
||||
# Now read with correct encoding (utf-16), we expect a success
|
||||
result_correct_encoding = KernelProcessStateMetadata.load_from_file(
|
||||
json_filename="test_state_utf16.json",
|
||||
directory=tmp_path,
|
||||
encoding="utf-16",
|
||||
)
|
||||
assert result_correct_encoding is not None
|
||||
assert result_correct_encoding.name == "CaféProcess"
|
||||
|
||||
|
||||
def test_create_step_state_metadata():
|
||||
step_state = KernelProcessStepStateMetadata(
|
||||
type_="Step", id="step123", name="TestStep", version_info="v1", state={"foo": "bar"}
|
||||
)
|
||||
|
||||
assert step_state.type_ == "Step"
|
||||
assert step_state.id == "step123"
|
||||
assert step_state.name == "TestStep"
|
||||
assert step_state.version_info == "v1"
|
||||
assert step_state.state == {"foo": "bar"}
|
||||
@@ -0,0 +1,52 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
|
||||
from semantic_kernel.exceptions.process_exceptions import ProcessEventUndefinedException
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_message_channel import KernelProcessMessageChannel
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_step_context import KernelProcessStepContext
|
||||
from semantic_kernel.processes.local_runtime.local_event import KernelProcessEvent
|
||||
|
||||
|
||||
class MockKernelProcessMessageChannel(KernelProcessMessageChannel):
|
||||
async def emit_event(self, process_event: KernelProcessEvent) -> None:
|
||||
pass
|
||||
|
||||
|
||||
async def test_initialization():
|
||||
# Arrange
|
||||
channel = MockKernelProcessMessageChannel()
|
||||
|
||||
# Act
|
||||
context = KernelProcessStepContext(channel=channel)
|
||||
|
||||
# Assert
|
||||
assert context.step_message_channel == channel
|
||||
|
||||
|
||||
async def test_emit_event():
|
||||
# Arrange
|
||||
channel = MockKernelProcessMessageChannel()
|
||||
channel.emit_event = AsyncMock()
|
||||
context = KernelProcessStepContext(channel=channel)
|
||||
event = KernelProcessEvent(id="event_001", data={"key": "value"})
|
||||
|
||||
# Act
|
||||
await context.emit_event(event)
|
||||
|
||||
# Assert
|
||||
channel.emit_event.assert_called_once_with(event)
|
||||
|
||||
|
||||
async def test_emit_event_with_invalid_event():
|
||||
# Arrange
|
||||
channel = MockKernelProcessMessageChannel()
|
||||
channel.emit_event = AsyncMock()
|
||||
context = KernelProcessStepContext(channel=channel)
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(ProcessEventUndefinedException):
|
||||
await context.emit_event(None)
|
||||
@@ -0,0 +1,68 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_edge import KernelProcessEdge
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_step_info import KernelProcessStepInfo
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_step_state import KernelProcessStepState
|
||||
|
||||
|
||||
class MockStepType:
|
||||
"""A mock class to simulate a step type."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def test_initialization():
|
||||
# Arrange
|
||||
inner_step_type = MockStepType
|
||||
state = MagicMock(spec=KernelProcessStepState)
|
||||
edge = MagicMock(spec=KernelProcessEdge)
|
||||
edges = {"output": [edge]}
|
||||
|
||||
# Act
|
||||
step_info = KernelProcessStepInfo(inner_step_type=inner_step_type, state=state, output_edges=edges)
|
||||
|
||||
# Assert
|
||||
assert step_info.inner_step_type == inner_step_type
|
||||
assert step_info.state == state
|
||||
assert step_info.output_edges == edges
|
||||
|
||||
|
||||
def test_initialization_with_missing_arguments():
|
||||
# Arrange
|
||||
inner_step_type = MockStepType
|
||||
state = MagicMock(spec=KernelProcessStepState)
|
||||
edge = MagicMock(spec=KernelProcessEdge)
|
||||
edges = {"output": [edge]}
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(ValidationError):
|
||||
KernelProcessStepInfo(inner_step_type=None, state=state, output_edges=edges)
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
KernelProcessStepInfo(inner_step_type=inner_step_type, state=None, output_edges=edges)
|
||||
|
||||
with pytest.raises(ValidationError):
|
||||
KernelProcessStepInfo(inner_step_type=inner_step_type, state=state, output_edges=None)
|
||||
|
||||
|
||||
def test_edges_property():
|
||||
# Arrange
|
||||
inner_step_type = MockStepType
|
||||
state = MagicMock(spec=KernelProcessStepState)
|
||||
edge_1 = MagicMock(spec=KernelProcessEdge)
|
||||
edge_2 = MagicMock(spec=KernelProcessEdge)
|
||||
edges = {"output": [edge_1, edge_2]}
|
||||
|
||||
# Act
|
||||
step_info = KernelProcessStepInfo(inner_step_type=inner_step_type, state=state, output_edges=edges)
|
||||
copied_edges = step_info.edges
|
||||
|
||||
# Assert
|
||||
assert copied_edges == edges
|
||||
assert copied_edges is not edges
|
||||
assert copied_edges["output"] is not edges["output"]
|
||||
@@ -0,0 +1,55 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from semantic_kernel.processes.kernel_process.kernel_process_step_state import KernelProcessStepState
|
||||
|
||||
|
||||
def test_initialization_with_name_and_id():
|
||||
# Arrange
|
||||
name = "step_state"
|
||||
step_id = "5678"
|
||||
|
||||
# Act
|
||||
step_state = KernelProcessStepState(name=name, id=step_id, version="1.0")
|
||||
|
||||
# Assert
|
||||
assert step_state.name == name
|
||||
assert step_state.id == step_id
|
||||
assert step_state.state is None
|
||||
|
||||
|
||||
def test_initialization_with_name_only():
|
||||
# Arrange
|
||||
name = "step_state_without_id"
|
||||
|
||||
# Act
|
||||
step_state = KernelProcessStepState(name=name, version="1.0")
|
||||
|
||||
# Assert
|
||||
assert step_state.name == name
|
||||
assert step_state.id is None
|
||||
assert step_state.state is None
|
||||
|
||||
|
||||
def test_setting_step_state_value():
|
||||
# Arrange
|
||||
name = "step_state"
|
||||
state_value = {"status": "in_progress"}
|
||||
|
||||
# Act
|
||||
step_state = KernelProcessStepState(name=name, version="1.0")
|
||||
step_state.state = state_value
|
||||
|
||||
# Assert
|
||||
assert step_state.state == state_value
|
||||
|
||||
|
||||
def test_initialization_with_invalid_name():
|
||||
# Arrange
|
||||
name = 12345 # Invalid type for name
|
||||
|
||||
# Act & Assert
|
||||
with pytest.raises(ValidationError):
|
||||
KernelProcessStepState(name=name)
|
||||
Reference in New Issue
Block a user