TermRemoteCtl/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/Terminal/PowerShellSessionHostTests.cs

127 lines
3.9 KiB
C#

using Microsoft.Extensions.Options;
using TermRemoteCtl.Agent.Configuration;
using TermRemoteCtl.Agent.History;
using TermRemoteCtl.Agent.Sessions;
using TermRemoteCtl.Agent.Terminal;
namespace TermRemoteCtl.Agent.Tests.Terminal;
public class PowerShellSessionHostTests
{
[Fact]
public async Task ResizeAsync_Forwards_To_ConPty_Session()
{
var factory = new FakeConPtySessionFactory();
using var harness = HostHarness.Create(factory);
await using var host = harness.Host;
await host.StartAsync("alpha", CancellationToken.None);
await host.ResizeAsync("alpha", 120, 40, CancellationToken.None);
Assert.Equal((120, 40), factory.Session.ResizeCalls.Single());
}
[Fact]
public async Task Session_Output_Is_Captured_In_Registry_History()
{
var factory = new FakeConPtySessionFactory();
using var harness = HostHarness.Create(factory, lineLimit: 3);
var session = harness.Registry.Create("Shell", DateTimeOffset.UtcNow);
await using var host = harness.Host;
await host.StartAsync(session.SessionId, CancellationToken.None);
factory.Session.EmitOutput(session.SessionId, "one\ntwo\nthree\n");
var history = harness.Registry.GetHistory(session.SessionId, 2);
Assert.Equal(["two", "three"], history.Lines);
Assert.True(history.HasMoreAbove);
}
private sealed class HostHarness : IDisposable
{
private HostHarness(string dataRoot, SessionRegistry registry, PowerShellSessionHost host)
{
DataRoot = dataRoot;
Registry = registry;
Host = host;
}
public string DataRoot { get; }
public SessionRegistry Registry { get; }
public PowerShellSessionHost Host { get; }
public static HostHarness Create(FakeConPtySessionFactory factory, int lineLimit = 4000)
{
var dataRoot = Path.Combine(Path.GetTempPath(), "TermRemoteCtl.Tests", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(dataRoot);
var options = Options.Create(new AgentOptions
{
DataRoot = dataRoot,
RingBufferLineLimit = lineLimit,
});
var registry = new SessionRegistry(new SessionHistoryStore(dataRoot), options);
var host = new PowerShellSessionHost(factory, registry);
return new HostHarness(dataRoot, registry, host);
}
public void Dispose()
{
if (Directory.Exists(DataRoot))
{
Directory.Delete(DataRoot, true);
}
}
}
private sealed class FakeConPtySessionFactory : IConPtySessionFactory
{
public FakeConPtySession Session { get; } = new();
public IConPtySession Create(string sessionId)
{
Session.SessionId = sessionId;
return Session;
}
}
private sealed class FakeConPtySession : IConPtySession
{
public string SessionId { get; set; } = string.Empty;
public event EventHandler<TerminalOutputEventArgs>? OutputReceived;
public List<(int Columns, int Rows)> ResizeCalls { get; } = new();
public Task StartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public Task WriteInputAsync(string input, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public Task ResizeAsync(int columns, int rows, CancellationToken cancellationToken)
{
ResizeCalls.Add((columns, rows));
return Task.CompletedTask;
}
public void EmitOutput(string sessionId, string chunk)
{
OutputReceived?.Invoke(this, new TerminalOutputEventArgs(sessionId, chunk));
}
public ValueTask DisposeAsync()
{
return ValueTask.CompletedTask;
}
}
}