| File: OpenAIRealtimeClientSessionTests.cs | |
| Project: ..\..\..\test\Libraries\Microsoft.Extensions.AI.OpenAI.Tests\Microsoft.Extensions.AI.OpenAI.Tests.csproj (Microsoft.Extensions.AI.OpenAI.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Threading; using System.Threading.Tasks; using Xunit; #pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. namespace Microsoft.Extensions.AI; public class OpenAIRealtimeClientSessionTests { [Fact] public async Task GetService_ReturnsExpectedServices() { await using IRealtimeClientSession session = new OpenAIRealtimeClientSession("key", "model"); Assert.Same(session, session.GetService(typeof(OpenAIRealtimeClientSession))); Assert.Same(session, session.GetService(typeof(IRealtimeClientSession))); Assert.Null(session.GetService(typeof(string))); Assert.Null(session.GetService(typeof(OpenAIRealtimeClientSession), "someKey")); } [Fact] public async Task GetService_NullServiceType_Throws() { await using IRealtimeClientSession session = new OpenAIRealtimeClientSession("key", "model"); Assert.Throws<ArgumentNullException>("serviceType", () => session.GetService(null!)); } [Fact] public async Task DisposeAsync_CanBeCalledMultipleTimes() { IRealtimeClientSession session = new OpenAIRealtimeClientSession("key", "model"); await session.DisposeAsync(); // Second dispose should not throw. await session.DisposeAsync(); Assert.Null(session.GetService(typeof(string))); } [Fact] public async Task Options_InitiallyNull() { await using var session = new OpenAIRealtimeClientSession("key", "model"); Assert.Null(session.Options); } [Fact] public void SessionUpdateMessage_NullOptions_Throws() { Assert.Throws<ArgumentNullException>("options", () => new SessionUpdateRealtimeClientMessage(null!)); } [Fact] public async Task SendAsync_NullMessage_Throws() { await using var session = new OpenAIRealtimeClientSession("key", "model"); await Assert.ThrowsAsync<ArgumentNullException>("message", () => session.SendAsync(null!)); } [Fact] public async Task SendAsync_CancelledToken_ThrowsOperationCanceledException() { await using var session = new OpenAIRealtimeClientSession("key", "model"); using var cts = new CancellationTokenSource(); cts.Cancel(); // Should throw when cancellation is requested. await Assert.ThrowsAsync<OperationCanceledException>(() => session.SendAsync(new RealtimeClientMessage(), cts.Token)); } [Fact] public async Task SendAsync_NotConnected_ThrowsInvalidOperationException() { await using var session = new OpenAIRealtimeClientSession("key", "model"); // Should throw when session is not connected. await Assert.ThrowsAsync<InvalidOperationException>(() => session.SendAsync(new RealtimeClientMessage())); } [Fact] public async Task ConnectAsync_CancelledToken_Throws() { await using var session = new OpenAIRealtimeClientSession("key", "model"); using var cts = new CancellationTokenSource(); cts.Cancel(); var ex = await Assert.ThrowsAnyAsync<Exception>(() => session.ConnectAsync(cts.Token)); Assert.True( ex is OperationCanceledException || ex is System.Net.WebSockets.WebSocketException, $"Expected OperationCanceledException or WebSocketException but got {ex.GetType().FullName}"); } }