Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:39:25 +08:00

105 lines
4.0 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Agents.AI.Hyperlight.Internal;
using Microsoft.Extensions.AI;
using Moq;
namespace Microsoft.Agents.AI.Hyperlight.UnitTests;
public sealed class ProvideAIContextTests
{
private static readonly AIAgent s_mockAgent = new Mock<AIAgent>().Object;
private static AIContextProvider.InvokingContext NewInvokingContext() => new(s_mockAgent, session: null, new AIContext());
[Fact]
public async Task ProvideAIContextAsync_ReturnsExecuteCodeToolAndInstructionsAsync()
{
// Arrange
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions());
// Act
var context = await provider.InvokingAsync(NewInvokingContext());
// Assert
Assert.NotNull(context);
Assert.NotNull(context!.Tools);
var tools = context.Tools!.ToList();
Assert.Single(tools);
var function = Assert.IsAssignableFrom<AIFunction>(tools[0]);
Assert.Equal("execute_code", function.Name);
Assert.False(string.IsNullOrWhiteSpace(context.Instructions));
}
[Fact]
public async Task ProvideAIContextAsync_AlwaysRequire_WrapsInApprovalRequiredAsync()
{
// Arrange
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions
{
ApprovalMode = CodeActApprovalMode.AlwaysRequire,
});
// Act
var context = await provider.InvokingAsync(NewInvokingContext());
// Assert
_ = Assert.IsType<ApprovalRequiredAIFunction>(context!.Tools!.First());
}
[Fact]
public async Task ProvideAIContextAsync_NeverRequireWithApprovalTool_WrapsInApprovalRequiredAsync()
{
// Arrange
var inner = AIFunctionFactory.Create(() => "ok", name: "t");
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions
{
ApprovalMode = CodeActApprovalMode.NeverRequire,
Tools = [new ApprovalRequiredAIFunction(inner)],
});
// Act
var context = await provider.InvokingAsync(NewInvokingContext());
// Assert
_ = Assert.IsType<ApprovalRequiredAIFunction>(context!.Tools!.First());
}
[Fact]
public async Task ProvideAIContextAsync_CapturesSnapshot_MutationsAfterDoNotAffectDescriptionAsync()
{
// Arrange
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions());
provider.AddTools(AIFunctionFactory.Create(() => "one", name: "first_tool"));
// Act
var context = await provider.InvokingAsync(NewInvokingContext());
provider.AddTools(AIFunctionFactory.Create(() => "two", name: "second_tool"));
// Assert — the returned execute_code description must reflect the first snapshot only.
var function = Assert.IsAssignableFrom<AIFunction>(context!.Tools!.First());
Assert.Contains("first_tool", function.Description);
Assert.DoesNotContain("second_tool", function.Description);
}
[Fact]
public async Task ProvideAIContextAsync_AddToolsSameNameReplacement_ChangesSnapshotFingerprintAsync()
{
// Arrange
using var provider = new HyperlightCodeActProvider(new HyperlightCodeActProviderOptions());
provider.AddTools(AIFunctionFactory.Create(() => "one", name: "same_tool"));
// Act
var firstContext = await provider.InvokingAsync(NewInvokingContext());
provider.AddTools(AIFunctionFactory.Create(() => "two", name: "same_tool"));
var secondContext = await provider.InvokingAsync(NewInvokingContext());
// Assert
var firstFunction = Assert.IsType<ExecuteCodeFunction>(firstContext!.Tools!.First());
var secondFunction = Assert.IsType<ExecuteCodeFunction>(secondContext!.Tools!.First());
Assert.NotEqual(firstFunction.ConfigFingerprint, secondFunction.ConfigFingerprint);
}
}