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