-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathprotocol_test.go
More file actions
268 lines (242 loc) · 6.59 KB
/
Copy pathprotocol_test.go
File metadata and controls
268 lines (242 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
package macwifi
import (
"bytes"
"encoding/binary"
"errors"
"io"
"reflect"
"strings"
"testing"
)
func TestWriteRequests(t *testing.T) {
t.Run("scan", func(t *testing.T) {
var got bytes.Buffer
if err := writeScanRequest(&got); err != nil {
t.Fatal(err)
}
want := []byte{'M', 'W', 'I', 'F', protocolVersion, msgTypeScanRequest}
if !bytes.Equal(got.Bytes(), want) {
t.Fatalf("writeScanRequest() = %x, want %x", got.Bytes(), want)
}
})
t.Run("password", func(t *testing.T) {
var got bytes.Buffer
if err := writePasswordRequest(&got, "Office WiFi"); err != nil {
t.Fatal(err)
}
want := []byte{'M', 'W', 'I', 'F', protocolVersion, msgTypePasswordRequest}
want = binary.LittleEndian.AppendUint16(want, uint16(len("Office WiFi")))
want = append(want, "Office WiFi"...)
if !bytes.Equal(got.Bytes(), want) {
t.Fatalf("writePasswordRequest() = %x, want %x", got.Bytes(), want)
}
})
t.Run("close", func(t *testing.T) {
var got bytes.Buffer
if err := writeCloseRequest(&got); err != nil {
t.Fatal(err)
}
want := []byte{'M', 'W', 'I', 'F', protocolVersion, msgTypeCloseRequest}
if !bytes.Equal(got.Bytes(), want) {
t.Fatalf("writeCloseRequest() = %x, want %x", got.Bytes(), want)
}
})
}
func TestReadHeader(t *testing.T) {
tests := []struct {
name string
frame []byte
want uint8
wantErr string
}{
{
name: "valid",
frame: []byte{'M', 'W', 'I', 'F', protocolVersion, msgTypeScanResponse},
want: msgTypeScanResponse,
},
{
name: "bad magic",
frame: []byte{'N', 'O', 'P', 'E', protocolVersion, msgTypeScanResponse},
wantErr: "bad magic",
},
{
name: "bad version",
frame: []byte{'M', 'W', 'I', 'F', protocolVersion + 1, msgTypeScanResponse},
wantErr: "unsupported protocol version",
},
{
name: "short",
frame: []byte{'M', 'W'},
wantErr: "read magic",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := readHeader(bytes.NewReader(tt.frame))
if tt.wantErr != "" {
if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
t.Fatalf("readHeader() error = %v, want containing %q", err, tt.wantErr)
}
return
}
if err != nil {
t.Fatal(err)
}
if got != tt.want {
t.Fatalf("readHeader() = 0x%02x, want 0x%02x", got, tt.want)
}
})
}
}
func TestDecodeScanResponse(t *testing.T) {
var body bytes.Buffer
writeString16(&body, "")
writeUint32(&body, 1)
writeNetwork(&body, Network{
SSID: "Office WiFi",
BSSID: "aa:bb:cc:dd:ee:ff",
RSSI: -52,
Noise: -91,
Channel: 149,
ChannelBand: Band5GHz,
ChannelWidth: 80,
Security: SecurityWPA2Personal,
PHYMode: "802.11ax",
Password: "",
Current: true,
Saved: true,
})
got, err := decodeScanResponse(&body)
if err != nil {
t.Fatal(err)
}
want := []Network{{
SSID: "Office WiFi",
BSSID: "aa:bb:cc:dd:ee:ff",
RSSI: -52,
Noise: -91,
Channel: 149,
ChannelBand: Band5GHz,
ChannelWidth: 80,
Security: SecurityWPA2Personal,
PHYMode: "802.11ax",
Password: "",
Current: true,
Saved: true,
}}
if !reflect.DeepEqual(got, want) {
t.Fatalf("decodeScanResponse() = %#v, want %#v", got, want)
}
}
func TestDecodeScanResponseReturnsRemoteError(t *testing.T) {
var body bytes.Buffer
writeString16(&body, "Location Services denied.")
got, err := decodeScanResponse(&body)
if err == nil || err.Error() != "Location Services denied." {
t.Fatalf("decodeScanResponse() error = %v, want remote error", err)
}
if got != nil {
t.Fatalf("decodeScanResponse() networks = %#v, want nil", got)
}
}
func TestDecodeScanResponseIdentifiesTruncatedNetwork(t *testing.T) {
var body bytes.Buffer
writeString16(&body, "")
writeUint32(&body, 1)
writeString16(&body, "Office WiFi")
_, err := decodeScanResponse(&body)
if err == nil || !strings.Contains(err.Error(), "network 0") {
t.Fatalf("decodeScanResponse() error = %v, want network index", err)
}
}
func TestDecodePasswordResponse(t *testing.T) {
t.Run("success", func(t *testing.T) {
var body bytes.Buffer
writeString16(&body, "")
writeString16(&body, "correct horse")
got, err := decodePasswordResponse(&body)
if err != nil {
t.Fatal(err)
}
if got != "correct horse" {
t.Fatalf("decodePasswordResponse() = %q, want %q", got, "correct horse")
}
})
t.Run("remote error", func(t *testing.T) {
var body bytes.Buffer
writeString16(&body, "user declined keychain access")
got, err := decodePasswordResponse(&body)
if err == nil || err.Error() != "user declined keychain access" {
t.Fatalf("decodePasswordResponse() error = %v, want remote error", err)
}
if got != "" {
t.Fatalf("decodePasswordResponse() = %q, want empty password", got)
}
})
}
func TestReadHelpersRejectShortInput(t *testing.T) {
if _, err := readBytes8(bytes.NewReader([]byte{2, 1})); !errors.Is(err, io.ErrUnexpectedEOF) {
t.Fatalf("readBytes8() error = %v, want ErrUnexpectedEOF", err)
}
if _, err := readString16(bytes.NewReader([]byte{2, 0, 1})); !errors.Is(err, io.ErrUnexpectedEOF) {
t.Fatalf("readString16() error = %v, want ErrUnexpectedEOF", err)
}
}
func TestFormatMAC(t *testing.T) {
tests := []struct {
name string
in []byte
want string
}{
{name: "valid", in: []byte{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, want: "aa:bb:cc:dd:ee:ff"},
{name: "empty"},
{name: "short", in: []byte{0xaa, 0xbb}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := formatMAC(tt.in); got != tt.want {
t.Fatalf("formatMAC(%x) = %q, want %q", tt.in, got, tt.want)
}
})
}
}
func writeNetwork(w *bytes.Buffer, n Network) {
writeString16(w, n.SSID)
writeBytes8(w, []byte{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff})
writeInt16(w, int16(n.RSSI))
writeInt16(w, int16(n.Noise))
writeUint16(w, uint16(n.Channel))
w.WriteByte(byte(n.ChannelBand))
writeUint16(w, uint16(n.ChannelWidth))
w.WriteByte(byte(n.Security))
writeString8(w, n.PHYMode)
writeString16(w, n.Password)
var flags uint8
if n.Current {
flags |= flagCurrent
}
if n.Saved {
flags |= flagSaved
}
w.WriteByte(flags)
}
func writeBytes8(w *bytes.Buffer, b []byte) {
w.WriteByte(byte(len(b)))
w.Write(b)
}
func writeString8(w *bytes.Buffer, s string) {
writeBytes8(w, []byte(s))
}
func writeString16(w *bytes.Buffer, s string) {
writeUint16(w, uint16(len(s)))
w.WriteString(s)
}
func writeInt16(w *bytes.Buffer, v int16) {
_ = binary.Write(w, byteOrder, v)
}
func writeUint16(w *bytes.Buffer, v uint16) {
_ = binary.Write(w, byteOrder, v)
}
func writeUint32(w *bytes.Buffer, v uint32) {
_ = binary.Write(w, byteOrder, v)
}