mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Port Agent Runtime abstractions / inprocess runtime (#149)
This commit is contained in:
+119
@@ -0,0 +1,119 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Extensions.AI.Agents.Runtime.Abstractions.Tests;
|
||||
|
||||
public class AgentIdTests()
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
[InlineData("invalid\u007Fkey")] // DEL character (127) is outside ASCII 32-126 range
|
||||
[InlineData("invalid\u0000key")] // NULL character is outside ASCII 32-126 range
|
||||
[InlineData("invalid\u0010key")] // Control character is outside ASCII 32-126 range
|
||||
[InlineData("InvalidKey💀")] // Control character is outside ASCII 32-126 range
|
||||
public void AgentIdShouldThrowArgumentExceptionWithInvalidKey(string? invalidKey)
|
||||
{
|
||||
// Act & Assert
|
||||
ArgumentException exception = Assert.Throws<ArgumentException>(() => new AgentId("validType", invalidKey!));
|
||||
Assert.Contains("Invalid AgentId key", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldInitializeCorrectlyTest()
|
||||
{
|
||||
AgentId agentId = new("TestType", "TestKey");
|
||||
|
||||
Assert.Equal("TestType", agentId.Type);
|
||||
Assert.Equal("TestKey", agentId.Key);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldConvertFromTupleTest()
|
||||
{
|
||||
(string, string) agentTuple = ("TupleType", "TupleKey");
|
||||
AgentId agentId = new(agentTuple);
|
||||
|
||||
Assert.Equal("TupleType", agentId.Type);
|
||||
Assert.Equal("TupleKey", agentId.Key);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldConvertFromAgentType()
|
||||
{
|
||||
AgentType agentType = "TestType";
|
||||
AgentId agentId = new(agentType, "TestKey");
|
||||
|
||||
Assert.Equal("TestType", agentId.Type);
|
||||
Assert.Equal("TestKey", agentId.Key);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldParseFromStringTest()
|
||||
{
|
||||
AgentId agentId = AgentId.FromStr("ParsedType/ParsedKey");
|
||||
|
||||
Assert.Equal("ParsedType", agentId.Type);
|
||||
Assert.Equal("ParsedKey", agentId.Key);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldCompareEqualityCorrectlyTest()
|
||||
{
|
||||
AgentId agentId1 = new("SameType", "SameKey");
|
||||
AgentId agentId2 = new("SameType", "SameKey");
|
||||
AgentId agentId3 = new("DifferentType", "DifferentKey");
|
||||
|
||||
Assert.Equal(agentId2, agentId1);
|
||||
Assert.NotEqual(agentId3, agentId1);
|
||||
Assert.True(agentId1 == agentId2);
|
||||
Assert.True(agentId1 != agentId3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldGenerateCorrectHashCodeTest()
|
||||
{
|
||||
AgentId agentId1 = new("HashType", "HashKey");
|
||||
AgentId agentId2 = new("HashType", "HashKey");
|
||||
AgentId agentId3 = new("DifferentType", "DifferentKey");
|
||||
|
||||
Assert.Equal(agentId2.GetHashCode(), agentId1.GetHashCode());
|
||||
Assert.NotEqual(agentId3.GetHashCode(), agentId1.GetHashCode());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldConvertExplicitlyFromStringTest()
|
||||
{
|
||||
AgentId agentId = (AgentId)"ConvertedType/ConvertedKey";
|
||||
|
||||
Assert.Equal("ConvertedType", agentId.Type);
|
||||
Assert.Equal("ConvertedKey", agentId.Key);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldReturnCorrectToStringTest()
|
||||
{
|
||||
AgentId agentId = new("ToStringType", "ToStringKey");
|
||||
|
||||
Assert.Equal("ToStringType/ToStringKey", agentId.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldCompareInequalityForWrongTypeTest()
|
||||
{
|
||||
AgentId agentId1 = new("Type1", "Key1");
|
||||
|
||||
Assert.False(agentId1.Equals(Guid.NewGuid()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AgentIdShouldCompareInequalityCorrectlyTest()
|
||||
{
|
||||
AgentId agentId1 = new("Type1", "Key1");
|
||||
AgentId agentId2 = new("Type2", "Key2");
|
||||
|
||||
Assert.True(agentId1 != agentId2);
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
namespace Microsoft.Extensions.AI.Agents.Runtime.Abstractions.Tests;
|
||||
|
||||
public class AgentMetadataTests()
|
||||
{
|
||||
[Fact]
|
||||
public void AgentMetadataShouldInitializeCorrectlyTest()
|
||||
{
|
||||
// Arrange & Act
|
||||
AgentMetadata metadata = new("TestType", "TestKey", "TestDescription");
|
||||
|
||||
// Assert
|
||||
Assert.Equal("TestType", metadata.Type);
|
||||
Assert.Equal("TestKey", metadata.Key);
|
||||
Assert.Equal("TestDescription", metadata.Description);
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.Extensions.AI.Agents.Runtime.Abstractions.Tests;
|
||||
|
||||
public class AgentProxyTests
|
||||
{
|
||||
private readonly Mock<IAgentRuntime> _mockRuntime;
|
||||
private readonly AgentId _agentId;
|
||||
private readonly AgentProxy _agentProxy;
|
||||
|
||||
public AgentProxyTests()
|
||||
{
|
||||
this._mockRuntime = new Mock<IAgentRuntime>();
|
||||
this._agentId = new AgentId("testType", "testKey");
|
||||
this._agentProxy = new AgentProxy(this._agentId, this._mockRuntime.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IdMatchesAgentIdTest()
|
||||
{
|
||||
// Assert
|
||||
Assert.Equal(this._agentId, this._agentProxy.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MetadataShouldMatchAgentTest()
|
||||
{
|
||||
AgentMetadata expectedMetadata = new("testType", "testKey", "testDescription");
|
||||
this._mockRuntime.Setup(r => r.GetAgentMetadataAsync(this._agentId))
|
||||
.ReturnsAsync(expectedMetadata);
|
||||
|
||||
Assert.Equal(expectedMetadata, this._agentProxy.Metadata);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SendMessageResponseTestAsync()
|
||||
{
|
||||
// Arrange
|
||||
object message = new { Content = "Hello" };
|
||||
AgentId sender = new("senderType", "senderKey");
|
||||
object response = new { Content = "Response" };
|
||||
|
||||
this._mockRuntime.Setup(r => r.SendMessageAsync(message, this._agentId, sender, null, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(response);
|
||||
|
||||
// Act
|
||||
object? result = await this._agentProxy.SendMessageAsync(message, sender);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(response, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadStateTestAsync()
|
||||
{
|
||||
// Arrange
|
||||
JsonElement state = JsonDocument.Parse("{\"key\":\"value\"}").RootElement;
|
||||
|
||||
this._mockRuntime.Setup(r => r.LoadAgentStateAsync(this._agentId, state))
|
||||
.Returns(default(ValueTask));
|
||||
|
||||
// Act
|
||||
await this._agentProxy.LoadStateAsync(state);
|
||||
|
||||
// Assert
|
||||
this._mockRuntime.Verify(r => r.LoadAgentStateAsync(this._agentId, state), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SaveStateTestAsync()
|
||||
{
|
||||
// Arrange
|
||||
JsonElement expectedState = JsonDocument.Parse("{\"key\":\"value\"}").RootElement;
|
||||
|
||||
this._mockRuntime.Setup(r => r.SaveAgentStateAsync(this._agentId))
|
||||
.ReturnsAsync(expectedState);
|
||||
|
||||
// Act
|
||||
JsonElement result = await this._agentProxy.SaveStateAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedState, result);
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Extensions.AI.Agents.Runtime.Abstractions.Tests;
|
||||
|
||||
public class AgentTypeTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
[InlineData("invalid type")] // Agent type must only contain alphanumeric letters or underscores
|
||||
[InlineData("123invalidType")] // Agent type cannot start with a number
|
||||
[InlineData("invalid@type")] // Agent type must only contain alphanumeric letters or underscores
|
||||
[InlineData("invalid-type")] // Agent type cannot alphanumeric underscores.
|
||||
public void AgentIdShouldThrowArgumentExceptionWithInvalidType(string? invalidType)
|
||||
{
|
||||
// Act & Assert
|
||||
ArgumentException exception = Assert.Throws<ArgumentException>(() => new AgentType(invalidType!));
|
||||
Assert.Contains("Invalid AgentId type", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitConversionFromStringTest()
|
||||
{
|
||||
// Arrange
|
||||
string agentTypeName = "TestAgent";
|
||||
|
||||
// Act
|
||||
AgentType agentType = agentTypeName;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(agentTypeName, agentType.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ImplicitConversionToStringTest()
|
||||
{
|
||||
// Arrange
|
||||
AgentType agentType = "TestAgent";
|
||||
|
||||
// Act
|
||||
string agentTypeName = agentType;
|
||||
|
||||
// Assert
|
||||
Assert.Equal("TestAgent", agentTypeName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExplicitConversionFromTypeTest()
|
||||
{
|
||||
// Arrange
|
||||
Type type = typeof(string);
|
||||
|
||||
// Act
|
||||
AgentType agentType = (AgentType)type;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(type.Name, agentType.Name);
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.Extensions.AI.Agents.Runtime.Abstractions.Tests;
|
||||
|
||||
public class MessageContextTests
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructWithMessageIdAndCancellationTokenTest()
|
||||
{
|
||||
// Arrange
|
||||
string messageId = Guid.NewGuid().ToString();
|
||||
CancellationToken cancellationToken = new();
|
||||
|
||||
// Act
|
||||
MessageContext messageContext = new(messageId, cancellationToken);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(messageId, messageContext.MessageId);
|
||||
Assert.Equal(cancellationToken, messageContext.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructWithCancellationTokenTest()
|
||||
{
|
||||
// Arrange
|
||||
CancellationToken cancellationToken = new();
|
||||
|
||||
// Act
|
||||
MessageContext messageContext = new(cancellationToken);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(messageContext.MessageId);
|
||||
Assert.Equal(cancellationToken, messageContext.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AssignSenderTest()
|
||||
{
|
||||
// Arrange
|
||||
MessageContext messageContext = new(new CancellationToken());
|
||||
AgentId sender = new("type", "key");
|
||||
|
||||
// Act
|
||||
messageContext.Sender = sender;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(sender, messageContext.Sender);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AssignTopicTest()
|
||||
{
|
||||
// Arrange
|
||||
MessageContext messageContext = new(new CancellationToken());
|
||||
TopicId topic = new("type", "source");
|
||||
|
||||
// Act
|
||||
messageContext.Topic = topic;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(topic, messageContext.Topic);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AssignIsRpcPropertyTest()
|
||||
{
|
||||
// Arrange
|
||||
MessageContext messageContext = new(new CancellationToken())
|
||||
{
|
||||
// Act
|
||||
IsRpc = true
|
||||
};
|
||||
|
||||
// Assert
|
||||
Assert.True(messageContext.IsRpc);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(ProjectsTargetFrameworks)</TargetFrameworks>
|
||||
<TargetFrameworks Condition="'$(Configuration)' == 'Debug'">$(ProjectsDebugTargetFrameworks)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.Extensions.AI.Agents.Runtime.Abstractions\Microsoft.Extensions.AI.Agents.Runtime.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Extensions.AI.Agents.Runtime.Abstractions.Tests;
|
||||
|
||||
public class TopicIdTests
|
||||
{
|
||||
[Fact]
|
||||
public void ConstrWithTypeOnlyTest()
|
||||
{
|
||||
// Arrange & Act
|
||||
TopicId topicId = new("testtype");
|
||||
|
||||
// Assert
|
||||
Assert.Equal("testtype", topicId.Type);
|
||||
Assert.Equal(TopicId.DefaultSource, topicId.Source);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructWithTypeAndSourceTest()
|
||||
{
|
||||
// Arrange & Act
|
||||
TopicId topicId = new("testtype", "customsource");
|
||||
|
||||
// Assert
|
||||
Assert.Equal("testtype", topicId.Type);
|
||||
Assert.Equal("customsource", topicId.Source);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConstructWithTupleTest()
|
||||
{
|
||||
// Arrange
|
||||
(string, string) tuple = ("testtype", "customsource");
|
||||
|
||||
// Act
|
||||
TopicId topicId = new(tuple);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("testtype", topicId.Type);
|
||||
Assert.Equal("customsource", topicId.Source);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConvertFromStringTest()
|
||||
{
|
||||
// Arrange
|
||||
const string TopicIdStr = "testtype/customsource";
|
||||
|
||||
// Act
|
||||
TopicId topicId = TopicId.FromStr(TopicIdStr);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("testtype", topicId.Type);
|
||||
Assert.Equal("customsource", topicId.Source);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("invalid-format")]
|
||||
[InlineData("too/many/parts")]
|
||||
[InlineData("")]
|
||||
public void InvalidFormatFromStringThrowsTest(string invalidInput)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<FormatException>(() => TopicId.FromStr(invalidInput));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToStringTest()
|
||||
{
|
||||
// Arrange
|
||||
TopicId topicId = new("testtype", "customsource");
|
||||
|
||||
// Act
|
||||
string result = topicId.ToString();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("testtype/customsource", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EqualityTest()
|
||||
{
|
||||
// Arrange
|
||||
TopicId topicId1 = new("testtype", "customsource");
|
||||
TopicId topicId2 = new("testtype", "customsource");
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(topicId1.Equals(topicId2));
|
||||
Assert.True(topicId1.Equals((object)topicId2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InequalityTest()
|
||||
{
|
||||
// Arrange
|
||||
TopicId topicId1 = new("testtype1", "source1");
|
||||
TopicId topicId2 = new("testtype2", "source2");
|
||||
TopicId topicId3 = new("testtype1", "source2");
|
||||
TopicId topicId4 = new("testtype2", "source1");
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(topicId1.Equals(topicId2));
|
||||
Assert.False(topicId1.Equals(topicId3));
|
||||
Assert.False(topicId1.Equals(topicId4));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NullEqualityTest()
|
||||
{
|
||||
// Arrange
|
||||
TopicId topicId = new("testtype", "customsource");
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(topicId.Equals(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DifferentTypeEqualityTest()
|
||||
{
|
||||
// Arrange
|
||||
TopicId topicId = new("testtype", "customsource");
|
||||
const string DifferentType = "not-a-topic-id";
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(topicId.Equals(DifferentType));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetHashCodeTest()
|
||||
{
|
||||
// Arrange
|
||||
TopicId topicId1 = new("testtype", "customsource");
|
||||
TopicId topicId2 = new("testtype", "customsource");
|
||||
|
||||
// Act
|
||||
int hash1 = topicId1.GetHashCode();
|
||||
int hash2 = topicId2.GetHashCode();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(hash1, hash2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExplicitConversionTest()
|
||||
{
|
||||
// Arrange
|
||||
string topicIdStr = "testtype/customsource";
|
||||
|
||||
// Act
|
||||
TopicId topicId = (TopicId)topicIdStr;
|
||||
|
||||
// Assert
|
||||
Assert.Equal("testtype", topicId.Type);
|
||||
Assert.Equal("customsource", topicId.Source);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsWildcardMatchTest()
|
||||
{
|
||||
// Arrange
|
||||
TopicId topicId1 = new("testtype", "source1");
|
||||
TopicId topicId2 = new("testtype", "source2");
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(topicId1.IsWildcardMatch(topicId2));
|
||||
Assert.True(topicId2.IsWildcardMatch(topicId1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsWildcardMismatchTest()
|
||||
{
|
||||
// Arrange
|
||||
TopicId topicId1 = new("testtype1", "source");
|
||||
TopicId topicId2 = new("testtype2", "source");
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(topicId1.IsWildcardMatch(topicId2));
|
||||
Assert.False(topicId2.IsWildcardMatch(topicId1));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user