136 lines
5.6 KiB
C#
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);
|
|
}
|
|
}
|