// Copyright (c) Microsoft. All rights reserved. using System; using System.Collections.Generic; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.AI; namespace Microsoft.Agents.AI.Abstractions.UnitTests; /// /// Unit tests for the class. /// public sealed class AgentRunContextTests { #region Constructor Validation Tests /// /// Verifies that passing null for agent throws ArgumentNullException. /// [Fact] public void Constructor_NullAgent_ThrowsArgumentNullException() { // Arrange AgentSession session = new TestAgentSession(); IReadOnlyCollection messages = new List(); AgentRunOptions options = new(); // Act & Assert Assert.Throws(() => new AgentRunContext(null!, session, messages, options)); } /// /// Verifies that passing null for session does not throw /// [Fact] public void Constructor_NullSession_DoesNotThrow() { // Arrange AIAgent agent = new TestAgent(); IReadOnlyCollection messages = new List(); AgentRunOptions options = new(); // Act AgentRunContext context = new(agent, null, messages, options); // Assert Assert.NotNull(context); Assert.Null(context.Session); } /// /// Verifies that passing null for requestMessages throws ArgumentNullException. /// [Fact] public void Constructor_NullRequestMessages_ThrowsArgumentNullException() { // Arrange AIAgent agent = new TestAgent(); AgentSession session = new TestAgentSession(); AgentRunOptions options = new(); // Act & Assert Assert.Throws(() => new AgentRunContext(agent, session, null!, options)); } /// /// Verifies that passing null for agentRunOptions does not throw. /// [Fact] public void Constructor_NullAgentRunOptions_DoesNotThrow() { // Arrange AIAgent agent = new TestAgent(); AgentSession session = new TestAgentSession(); IReadOnlyCollection messages = new List(); // Act AgentRunContext context = new(agent, session, messages, null); // Assert Assert.NotNull(context); Assert.Null(context.RunOptions); } #endregion #region Property Roundtrip Tests /// /// Verifies that the Agent property returns the value passed to the constructor. /// [Fact] public void Agent_ReturnsValueFromConstructor() { // Arrange AIAgent agent = new TestAgent(); AgentSession session = new TestAgentSession(); IReadOnlyCollection messages = new List(); AgentRunOptions options = new(); // Act AgentRunContext context = new(agent, session, messages, options); // Assert Assert.Same(agent, context.Agent); } /// /// Verifies that the Session property returns the value passed to the constructor. /// [Fact] public void Session_ReturnsValueFromConstructor() { // Arrange AIAgent agent = new TestAgent(); AgentSession session = new TestAgentSession(); IReadOnlyCollection messages = new List(); AgentRunOptions options = new(); // Act AgentRunContext context = new(agent, session, messages, options); // Assert Assert.Same(session, context.Session); } /// /// Verifies that the RequestMessages property returns the value passed to the constructor. /// [Fact] public void RequestMessages_ReturnsValueFromConstructor() { // Arrange AIAgent agent = new TestAgent(); AgentSession session = new TestAgentSession(); IReadOnlyCollection messages = new List { new(ChatRole.User, "Hello"), new(ChatRole.Assistant, "Hi there!") }; AgentRunOptions options = new(); // Act AgentRunContext context = new(agent, session, messages, options); // Assert Assert.Same(messages, context.RequestMessages); Assert.Equal(2, context.RequestMessages.Count); } /// /// Verifies that the RunOptions property returns the value passed to the constructor. /// [Fact] public void RunOptions_ReturnsValueFromConstructor() { // Arrange AIAgent agent = new TestAgent(); AgentSession session = new TestAgentSession(); IReadOnlyCollection messages = new List(); AgentRunOptions options = new() { AllowBackgroundResponses = true, AdditionalProperties = new AdditionalPropertiesDictionary { ["key1"] = "value1" } }; // Act AgentRunContext context = new(agent, session, messages, options); // Assert Assert.Same(options, context.RunOptions); Assert.True(context.RunOptions!.AllowBackgroundResponses); } /// /// Verifies that an empty messages collection is handled correctly. /// [Fact] public void RequestMessages_EmptyCollection_ReturnsEmptyCollection() { // Arrange AIAgent agent = new TestAgent(); AgentSession session = new TestAgentSession(); IReadOnlyCollection messages = new List(); AgentRunOptions options = new(); // Act AgentRunContext context = new(agent, session, messages, options); // Assert Assert.NotNull(context.RequestMessages); Assert.Empty(context.RequestMessages); } #endregion #region Test Helpers private sealed class TestAgentSession : AgentSession; private sealed class TestAgent : AIAgent { protected override ValueTask CreateSessionCoreAsync(CancellationToken cancellationToken = default) => throw new NotImplementedException(); protected override ValueTask DeserializeSessionCoreAsync(JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default) => throw new NotImplementedException(); protected override ValueTask SerializeSessionCoreAsync(AgentSession session, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default) => throw new NotImplementedException(); protected override Task RunCoreAsync( IEnumerable messages, AgentSession? session = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default) => throw new NotImplementedException(); protected override IAsyncEnumerable RunCoreStreamingAsync( IEnumerable messages, AgentSession? session = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default) => throw new NotImplementedException(); } #endregion }