Initial release: pure Go mosh client and server
Wire-compatible with C mosh. AES-128-OCB3, SSP transport, fragmentation, protobuf state sync, latch extension fields. Includes ServeRW bridge mode for embedding.
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
package mosh
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFramebufferDiffIdentical(t *testing.T) {
|
||||
fb := NewFramebuffer(80, 24)
|
||||
old := NewFramebuffer(80, 24)
|
||||
diff := fb.Diff(old)
|
||||
// Should just be cursor positioning + show cursor, no cell updates.
|
||||
if strings.Contains(string(diff), "\033[2J") {
|
||||
t.Fatal("identical framebuffers should not trigger full clear")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFramebufferDiffSingleCell(t *testing.T) {
|
||||
old := NewFramebuffer(80, 24)
|
||||
fb := NewFramebuffer(80, 24)
|
||||
fb.CellAt(5, 3).Rune = 'A'
|
||||
fb.CellAt(5, 3).Width = 1
|
||||
|
||||
diff := fb.Diff(old)
|
||||
s := string(diff)
|
||||
// Should contain CUP to row 4, col 6 (1-indexed).
|
||||
if !strings.Contains(s, "\033[4;6H") {
|
||||
t.Fatalf("expected CUP \\033[4;6H, got %q", s)
|
||||
}
|
||||
if !strings.Contains(s, "A") {
|
||||
t.Fatal("diff should contain 'A'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFramebufferFullRedraw(t *testing.T) {
|
||||
fb := NewFramebuffer(80, 24)
|
||||
fb.CellAt(0, 0).Rune = 'X'
|
||||
fb.CellAt(0, 0).Width = 1
|
||||
|
||||
diff := fb.Diff(nil)
|
||||
s := string(diff)
|
||||
if !strings.Contains(s, "\033[2J") {
|
||||
t.Fatal("nil old should trigger full redraw with clear")
|
||||
}
|
||||
if !strings.Contains(s, "X") {
|
||||
t.Fatal("full redraw should contain 'X'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFramebufferDiffSizeChange(t *testing.T) {
|
||||
old := NewFramebuffer(80, 24)
|
||||
fb := NewFramebuffer(132, 43)
|
||||
diff := fb.Diff(old)
|
||||
s := string(diff)
|
||||
if !strings.Contains(s, "\033[2J") {
|
||||
t.Fatal("size change should trigger full redraw")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFramebufferDiffWithAttrs(t *testing.T) {
|
||||
old := NewFramebuffer(80, 24)
|
||||
fb := NewFramebuffer(80, 24)
|
||||
|
||||
c := fb.CellAt(0, 0)
|
||||
c.Rune = 'B'
|
||||
c.Width = 1
|
||||
c.Attr = Attr{Bold: true, FG: Color{Type: ColorIndex, Value: 1}}
|
||||
|
||||
diff := fb.Diff(old)
|
||||
s := string(diff)
|
||||
// Should contain bold (1) and red fg (31).
|
||||
if !strings.Contains(s, "1") {
|
||||
t.Fatal("diff should contain bold SGR")
|
||||
}
|
||||
if !strings.Contains(s, "31") {
|
||||
t.Fatal("diff should contain red FG SGR")
|
||||
}
|
||||
if !strings.Contains(s, "B") {
|
||||
t.Fatal("diff should contain 'B'")
|
||||
}
|
||||
// Should reset at end.
|
||||
if !strings.Contains(s, "\033[m") {
|
||||
t.Fatal("diff should reset attributes at end")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFramebufferDiffRGBColor(t *testing.T) {
|
||||
old := NewFramebuffer(80, 24)
|
||||
fb := NewFramebuffer(80, 24)
|
||||
|
||||
c := fb.CellAt(0, 0)
|
||||
c.Rune = 'R'
|
||||
c.Width = 1
|
||||
c.Attr.FG = Color{Type: ColorRGB, Value: 0xFF8000} // orange
|
||||
|
||||
diff := fb.Diff(old)
|
||||
s := string(diff)
|
||||
if !strings.Contains(s, "38;2;255;128;0") {
|
||||
t.Fatalf("expected RGB SGR, got %q", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFramebufferDiffWideChar(t *testing.T) {
|
||||
old := NewFramebuffer(80, 24)
|
||||
fb := NewFramebuffer(80, 24)
|
||||
|
||||
// Wide character at (0,0) with continuation at (1,0).
|
||||
fb.CellAt(0, 0).Rune = '中'
|
||||
fb.CellAt(0, 0).Width = 2
|
||||
fb.CellAt(1, 0).Rune = 0
|
||||
fb.CellAt(1, 0).Width = 0
|
||||
|
||||
diff := fb.Diff(old)
|
||||
s := string(diff)
|
||||
if !strings.Contains(s, "中") {
|
||||
t.Fatal("diff should contain wide character")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFramebufferDiffCursorPosition(t *testing.T) {
|
||||
old := NewFramebuffer(80, 24)
|
||||
fb := NewFramebuffer(80, 24)
|
||||
fb.CurX = 10
|
||||
fb.CurY = 5
|
||||
|
||||
diff := fb.Diff(old)
|
||||
s := string(diff)
|
||||
// Final cursor position should be at row 6, col 11 (1-indexed).
|
||||
if !strings.Contains(s, "\033[6;11H") {
|
||||
t.Fatalf("expected cursor at [6;11H, got %q", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFramebufferDiffCursorHidden(t *testing.T) {
|
||||
old := NewFramebuffer(80, 24)
|
||||
fb := NewFramebuffer(80, 24)
|
||||
fb.CurVis = false
|
||||
|
||||
diff := fb.Diff(old)
|
||||
s := string(diff)
|
||||
if strings.Contains(s, "\033[?25h") {
|
||||
t.Fatal("cursor should not be shown when CurVis=false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendCUP(t *testing.T) {
|
||||
buf := appendCUP(nil, 0, 0)
|
||||
if string(buf) != "\033[1;1H" {
|
||||
t.Fatalf("got %q", string(buf))
|
||||
}
|
||||
buf = appendCUP(nil, 23, 79)
|
||||
if string(buf) != "\033[24;80H" {
|
||||
t.Fatalf("got %q", string(buf))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user