| File: TestServices\TestAuxiliaryBackchannelMonitor.cs | Web Access |
| Project: src\tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj (Aspire.Cli.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.Collections.Concurrent; using System.Runtime.CompilerServices; using System.Threading.Channels; using Aspire.Cli.Backchannel; namespace Aspire.Cli.Tests.TestServices; internal sealed class TestAuxiliaryBackchannelMonitor : IAuxiliaryBackchannelMonitor { private readonly ConcurrentDictionary<string, IAppHostAuxiliaryBackchannel> _connectionsBySocketPath = new(StringComparers.FileSystemPath); private readonly Channel<bool> _connectionChanges = Channel.CreateUnbounded<bool>(); public IEnumerable<IAppHostAuxiliaryBackchannel> Connections => _connectionsBySocketPath.Values; public string? SelectedAppHostPath { get; set; } /// <summary> /// Gets the number of times ScanAsync was called. /// </summary> public int ScanCallCount { get; private set; } public Func<CancellationToken, Task>? ScanAsyncCallback { get; set; } /// <summary> /// Triggers an immediate scan. In the test implementation, this just increments ScanCallCount. /// </summary> public Task ScanAsync(CancellationToken cancellationToken = default) { ScanCallCount++; return ScanAsyncCallback?.Invoke(cancellationToken) ?? Task.CompletedTask; } public async IAsyncEnumerable<IReadOnlyList<IAppHostAuxiliaryBackchannel>> WatchConnectionsAsync([EnumeratorCancellation] CancellationToken cancellationToken = default) { await ScanAsync(cancellationToken).ConfigureAwait(false); yield return Connections.ToList(); await foreach (var _ in _connectionChanges.Reader.ReadAllAsync(cancellationToken).ConfigureAwait(false)) { await ScanAsync(cancellationToken).ConfigureAwait(false); yield return Connections.ToList(); } } public void NotifyConnectionsChanged() { _connectionChanges.Writer.TryWrite(true); } public IAppHostAuxiliaryBackchannel? SelectedConnection { get { // Delegates to the production policy so this fake cannot drift from the behavior // selection tests are meant to be asserting on. var selectedAppHostPath = SelectedAppHostPath; var connection = AuxiliaryBackchannelMonitor.SelectConnection(Connections, ref selectedAppHostPath); SelectedAppHostPath = selectedAppHostPath; return connection; } } public IReadOnlyList<IAppHostAuxiliaryBackchannel> GetConnectionsForWorkingDirectory(DirectoryInfo workingDirectory) { return Connections .Where(c => AuxiliaryBackchannelMonitor.IsAppHostInScopeOfDirectory(c.AppHostInfo?.AppHostPath, workingDirectory.FullName)) .ToList(); } public void AddConnection(string socketPath, IAppHostAuxiliaryBackchannel connection) { _connectionsBySocketPath[socketPath] = connection; } public void RemoveConnection(string socketPath) { _connectionsBySocketPath.TryRemove(socketPath, out _); } public void ClearConnections() { _connectionsBySocketPath.Clear(); } }