| File: Utils\TestResourceTerminalHost.cs | Web Access |
| Project: src\tests\Aspire.Hosting.Tests\Aspire.Hosting.Tests.csproj (Aspire.Hosting.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Hex1b; using Hex1b.Automation; using Microsoft.AspNetCore.InternalTesting; namespace Aspire.Hosting.Tests.Utils; internal sealed class TestResourceTerminalHost : IAsyncDisposable { private readonly Hex1bTerminal _terminal; private readonly CancellationTokenSource _cts = new(); private readonly Task _runTask; private Task? _disposeTask; private TestResourceTerminalHost(string socketPath, Hex1bTerminalBuilder builder) { SocketPath = socketPath; _terminal = builder .WithHeadless() .WithDimensions(120, 40) .WithHmp1UdsServer(socketPath) .Build(); _runTask = _terminal.RunAsync(_cts.Token); } public string SocketPath { get; } public static Task<TestResourceTerminalHost> StartAsync(string socketPath) => StartAsync(socketPath, Hex1bTerminal.CreateBuilder().WithPtyProcess("bash")); public static Task<TestResourceTerminalHost> StartAsync(string socketPath, IHex1bTerminalWorkloadAdapter workload) => StartAsync(socketPath, Hex1bTerminal.CreateBuilder().WithWorkload(workload)); public Task WaitForTextAsync(string text) => new Hex1bTerminalAutomator(_terminal, TimeSpan.FromSeconds(30)).WaitUntilTextAsync(text); private static async Task<TestResourceTerminalHost> StartAsync(string socketPath, Hex1bTerminalBuilder builder) { var host = new TestResourceTerminalHost(socketPath, builder); try { await AsyncTestHelpers.AssertIsTrueRetryAsync(() => { if (host._runTask.IsCompleted) { host._runTask.GetAwaiter().GetResult(); throw new InvalidOperationException("The terminal host exited before its socket became available."); } return File.Exists(socketPath); }, $"The terminal host did not begin listening on '{socketPath}'."); return host; } catch { await host.DisposeAsync(); throw; } } public ValueTask DisposeAsync() => new(_disposeTask ??= DisposeCoreAsync()); private async Task DisposeCoreAsync() { await _cts.CancelAsync(); try { await _runTask; } catch (OperationCanceledException) when (_cts.IsCancellationRequested) { // Expected when the test shuts down the terminal host. } finally { await _terminal.DisposeAsync(); _cts.Dispose(); } } }