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

136 lines
5.6 KiB
C#

using TermRemoteCtl.Agent.Terminal.Screen;
namespace TermRemoteCtl.Agent.Tests.Terminal;
public sealed class TerminalScreenEngineTests
{
[Fact]
public void ApplyOutput_Clear_Removes_Stale_Lines_From_Visible_Snapshot()
{
var engine = new TerminalScreenEngine(rows: 4, cols: 20);
engine.ApplyOutput("first line\r\nsecond line", sourceSequence: 1);
engine.ApplyOutput("\u001b[2J\u001b[Hprompt> ", sourceSequence: 2);
var snapshot = engine.CreateSnapshot("session-1");
Assert.Equal(2L, snapshot.SourceSequence);
Assert.Equal(2L, snapshot.ScreenVersion);
Assert.StartsWith("prompt> ", snapshot.PrimaryBuffer.Viewport[0].Text, StringComparison.Ordinal);
Assert.DoesNotContain(
snapshot.PrimaryBuffer.Viewport,
line => line.Text.Contains("first line", StringComparison.Ordinal));
Assert.Equal(0, snapshot.CursorRow);
Assert.Equal(8, snapshot.CursorColumn);
}
[Fact]
public void ApplyOutput_Cursor_Movement_And_Insert_Produces_Final_Visible_Line()
{
var engine = new TerminalScreenEngine(rows: 4, cols: 40);
engine.ApplyOutput("PS> gst", sourceSequence: 1);
engine.ApplyOutput("\u001b[2D", sourceSequence: 2);
engine.ApplyOutput("it", sourceSequence: 3);
var snapshot = engine.CreateSnapshot("session-1");
Assert.StartsWith("PS> git", snapshot.PrimaryBuffer.Viewport[0].Text, StringComparison.Ordinal);
Assert.Equal(0, snapshot.CursorRow);
Assert.Equal(7, snapshot.CursorColumn);
Assert.Equal(3L, snapshot.SourceSequence);
Assert.Equal(3L, snapshot.ScreenVersion);
}
[Fact]
public void ApplyOutput_Alternate_Buffer_Preserves_Primary_And_Restores_On_Exit()
{
var engine = new TerminalScreenEngine(rows: 4, cols: 20);
engine.ApplyOutput("primary view", sourceSequence: 1);
engine.ApplyOutput("\u001b[?1049halt view", sourceSequence: 2);
var alternateSnapshot = engine.CreateSnapshot("session-1");
Assert.Equal("alternate", alternateSnapshot.ActiveBuffer);
Assert.StartsWith("alt view", alternateSnapshot.AlternateBuffer!.Viewport[0].Text, StringComparison.Ordinal);
Assert.StartsWith("primary view", alternateSnapshot.PrimaryBuffer.Viewport[0].Text, StringComparison.Ordinal);
engine.ApplyOutput("\u001b[?1049l", sourceSequence: 3);
var restoredSnapshot = engine.CreateSnapshot("session-1");
Assert.Equal("primary", restoredSnapshot.ActiveBuffer);
Assert.StartsWith("primary view", restoredSnapshot.PrimaryBuffer.Viewport[0].Text, StringComparison.Ordinal);
Assert.StartsWith("alt view", restoredSnapshot.AlternateBuffer!.Viewport[0].Text, StringComparison.Ordinal);
}
[Theory]
[InlineData("\u001b[?1047h", "\u001b[?1047l")]
[InlineData("\u001b[?47h", "\u001b[?47l")]
public void ApplyOutput_Alternate_Buffer_Compatibility_Modes_Switch_Buffers(
string enterSequence,
string exitSequence)
{
var engine = new TerminalScreenEngine(rows: 4, cols: 20);
engine.ApplyOutput("primary", sourceSequence: 1);
engine.ApplyOutput($"{enterSequence}alt", sourceSequence: 2);
var alternateSnapshot = engine.CreateSnapshot("session-1");
Assert.Equal("alternate", alternateSnapshot.ActiveBuffer);
Assert.StartsWith("alt", alternateSnapshot.AlternateBuffer!.Viewport[0].Text, StringComparison.Ordinal);
Assert.StartsWith("primary", alternateSnapshot.PrimaryBuffer.Viewport[0].Text, StringComparison.Ordinal);
engine.ApplyOutput(exitSequence, sourceSequence: 3);
var restoredSnapshot = engine.CreateSnapshot("session-1");
Assert.Equal("primary", restoredSnapshot.ActiveBuffer);
Assert.StartsWith("primary", restoredSnapshot.PrimaryBuffer.Viewport[0].Text, StringComparison.Ordinal);
}
[Fact]
public void ApplyOutput_Osc_Window_Title_Does_Not_Leak_Into_Visible_Screen()
{
var engine = new TerminalScreenEngine(rows: 4, cols: 80);
engine.ApplyOutput("\u001b]0;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe\u0007", sourceSequence: 1);
engine.ApplyOutput("PS D:\\App\\python\\MLplatform> pwd", sourceSequence: 2);
var snapshot = engine.CreateSnapshot("session-1");
Assert.DoesNotContain(
snapshot.PrimaryBuffer.Viewport,
line => line.Text.Contains("]0;", StringComparison.Ordinal));
Assert.DoesNotContain(
snapshot.PrimaryBuffer.Viewport,
line => line.Text.Contains("powershell.exe", StringComparison.OrdinalIgnoreCase));
Assert.StartsWith(
"PS D:\\App\\python\\MLplatform> pwd",
snapshot.PrimaryBuffer.Viewport[0].Text,
StringComparison.Ordinal);
Assert.Equal(0, snapshot.CursorRow);
Assert.Equal(32, snapshot.CursorColumn);
}
[Fact]
public void ApplyOutput_Osc_Window_Title_With_String_Terminator_Does_Not_Leak_Into_Visible_Screen()
{
var engine = new TerminalScreenEngine(rows: 4, cols: 80);
engine.ApplyOutput("\u001b]0;PowerShell Title\u001b\\", sourceSequence: 1);
engine.ApplyOutput("prompt> ", sourceSequence: 2);
var snapshot = engine.CreateSnapshot("session-1");
Assert.DoesNotContain(
snapshot.PrimaryBuffer.Viewport,
line => line.Text.Contains("PowerShell Title", StringComparison.Ordinal));
Assert.StartsWith("prompt> ", snapshot.PrimaryBuffer.Viewport[0].Text, StringComparison.Ordinal);
Assert.Equal(0, snapshot.CursorRow);
Assert.Equal(8, snapshot.CursorColumn);
}
}