1package terminalquery
2
3import (
4 "testing"
5
6 "github.com/stretchr/testify/require"
7)
8
9func TestProbeRequiresKittyAndDA1(t *testing.T) {
10 for _, tc := range []struct {
11 name string
12 data string
13 kitty bool
14 da1 bool
15 unrelated string
16 }{
17 {name: "both and input", data: "x\x1b[?1;2c" + "\x1b_Gi=31;OK\x1b\\y", kitty: true, da1: true, unrelated: "xy"},
18 {name: "secondary DA is insufficient", data: "\x1b[>1;2c\x1b_Gi=31;OK\x1b\\", kitty: true, unrelated: "\x1b[>1;2c"},
19 {name: "ordinary input", data: "hello", unrelated: "hello"},
20 } {
21 t.Run(tc.name, func(t *testing.T) {
22 var p Probe
23 got := append(p.Feed([]byte(tc.data)), p.Finish()...)
24 require.Equal(t, tc.kitty, p.KittyGraphics())
25 require.Equal(t, tc.da1, p.DA1())
26 require.Equal(t, tc.unrelated, string(got))
27 })
28 }
29}
30
31func TestProbeRecognizesFragmentedResponsesAndReplaysInput(t *testing.T) {
32 var p Probe
33 var unrelated []byte
34 for _, fragment := range []string{"a\x1b", "[?1;2", "c", "b\x1b_Gi=31;", "OK\x1b", "\\z"} {
35 unrelated = append(unrelated, p.Feed([]byte(fragment))...)
36 }
37 unrelated = append(unrelated, p.Finish()...)
38 require.True(t, p.Ready())
39 require.Equal(t, "abz", string(unrelated))
40}
41
42func TestProbeRequiresExactCapabilityResponses(t *testing.T) {
43 for _, data := range []string{
44 "\x1b_Gi=31;OK,extra\x1b\\",
45 "\x1b_Gi=310;OK\x1b\\",
46 "\x1b_Gi=31;OKAY\x1b\\",
47 "\x1b[?1;;2c",
48 "\x1b[?x;2c",
49 } {
50 var p Probe
51 got := append(p.Feed([]byte(data)), p.Finish()...)
52 require.False(t, p.Ready(), "response %q was accepted", data)
53 require.Equal(t, data, string(got))
54 }
55}
56
57func FuzzProbeNeverPanics(f *testing.F) {
58 f.Add([]byte("text\x1b[?1;2c\x1b_Gi=31;OK\x1b\\"))
59 f.Add([]byte("\x1b_G"))
60 f.Fuzz(func(t *testing.T, data []byte) {
61 var p Probe
62 _ = p.Feed(data)
63 _ = p.Finish()
64 })
65}
66
67func TestProbeDoesNotRetainLargeInputFragments(t *testing.T) {
68 var p Probe
69 input := append(make([]byte, 1<<20), []byte("\x1b_G")...)
70 got := append(p.Feed(input), p.Finish()...)
71 require.Equal(t, input, got)
72 require.LessOrEqual(t, cap(p.pending), maxProbeResponseBytes+2)
73}
74
75func TestProbeBoundsUnterminatedResponse(t *testing.T) {
76 var p Probe
77 input := append([]byte("prefix"), []byte("\x1b_G")...)
78 input = append(input, make([]byte, maxProbeResponseBytes+1)...)
79 got := append(p.Feed(input), p.Finish()...)
80 require.False(t, p.Ready())
81 require.Equal(t, input, got)
82}