Something went wrong. Try again.
Go bindings for libghostty-vt. pkg.go.dev/go.mitchellh.com/libghostty
ghostty
Something went wrong. Try again.
go-libghostty paste_test.go
8.0 kB · 344 lines
Go
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345package libghostty
import ( "bytes" "errors" "io" "strings" "testing")
func TestTerminalPasteText(t *testing.T) { var output bytes.Buffer var requested []string term, err := NewTerminal( WithSize(80, 24), WithWritePty(func(_ *Terminal, data []byte) { output.Write(data) }), ) if err != nil { t.Fatal(err) } defer term.Close()
written, err := term.Paste(Paste{ Location: ClipboardLocationStandard, Source: PasteSourceText, MIMEs: []string{"image/png", "text/plain"}, Reader: func(mime string, writer io.Writer) error { requested = append(requested, mime) _, err := io.WriteString(writer, "hello") return err }, }) if err != nil { t.Fatal(err) } if !written { t.Fatal("expected paste to write text") } if got := output.String(); got != "hello" { t.Fatalf("expected pasted text %q, got %q", "hello", got) } if len(requested) != 1 || requested[0] != "text/plain" { t.Fatalf("expected only text/plain to be requested, got %q", requested) }}
func TestTerminalPasteRejectedAndRetry(t *testing.T) { var output bytes.Buffer var reads int term, err := NewTerminal( WithSize(80, 24), WithWritePty(func(_ *Terminal, data []byte) { output.Write(data) }), ) if err != nil { t.Fatal(err) } defer term.Close()
paste := Paste{ Location: ClipboardLocationStandard, Source: PasteSourceClipboard, MIMEs: []string{"text/plain"}, Reader: func(_ string, writer io.Writer) error { reads++ _, err := io.WriteString(writer, "hello\nworld") return err }, } written, err := term.Paste(paste) if written { t.Fatal("expected rejected paste not to write") } assertResultError(t, err, ResultRejected) if output.Len() != 0 { t.Fatalf("expected rejected paste to write nothing, got %q", output.Bytes()) }
paste.AllowUnsafe = true written, err = term.Paste(paste) if err != nil { t.Fatal(err) } if !written { t.Fatal("expected confirmed paste to write") } if got := output.String(); got != "hello\rworld" { t.Fatalf("expected legacy newline framing, got %q", got) } if reads != 2 { t.Fatalf("expected source to be read once per call, got %d reads", reads) }}
func TestTerminalPasteRejectsCarriageReturn(t *testing.T) { // A carriage return is the Enter key on the input stream, so an // unbracketed paste refuses it exactly like a newline. var output bytes.Buffer term, err := NewTerminal( WithSize(80, 24), WithWritePty(func(_ *Terminal, data []byte) { output.Write(data) }), ) if err != nil { t.Fatal(err) } defer term.Close()
paste := Paste{ Location: ClipboardLocationStandard, Source: PasteSourceClipboard, MIMEs: []string{"text/plain"}, Reader: func(_ string, writer io.Writer) error { _, err := io.WriteString(writer, "rm -rf /\r") return err }, } written, err := term.Paste(paste) if written { t.Fatal("expected rejected paste not to write") } assertResultError(t, err, ResultRejected) if output.Len() != 0 { t.Fatalf("expected rejected paste to write nothing, got %q", output.Bytes()) }
paste.AllowUnsafe = true written, err = term.Paste(paste) if err != nil { t.Fatal(err) } if !written { t.Fatal("expected confirmed paste to write") } if got := output.String(); got != "rm -rf /\r" { t.Fatalf("expected confirmed paste output, got %q", got) }}
func TestTerminalPasteBracketed(t *testing.T) { var output bytes.Buffer term, err := NewTerminal( WithSize(80, 24), WithWritePty(func(_ *Terminal, data []byte) { output.Write(data) }), ) if err != nil { t.Fatal(err) } defer term.Close() if err := term.SetMode(ModeBracketedPaste, true); err != nil { t.Fatal(err) }
written, err := term.Paste(Paste{ Source: PasteSourceText, MIMEs: []string{"text/plain"}, Reader: func(_ string, writer io.Writer) error { _, err := io.WriteString(writer, "hello\nworld") return err }, }) if err != nil { t.Fatal(err) } if !written { t.Fatal("expected bracketed paste to write") } if want := "\x1b[200~hello\nworld\x1b[201~"; output.String() != want { t.Fatalf("expected bracketed paste %q, got %q", want, output.String()) }}
func TestTerminalPasteReaderError(t *testing.T) { sentinel := errors.New("clipboard unavailable") term, err := NewTerminal( WithSize(80, 24), WithWritePty(func(_ *Terminal, _ []byte) {}), ) if err != nil { t.Fatal(err) } defer term.Close()
written, err := term.Paste(Paste{ MIMEs: []string{"text/plain"}, Reader: func(_ string, _ io.Writer) error { return sentinel }, }) if written { t.Fatal("expected failed paste not to write") } assertResultError(t, err, ResultIOError) if !errors.Is(err, sentinel) { t.Fatalf("expected callback error to be preserved, got %v", err) }}
func TestTerminalPasteEmpty(t *testing.T) { term, err := NewTerminal( WithSize(80, 24), WithWritePty(func(_ *Terminal, _ []byte) {}), ) if err != nil { t.Fatal(err) } defer term.Close()
written, err := term.Paste(Paste{}) if err != nil { t.Fatal(err) } if written { t.Fatal("expected empty paste not to write") }}
func TestTerminalPasteKittyEventUsesSecureRandom(t *testing.T) { var randomCalls int if err := SysSetRandomSecure(func(data []byte) error { randomCalls++ for i := range data { data[i] = byte(i + 1) } return nil }); err != nil { t.Fatal(err) } defer func() { if err := SysSetRandomSecure(nil); err != nil { t.Errorf("restore platform random source: %v", err) } }()
var output strings.Builder var reads int term, err := NewTerminal( WithSize(80, 24), WithWritePty(func(_ *Terminal, data []byte) { output.Write(data) }), WithClipboardRead(func(_ *Terminal, _ ClipboardRead) ClipboardReadReply { return ClipboardReadReply{Result: ClipboardReadDenied} }), ) if err != nil { t.Fatal(err) } defer term.Close() if err := term.SetMode(ModePasteEvents, true); err != nil { t.Fatal(err) }
written, err := term.Paste(Paste{ Location: ClipboardLocationPrimary, Source: PasteSourceClipboard, MIMEs: []string{"text/plain", "image/png"}, Reader: func(_ string, _ io.Writer) error { reads++ return nil }, }) if err != nil { t.Fatal(err) } if !written { t.Fatal("expected Kitty paste event to be written") } if randomCalls == 0 { t.Fatal("expected paste event to request secure random bytes") } if reads != 0 { t.Fatalf("expected paste event not to read content, got %d reads", reads) } if got := output.String(); !strings.HasPrefix(got, "\x1b]5522;type=read:status=OK:loc=primary:pw=") { t.Fatalf("unexpected Kitty paste event %q", got) }}
func TestPasteIsSafe(t *testing.T) { tests := []struct { name string data string want bool }{ {name: "empty", data: "", want: true}, {name: "plain", data: "hello", want: true}, {name: "newline", data: "hello\nworld", want: false}, {name: "carriage return", data: "hello\rworld", want: false}, {name: "bracketed paste end", data: "hello\x1b[201~world", want: false}, }
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := PasteIsSafe([]byte(tt.data)); got != tt.want { t.Fatalf("PasteIsSafe(%q) = %v, want %v", tt.data, got, tt.want) } }) }}
func TestPasteEncodeLegacy(t *testing.T) { in := []byte("hello\nworld\x1b!")
out, err := PasteEncode(in, false) if err != nil { t.Fatal(err) }
if string(out) != "hello\rworld !" { t.Fatalf("PasteEncode legacy = %q, want %q", out, "hello\rworld !") } if string(in) != "hello\nworld\x1b!" { t.Fatalf("PasteEncode mutated input to %q", in) }}
func TestPasteEncodeBracketed(t *testing.T) { out, err := PasteEncode([]byte("hello\nworld"), true) if err != nil { t.Fatal(err) }
want := "\x1b[200~hello\nworld\x1b[201~" if string(out) != want { t.Fatalf("PasteEncode bracketed = %q, want %q", out, want) }}
func TestPasteEncodeEmpty(t *testing.T) { out, err := PasteEncode(nil, false) if err != nil { t.Fatal(err) } if out != nil { t.Fatalf("PasteEncode empty = %q, want nil", out) }}