main
1package rfb
2
3import (
4 "testing"
5)
6
7func TestEncodeKeyEvent(t *testing.T) {
8 tests := []struct {
9 name string
10 down bool
11 key uint32
12 want []byte
13 }{
14 {
15 name: "key down 'a'",
16 down: true,
17 key: 0x61,
18 want: []byte{0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61},
19 },
20 {
21 name: "key up 'a'",
22 down: false,
23 key: 0x61,
24 want: []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61},
25 },
26 {
27 name: "key down Return",
28 down: true,
29 key: KeyReturn,
30 want: []byte{0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0d},
31 },
32 }
33
34 for _, tt := range tests {
35 t.Run(tt.name, func(t *testing.T) {
36 got := EncodeKeyEvent(tt.down, tt.key)
37 if len(got) != len(tt.want) {
38 t.Errorf("EncodeKeyEvent() len = %d, want %d", len(got), len(tt.want))
39 return
40 }
41 for i := range got {
42 if got[i] != tt.want[i] {
43 t.Errorf("EncodeKeyEvent()[%d] = %02x, want %02x", i, got[i], tt.want[i])
44 }
45 }
46 })
47 }
48}
49
50func TestEncodeClientCutText(t *testing.T) {
51 text := "Hello"
52 got := EncodeClientCutText(text)
53
54 // Type
55 if got[0] != MsgTypeClientCutText {
56 t.Errorf("type = %d, want %d", got[0], MsgTypeClientCutText)
57 }
58
59 // Length (big-endian)
60 length := uint32(got[4])<<24 | uint32(got[5])<<16 | uint32(got[6])<<8 | uint32(got[7])
61 if length != uint32(len(text)) {
62 t.Errorf("length = %d, want %d", length, len(text))
63 }
64
65 // Text
66 gotText := string(got[8:])
67 if gotText != text {
68 t.Errorf("text = %q, want %q", gotText, text)
69 }
70}
71
72func TestRuneToKeysym(t *testing.T) {
73 tests := []struct {
74 r rune
75 want uint32
76 }{
77 {'\n', KeyReturn},
78 {'\t', KeyTab},
79 {'\b', KeyBackspace},
80 {'a', 0x61},
81 {'A', 0x41},
82 {'1', 0x31},
83 }
84
85 for _, tt := range tests {
86 got := RuneToKeysym(tt.r)
87 if got != tt.want {
88 t.Errorf("RuneToKeysym(%q) = %#x, want %#x", tt.r, got, tt.want)
89 }
90 }
91}
92
93func TestParseServerCutText(t *testing.T) {
94 // Build a valid ServerCutText message
95 text := "clipboard content"
96 msg := make([]byte, 8+len(text))
97 msg[0] = MsgTypeServerCutText
98 // padding msg[1:4]
99 msg[4] = 0
100 msg[5] = 0
101 msg[6] = 0
102 msg[7] = byte(len(text))
103 copy(msg[8:], text)
104
105 cut, err := ParseServerCutText(msg)
106 if err != nil {
107 t.Fatalf("ParseServerCutText() error = %v", err)
108 }
109 if cut.Text != text {
110 t.Errorf("Text = %q, want %q", cut.Text, text)
111 }
112}
113
114func TestEncodeSetEncodings(t *testing.T) {
115 encodings := []int32{EncodingTight, EncodingRaw}
116 got := EncodeSetEncodings(encodings)
117
118 // Type
119 if got[0] != MsgTypeSetEncodings {
120 t.Errorf("type = %d, want %d", got[0], MsgTypeSetEncodings)
121 }
122
123 // Count
124 count := uint16(got[2])<<8 | uint16(got[3])
125 if count != uint16(len(encodings)) {
126 t.Errorf("count = %d, want %d", count, len(encodings))
127 }
128
129 // Expected length: 4 header + 4 per encoding
130 wantLen := 4 + 4*len(encodings)
131 if len(got) != wantLen {
132 t.Errorf("len = %d, want %d", len(got), wantLen)
133 }
134}
135
136func TestEncodeFramebufferUpdateRequest(t *testing.T) {
137 got := EncodeFramebufferUpdateRequest(true, 0, 0, 1920, 1080)
138
139 // Type
140 if got[0] != MsgTypeFramebufferUpdateRequest {
141 t.Errorf("type = %d, want %d", got[0], MsgTypeFramebufferUpdateRequest)
142 }
143
144 // Incremental
145 if got[1] != 1 {
146 t.Errorf("incremental = %d, want 1", got[1])
147 }
148
149 // Width
150 width := uint16(got[6])<<8 | uint16(got[7])
151 if width != 1920 {
152 t.Errorf("width = %d, want 1920", width)
153 }
154
155 // Height
156 height := uint16(got[8])<<8 | uint16(got[9])
157 if height != 1080 {
158 t.Errorf("height = %d, want 1080", height)
159 }
160}