| File: TestServices\NativeActivationRpcTestHost.cs | Web Access |
| Project: src\tests\Aspire.Hosting.Native.Core.Tests\Aspire.Hosting.Native.Core.Tests.csproj (Aspire.Hosting.Native.Core.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.Net; using System.Net.Sockets; using System.Text.Json; using Aspire.Hosting.Native.Rpc; using StreamJsonRpc; namespace Aspire.Hosting.Native.Core.Tests.TestServices; /// <summary>Responds to activation bootstrap but deliberately stalls authority abandonment.</summary> internal sealed class NativeActivationRpcTestHost : IAsyncDisposable { private readonly TcpListener _listener = new(IPAddress.Loopback, 0); private readonly CancellationTokenSource _lifetime = new(); private readonly Task _run; public IPEndPoint Endpoint => (IPEndPoint)_listener.LocalEndpoint; public TaskCompletionSource AbandonmentStarted { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously); public NativeActivationRpcTestHost() { _listener.Start(); _run = RunAsync(); } private async Task RunAsync() { try { using var socket = await _listener.AcceptSocketAsync(_lifetime.Token); using var stream = new NetworkStream(socket, ownsSocket: false); using var rpc = new JsonRpc(new HeaderDelimitedMessageHandler(stream, stream, new SystemTextJsonFormatter())); rpc.AddLocalRpcMethod("authenticate", new Func<string, bool>(_ => true)); rpc.AddLocalRpcMethod("getApplicationServer", new Func<JsonElement>(() => JsonSerializer.SerializeToElement(new Dictionary<string, string> { ["$handle"] = "root", ["$type"] = NativeRpcContract.ApplicationServerTypeId }))); rpc.AddLocalRpcMethod("expectIntegrationHost", new Func<string, string>(_ => "authority")); rpc.AddLocalRpcMethod("abandonIntegrationHostRegistration", new Func<string, Task<bool>>(async _ => { AbandonmentStarted.TrySetResult(); await Task.Delay(Timeout.InfiniteTimeSpan, TimeProvider.System, _lifetime.Token); return true; })); rpc.StartListening(); await rpc.Completion.WaitAsync(_lifetime.Token); } catch (OperationCanceledException) when (_lifetime.IsCancellationRequested) { } } public async ValueTask DisposeAsync() { await _lifetime.CancelAsync(); try { await _run.WaitAsync(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken); } finally { _listener.Stop(); _lifetime.Dispose(); } } }