139 lines
4.8 KiB
C#
139 lines
4.8 KiB
C#
using TermRemoteCtl.Agent.Sessions;
|
|
using Microsoft.Extensions.Options;
|
|
using TermRemoteCtl.Agent.Configuration;
|
|
using TermRemoteCtl.Agent.History;
|
|
|
|
namespace TermRemoteCtl.Agent.Tests.Sessions;
|
|
|
|
public class SessionRegistryTests
|
|
{
|
|
[Fact]
|
|
public void Create_Returns_Record_And_List_Is_Ordered_By_Name()
|
|
{
|
|
using var harness = SessionRegistryHarness.Create();
|
|
var registry = harness.Registry;
|
|
var now = new DateTimeOffset(2026, 03, 27, 03, 00, 00, TimeSpan.Zero);
|
|
|
|
var zebra = registry.Create("Zebra", now);
|
|
var alpha = registry.Create("Alpha", now.AddMinutes(1));
|
|
|
|
Assert.Equal("Zebra", zebra.Name);
|
|
Assert.Equal("Alpha", alpha.Name);
|
|
Assert.Equal(["Alpha", "Zebra"], registry.List().Select(record => record.Name).ToArray());
|
|
}
|
|
|
|
[Fact]
|
|
public void Create_Sets_Record_Metadata()
|
|
{
|
|
using var harness = SessionRegistryHarness.Create();
|
|
var registry = harness.Registry;
|
|
var now = new DateTimeOffset(2026, 03, 27, 03, 15, 00, TimeSpan.Zero);
|
|
|
|
var record = registry.Create("Shell", now);
|
|
|
|
Assert.False(string.IsNullOrWhiteSpace(record.SessionId));
|
|
Assert.Equal("Shell", record.Name);
|
|
Assert.Equal("created", record.Status);
|
|
Assert.Equal(now, record.CreatedAtUtc);
|
|
Assert.Equal(now, record.UpdatedAtUtc);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AppendOutputAsync_Stores_Recent_Scrollback_Lines()
|
|
{
|
|
using var harness = SessionRegistryHarness.Create(lineLimit: 3);
|
|
var registry = harness.Registry;
|
|
var session = registry.Create("Shell", DateTimeOffset.UtcNow);
|
|
|
|
await registry.AppendOutputAsync(session.SessionId, "one\ntwo\nthree\n", CancellationToken.None);
|
|
|
|
var history = registry.GetHistory(session.SessionId, 2);
|
|
|
|
Assert.Equal(["two", "three"], history.Lines);
|
|
Assert.True(history.HasMoreAbove);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AppendOutputAsync_Persists_History_To_Log_File()
|
|
{
|
|
using var harness = SessionRegistryHarness.Create();
|
|
var registry = harness.Registry;
|
|
var session = registry.Create("Shell", DateTimeOffset.UtcNow);
|
|
|
|
await registry.AppendOutputAsync(session.SessionId, "dir\r\n", CancellationToken.None);
|
|
|
|
var logPath = Path.Combine(harness.DataRoot, "sessions", $"{session.SessionId}.log");
|
|
var content = await File.ReadAllTextAsync(logPath);
|
|
|
|
Assert.Equal("dir\r\n", content);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AppendOutputAsync_Stores_Recent_Replay_Output()
|
|
{
|
|
using var harness = SessionRegistryHarness.Create();
|
|
var registry = harness.Registry;
|
|
var session = registry.Create("Shell", DateTimeOffset.UtcNow);
|
|
|
|
await registry.AppendOutputAsync(session.SessionId, "prompt> ", CancellationToken.None);
|
|
await registry.AppendOutputAsync(session.SessionId, "dir\r\n", CancellationToken.None);
|
|
|
|
var replay = registry.GetReplaySnapshot(session.SessionId);
|
|
|
|
Assert.Equal("prompt> dir\r\n", replay);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Delete_Removes_Session_Record_And_History_Log()
|
|
{
|
|
using var harness = SessionRegistryHarness.Create();
|
|
var registry = harness.Registry;
|
|
var session = registry.Create("Shell", DateTimeOffset.UtcNow);
|
|
await registry.AppendOutputAsync(session.SessionId, "dir\r\n", CancellationToken.None);
|
|
|
|
await registry.DeleteAsync(session.SessionId, CancellationToken.None);
|
|
|
|
Assert.Empty(registry.List());
|
|
Assert.False(registry.TryGet(session.SessionId, out _));
|
|
Assert.False(File.Exists(Path.Combine(harness.DataRoot, "sessions", $"{session.SessionId}.log")));
|
|
Assert.Throws<KeyNotFoundException>(() => registry.GetHistory(session.SessionId, 10));
|
|
}
|
|
|
|
private sealed class SessionRegistryHarness : IDisposable
|
|
{
|
|
private SessionRegistryHarness(string dataRoot, SessionRegistry registry)
|
|
{
|
|
DataRoot = dataRoot;
|
|
Registry = registry;
|
|
}
|
|
|
|
public string DataRoot { get; }
|
|
|
|
public SessionRegistry Registry { get; }
|
|
|
|
public static SessionRegistryHarness Create(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 historyStore = new SessionHistoryStore(dataRoot);
|
|
var registry = new SessionRegistry(historyStore, options);
|
|
|
|
return new SessionRegistryHarness(dataRoot, registry);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Directory.Exists(DataRoot))
|
|
{
|
|
Directory.Delete(DataRoot, true);
|
|
}
|
|
}
|
|
}
|
|
}
|