db620d33df
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
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
226 lines
6.6 KiB
C#
226 lines
6.6 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
using System.Reflection;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Microsoft.Agents.AI.UnitTests.AgentSkills;
|
|
|
|
/// <summary>
|
|
/// Unit tests for <see cref="AgentInlineSkillResource"/>.
|
|
/// </summary>
|
|
public sealed class AgentInlineSkillResourceTests
|
|
{
|
|
[Fact]
|
|
public async Task ReadAsync_StaticValue_ReturnsValueAsync()
|
|
{
|
|
// Arrange
|
|
var resource = new AgentInlineSkillResource("config", "my-value");
|
|
|
|
// Act
|
|
var result = await resource.ReadAsync();
|
|
|
|
// Assert
|
|
Assert.Equal("my-value", result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadAsync_StaticObjectValue_ReturnsSameInstanceAsync()
|
|
{
|
|
// Arrange
|
|
var obj = new object();
|
|
var resource = new AgentInlineSkillResource("ref", obj);
|
|
|
|
// Act
|
|
var result = await resource.ReadAsync();
|
|
|
|
// Assert
|
|
Assert.Same(obj, result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadAsync_Delegate_InvokesFunctionAsync()
|
|
{
|
|
// Arrange
|
|
int callCount = 0;
|
|
var resource = new AgentInlineSkillResource("dynamic", () =>
|
|
{
|
|
callCount++;
|
|
return "computed";
|
|
});
|
|
|
|
// Act
|
|
var result = await resource.ReadAsync();
|
|
|
|
// Assert
|
|
Assert.Equal("computed", result?.ToString());
|
|
Assert.Equal(1, callCount);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadAsync_Delegate_InvokesEachTimeAsync()
|
|
{
|
|
// Arrange
|
|
int callCount = 0;
|
|
var resource = new AgentInlineSkillResource("counter", () => ++callCount);
|
|
|
|
// Act
|
|
await resource.ReadAsync();
|
|
await resource.ReadAsync();
|
|
var result = await resource.ReadAsync();
|
|
|
|
// Assert
|
|
Assert.Equal(3, callCount);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_StaticValue_SetsNameAndDescription()
|
|
{
|
|
// Arrange & Act
|
|
var resource = new AgentInlineSkillResource("my-res", "val", "A description.");
|
|
|
|
// Assert
|
|
Assert.Equal("my-res", resource.Name);
|
|
Assert.Equal("A description.", resource.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_StaticValue_NullDescription_DescriptionIsNull()
|
|
{
|
|
// Arrange & Act
|
|
var resource = new AgentInlineSkillResource("my-res", "val");
|
|
|
|
// Assert
|
|
Assert.Null(resource.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_StaticValue_NullValue_Throws()
|
|
{
|
|
// Act & Assert — cast needed to target the object overload
|
|
#pragma warning disable IDE0004
|
|
Assert.Throws<ArgumentNullException>(() =>
|
|
new AgentInlineSkillResource("my-res", (object)null!));
|
|
#pragma warning restore IDE0004
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_Delegate_NullMethod_Throws()
|
|
{
|
|
// Act & Assert
|
|
Assert.Throws<ArgumentNullException>(() =>
|
|
new AgentInlineSkillResource("my-res", null!));
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_NullName_Throws()
|
|
{
|
|
// Act & Assert
|
|
Assert.Throws<ArgumentNullException>(() =>
|
|
new AgentInlineSkillResource(null!, "val"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_WhitespaceName_Throws()
|
|
{
|
|
// Act & Assert
|
|
Assert.Throws<ArgumentException>(() =>
|
|
new AgentInlineSkillResource(" ", "val"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_Delegate_SetsNameAndDescription()
|
|
{
|
|
// Arrange & Act
|
|
var resource = new AgentInlineSkillResource("dyn-res", () => "hello", "Dynamic resource.");
|
|
|
|
// Assert
|
|
Assert.Equal("dyn-res", resource.Name);
|
|
Assert.Equal("Dynamic resource.", resource.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadAsync_WithSerializerOptions_SerializesReturnCustomTypeAsync()
|
|
{
|
|
// Arrange — delegate resource returns a custom type; the JSO includes a source-generated context for it
|
|
var jso = SkillTestJsonContext.Default.Options;
|
|
var resource = new AgentInlineSkillResource("config", () => new SkillConfig { Theme = "dark", Verbose = true }, serializerOptions: jso);
|
|
|
|
// Act
|
|
var result = await resource.ReadAsync();
|
|
|
|
// Assert — the custom type was returned successfully
|
|
Assert.NotNull(result);
|
|
Assert.Contains("dark", result!.ToString()!);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadAsync_SupportsCancellationTokenAsync()
|
|
{
|
|
// Arrange
|
|
using var cts = new CancellationTokenSource();
|
|
var resource = new AgentInlineSkillResource("cancellable", "value");
|
|
|
|
// Act — should not throw with a non-cancelled token
|
|
var result = await resource.ReadAsync(cancellationToken: cts.Token);
|
|
|
|
// Assert
|
|
Assert.Equal("value", result);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_MethodInfo_SetsNameAndDescription()
|
|
{
|
|
// Arrange
|
|
var method = typeof(AgentInlineSkillResourceTests).GetMethod(nameof(StaticResourceHelper), BindingFlags.NonPublic | BindingFlags.Static)!;
|
|
|
|
// Act
|
|
var resource = new AgentInlineSkillResource("method-resource", method, target: null, description: "A method resource.");
|
|
|
|
// Assert
|
|
Assert.Equal("method-resource", resource.Name);
|
|
Assert.Equal("A method resource.", resource.Description);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadAsync_MethodInfo_StaticMethod_ReturnsValueAsync()
|
|
{
|
|
// Arrange
|
|
var method = typeof(AgentInlineSkillResourceTests).GetMethod(nameof(StaticResourceHelper), BindingFlags.NonPublic | BindingFlags.Static)!;
|
|
var resource = new AgentInlineSkillResource("static-method-res", method, target: null);
|
|
|
|
// Act
|
|
var result = await resource.ReadAsync();
|
|
|
|
// Assert
|
|
Assert.Equal("static-resource-value", result?.ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReadAsync_MethodInfo_InstanceMethod_ReturnsValueAsync()
|
|
{
|
|
// Arrange
|
|
var method = typeof(AgentInlineSkillResourceTests).GetMethod(nameof(InstanceResourceHelper), BindingFlags.NonPublic | BindingFlags.Instance)!;
|
|
var resource = new AgentInlineSkillResource("instance-method-res", method, target: this);
|
|
|
|
// Act
|
|
var result = await resource.ReadAsync();
|
|
|
|
// Assert
|
|
Assert.Equal("instance-resource-value", result?.ToString());
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_MethodInfo_NullMethod_Throws()
|
|
{
|
|
// Act & Assert
|
|
Assert.Throws<ArgumentNullException>(() =>
|
|
new AgentInlineSkillResource("my-res", null!, target: null));
|
|
}
|
|
|
|
private static string StaticResourceHelper() => "static-resource-value";
|
|
|
|
private string InstanceResourceHelper() => "instance-resource-value";
|
|
}
|