]> git.r.bdr.sh - rbdr/mobius/blame - hotline/transaction_handlers_test.go
Improve readability of client version in logs
[rbdr/mobius] / hotline / transaction_handlers_test.go
CommitLineData
6988a057
JH
1package hotline
2
3import (
decc2fbf 4 "errors"
9ebf276d 5 "fmt"
6988a057 6 "github.com/stretchr/testify/assert"
00d1ef67 7 "io/fs"
6988a057 8 "math/rand"
00d1ef67 9 "os"
f22acf38 10 "path/filepath"
decc2fbf 11 "strings"
6988a057 12 "testing"
7cd900d6 13 "time"
6988a057
JH
14)
15
16func TestHandleSetChatSubject(t *testing.T) {
17 type args struct {
18 cc *ClientConn
19 t *Transaction
20 }
21 tests := []struct {
22 name string
23 args args
24 want []Transaction
25 wantErr bool
26 }{
27 {
28 name: "sends chat subject to private chat members",
29 args: args{
30 cc: &ClientConn{
72dd37f1 31 UserName: []byte{0x00, 0x01},
6988a057
JH
32 Server: &Server{
33 PrivateChats: map[uint32]*PrivateChat{
34 uint32(1): {
35 Subject: "unset",
36 ClientConn: map[uint16]*ClientConn{
37 uint16(1): {
38 Account: &Account{
187d6dc5 39 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
40 },
41 ID: &[]byte{0, 1},
42 },
43 uint16(2): {
44 Account: &Account{
187d6dc5 45 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
46 },
47 ID: &[]byte{0, 2},
48 },
49 },
50 },
51 },
52 Clients: map[uint16]*ClientConn{
53 uint16(1): {
54 Account: &Account{
187d6dc5 55 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
56 },
57 ID: &[]byte{0, 1},
58 },
59 uint16(2): {
60 Account: &Account{
187d6dc5 61 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
62 },
63 ID: &[]byte{0, 2},
64 },
65 },
66 },
67 },
68 t: &Transaction{
69 Flags: 0x00,
70 IsReply: 0x00,
71 Type: []byte{0, 0x6a},
72 ID: []byte{0, 0, 0, 1},
73 ErrorCode: []byte{0, 0, 0, 0},
74 Fields: []Field{
75 NewField(fieldChatID, []byte{0, 0, 0, 1}),
76 NewField(fieldChatSubject, []byte("Test Subject")),
77 },
78 },
79 },
80 want: []Transaction{
81 {
82 clientID: &[]byte{0, 1},
83 Flags: 0x00,
84 IsReply: 0x00,
85 Type: []byte{0, 0x77},
86 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
87 ErrorCode: []byte{0, 0, 0, 0},
88 Fields: []Field{
89 NewField(fieldChatID, []byte{0, 0, 0, 1}),
90 NewField(fieldChatSubject, []byte("Test Subject")),
91 },
92 },
93 {
94 clientID: &[]byte{0, 2},
95 Flags: 0x00,
96 IsReply: 0x00,
97 Type: []byte{0, 0x77},
98 ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
99 ErrorCode: []byte{0, 0, 0, 0},
100 Fields: []Field{
101 NewField(fieldChatID, []byte{0, 0, 0, 1}),
102 NewField(fieldChatSubject, []byte("Test Subject")),
103 },
104 },
105 },
106 wantErr: false,
107 },
108 }
109 for _, tt := range tests {
110 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
111
112 t.Run(tt.name, func(t *testing.T) {
113 got, err := HandleSetChatSubject(tt.args.cc, tt.args.t)
114 if (err != nil) != tt.wantErr {
115 t.Errorf("HandleSetChatSubject() error = %v, wantErr %v", err, tt.wantErr)
116 return
117 }
118 if !assert.Equal(t, tt.want, got) {
119 t.Errorf("HandleSetChatSubject() got = %v, want %v", got, tt.want)
120 }
121 })
122 }
123}
124
125func TestHandleLeaveChat(t *testing.T) {
126 type args struct {
127 cc *ClientConn
128 t *Transaction
129 }
130 tests := []struct {
131 name string
132 args args
133 want []Transaction
134 wantErr bool
135 }{
136 {
137 name: "returns expected transactions",
138 args: args{
139 cc: &ClientConn{
140 ID: &[]byte{0, 2},
141 Server: &Server{
142 PrivateChats: map[uint32]*PrivateChat{
143 uint32(1): {
144 ClientConn: map[uint16]*ClientConn{
145 uint16(1): {
146 Account: &Account{
187d6dc5 147 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
148 },
149 ID: &[]byte{0, 1},
150 },
151 uint16(2): {
152 Account: &Account{
187d6dc5 153 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
154 },
155 ID: &[]byte{0, 2},
156 },
157 },
158 },
159 },
160 Clients: map[uint16]*ClientConn{
161 uint16(1): {
162 Account: &Account{
187d6dc5 163 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
164 },
165 ID: &[]byte{0, 1},
166 },
167 uint16(2): {
168 Account: &Account{
187d6dc5 169 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
170 },
171 ID: &[]byte{0, 2},
172 },
173 },
174 },
175 },
5c34f875 176 t: NewTransaction(tranDeleteUser, nil, NewField(fieldChatID, []byte{0, 0, 0, 1})),
6988a057
JH
177 },
178 want: []Transaction{
179 {
180 clientID: &[]byte{0, 1},
181 Flags: 0x00,
182 IsReply: 0x00,
183 Type: []byte{0, 0x76},
184 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
185 ErrorCode: []byte{0, 0, 0, 0},
186 Fields: []Field{
187 NewField(fieldChatID, []byte{0, 0, 0, 1}),
188 NewField(fieldUserID, []byte{0, 2}),
189 },
190 },
191 },
192 wantErr: false,
193 },
194 }
195 for _, tt := range tests {
196 rand.Seed(1)
197 t.Run(tt.name, func(t *testing.T) {
198 got, err := HandleLeaveChat(tt.args.cc, tt.args.t)
199 if (err != nil) != tt.wantErr {
200 t.Errorf("HandleLeaveChat() error = %v, wantErr %v", err, tt.wantErr)
201 return
202 }
203 if !assert.Equal(t, tt.want, got) {
204 t.Errorf("HandleLeaveChat() got = %v, want %v", got, tt.want)
205 }
206 })
207 }
208}
209
6988a057
JH
210func TestHandleGetUserNameList(t *testing.T) {
211 type args struct {
212 cc *ClientConn
213 t *Transaction
214 }
215 tests := []struct {
216 name string
217 args args
218 want []Transaction
219 wantErr bool
220 }{
221 {
222 name: "replies with userlist transaction",
223 args: args{
224 cc: &ClientConn{
225
226 ID: &[]byte{1, 1},
227 Server: &Server{
228 Clients: map[uint16]*ClientConn{
229 uint16(1): {
230 ID: &[]byte{0, 1},
a7216f67
JH
231 Icon: []byte{0, 2},
232 Flags: []byte{0, 3},
72dd37f1 233 UserName: []byte{0, 4},
bd1ce113 234 Agreed: true,
6988a057 235 },
c7e932c0
JH
236 uint16(2): {
237 ID: &[]byte{0, 2},
a7216f67
JH
238 Icon: []byte{0, 2},
239 Flags: []byte{0, 3},
c7e932c0 240 UserName: []byte{0, 4},
bd1ce113
JH
241 Agreed: true,
242 },
243 uint16(3): {
244 ID: &[]byte{0, 3},
a7216f67
JH
245 Icon: []byte{0, 2},
246 Flags: []byte{0, 3},
bd1ce113
JH
247 UserName: []byte{0, 4},
248 Agreed: false,
c7e932c0 249 },
6988a057
JH
250 },
251 },
252 },
253 t: &Transaction{
254 ID: []byte{0, 0, 0, 1},
255 Type: []byte{0, 1},
256 },
257 },
258 want: []Transaction{
259 {
260 clientID: &[]byte{1, 1},
261 Flags: 0x00,
262 IsReply: 0x01,
263 Type: []byte{0, 1},
264 ID: []byte{0, 0, 0, 1},
265 ErrorCode: []byte{0, 0, 0, 0},
266 Fields: []Field{
267 NewField(
268 fieldUsernameWithInfo,
269 []byte{00, 01, 00, 02, 00, 03, 00, 02, 00, 04},
270 ),
c7e932c0
JH
271 NewField(
272 fieldUsernameWithInfo,
273 []byte{00, 02, 00, 02, 00, 03, 00, 02, 00, 04},
274 ),
6988a057
JH
275 },
276 },
277 },
278 wantErr: false,
279 },
280 }
281 for _, tt := range tests {
282 t.Run(tt.name, func(t *testing.T) {
283 got, err := HandleGetUserNameList(tt.args.cc, tt.args.t)
284 if (err != nil) != tt.wantErr {
285 t.Errorf("HandleGetUserNameList() error = %v, wantErr %v", err, tt.wantErr)
286 return
287 }
bd1ce113 288 assert.Equal(t, tt.want, got)
6988a057
JH
289 })
290 }
291}
292
293func TestHandleChatSend(t *testing.T) {
294 type args struct {
295 cc *ClientConn
296 t *Transaction
297 }
298 tests := []struct {
299 name string
300 args args
301 want []Transaction
302 wantErr bool
303 }{
304 {
305 name: "sends chat msg transaction to all clients",
306 args: args{
307 cc: &ClientConn{
9ebf276d 308 Account: &Account{
187d6dc5 309 Access: func() accessBitmap {
9ebf276d
JH
310 var bits accessBitmap
311 bits.Set(accessSendChat)
187d6dc5 312 return bits
9ebf276d
JH
313 }(),
314 },
72dd37f1 315 UserName: []byte{0x00, 0x01},
6988a057
JH
316 Server: &Server{
317 Clients: map[uint16]*ClientConn{
318 uint16(1): {
319 Account: &Account{
187d6dc5 320 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
321 },
322 ID: &[]byte{0, 1},
323 },
324 uint16(2): {
325 Account: &Account{
187d6dc5 326 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
6988a057
JH
327 },
328 ID: &[]byte{0, 2},
329 },
330 },
331 },
332 },
333 t: &Transaction{
334 Fields: []Field{
335 NewField(fieldData, []byte("hai")),
336 },
337 },
338 },
339 want: []Transaction{
340 {
341 clientID: &[]byte{0, 1},
342 Flags: 0x00,
343 IsReply: 0x00,
344 Type: []byte{0, 0x6a},
345 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
346 ErrorCode: []byte{0, 0, 0, 0},
347 Fields: []Field{
348 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
349 },
350 },
351 {
352 clientID: &[]byte{0, 2},
353 Flags: 0x00,
354 IsReply: 0x00,
355 Type: []byte{0, 0x6a},
356 ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
357 ErrorCode: []byte{0, 0, 0, 0},
358 Fields: []Field{
359 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
360 },
361 },
362 },
363 wantErr: false,
364 },
9ebf276d
JH
365 {
366 name: "when user does not have required permission",
367 args: args{
368 cc: &ClientConn{
369 Account: &Account{
187d6dc5 370 Access: func() accessBitmap {
9ebf276d 371 var bits accessBitmap
187d6dc5 372 return bits
9ebf276d
JH
373 }(),
374 },
375 Server: &Server{
376 Accounts: map[string]*Account{},
377 },
378 },
379 t: NewTransaction(
380 tranChatSend, &[]byte{0, 1},
381 NewField(fieldData, []byte("hai")),
382 ),
383 },
384 want: []Transaction{
385 {
386 Flags: 0x00,
387 IsReply: 0x01,
388 Type: []byte{0, 0x00},
389 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
390 ErrorCode: []byte{0, 0, 0, 1},
391 Fields: []Field{
392 NewField(fieldError, []byte("You are not allowed to participate in chat.")),
393 },
394 },
395 },
396 wantErr: false,
397 },
72dd37f1
JH
398 {
399 name: "sends chat msg as emote if fieldChatOptions is set",
400 args: args{
401 cc: &ClientConn{
9ebf276d 402 Account: &Account{
187d6dc5 403 Access: func() accessBitmap {
9ebf276d
JH
404 var bits accessBitmap
405 bits.Set(accessSendChat)
187d6dc5 406 return bits
9ebf276d
JH
407 }(),
408 },
72dd37f1
JH
409 UserName: []byte("Testy McTest"),
410 Server: &Server{
411 Clients: map[uint16]*ClientConn{
412 uint16(1): {
413 Account: &Account{
187d6dc5 414 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
72dd37f1
JH
415 },
416 ID: &[]byte{0, 1},
417 },
418 uint16(2): {
419 Account: &Account{
187d6dc5 420 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
72dd37f1
JH
421 },
422 ID: &[]byte{0, 2},
423 },
424 },
425 },
426 },
427 t: &Transaction{
428 Fields: []Field{
429 NewField(fieldData, []byte("performed action")),
430 NewField(fieldChatOptions, []byte{0x00, 0x01}),
431 },
432 },
433 },
434 want: []Transaction{
435 {
436 clientID: &[]byte{0, 1},
437 Flags: 0x00,
438 IsReply: 0x00,
439 Type: []byte{0, 0x6a},
481631f6 440 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
72dd37f1
JH
441 ErrorCode: []byte{0, 0, 0, 0},
442 Fields: []Field{
443 NewField(fieldData, []byte("\r*** Testy McTest performed action")),
444 },
445 },
446 {
447 clientID: &[]byte{0, 2},
448 Flags: 0x00,
449 IsReply: 0x00,
450 Type: []byte{0, 0x6a},
481631f6 451 ID: []byte{0xf0, 0xc5, 0x34, 0x1e},
72dd37f1
JH
452 ErrorCode: []byte{0, 0, 0, 0},
453 Fields: []Field{
454 NewField(fieldData, []byte("\r*** Testy McTest performed action")),
455 },
456 },
457 },
458 wantErr: false,
459 },
6988a057
JH
460 {
461 name: "only sends chat msg to clients with accessReadChat permission",
462 args: args{
463 cc: &ClientConn{
9ebf276d 464 Account: &Account{
187d6dc5 465 Access: func() accessBitmap {
9ebf276d
JH
466 var bits accessBitmap
467 bits.Set(accessSendChat)
187d6dc5 468 return bits
9ebf276d
JH
469 }(),
470 },
72dd37f1 471 UserName: []byte{0x00, 0x01},
6988a057
JH
472 Server: &Server{
473 Clients: map[uint16]*ClientConn{
474 uint16(1): {
475 Account: &Account{
187d6dc5
JH
476 Access: func() accessBitmap {
477 var bits accessBitmap
478 bits.Set(accessReadChat)
479 return bits
480 }()},
6988a057
JH
481 ID: &[]byte{0, 1},
482 },
483 uint16(2): {
484 Account: &Account{
187d6dc5 485 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
6988a057
JH
486 },
487 ID: &[]byte{0, 2},
488 },
489 },
490 },
491 },
492 t: &Transaction{
493 Fields: []Field{
494 NewField(fieldData, []byte("hai")),
495 },
496 },
497 },
498 want: []Transaction{
499 {
500 clientID: &[]byte{0, 1},
501 Flags: 0x00,
502 IsReply: 0x00,
503 Type: []byte{0, 0x6a},
504 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
505 ErrorCode: []byte{0, 0, 0, 0},
506 Fields: []Field{
507 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
508 },
509 },
510 },
511 wantErr: false,
512 },
481631f6
JH
513 {
514 name: "only sends private chat msg to members of private chat",
515 args: args{
516 cc: &ClientConn{
517 Account: &Account{
187d6dc5 518 Access: func() accessBitmap {
481631f6
JH
519 var bits accessBitmap
520 bits.Set(accessSendChat)
187d6dc5 521 return bits
481631f6
JH
522 }(),
523 },
524 UserName: []byte{0x00, 0x01},
525 Server: &Server{
526 PrivateChats: map[uint32]*PrivateChat{
527 uint32(1): {
528 ClientConn: map[uint16]*ClientConn{
529 uint16(1): {
530 ID: &[]byte{0, 1},
531 },
532 uint16(2): {
533 ID: &[]byte{0, 2},
534 },
535 },
536 },
537 },
538 Clients: map[uint16]*ClientConn{
539 uint16(1): {
540 Account: &Account{
187d6dc5 541 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
481631f6
JH
542 },
543 ID: &[]byte{0, 1},
544 },
545 uint16(2): {
546 Account: &Account{
187d6dc5 547 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
481631f6
JH
548 },
549 ID: &[]byte{0, 2},
550 },
551 uint16(3): {
552 Account: &Account{
187d6dc5 553 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
481631f6
JH
554 },
555 ID: &[]byte{0, 3},
556 },
557 },
558 },
559 },
560 t: &Transaction{
561 Fields: []Field{
562 NewField(fieldData, []byte("hai")),
563 NewField(fieldChatID, []byte{0, 0, 0, 1}),
564 },
565 },
566 },
567 want: []Transaction{
568 {
569 clientID: &[]byte{0, 1},
570 Flags: 0x00,
571 IsReply: 0x00,
572 Type: []byte{0, 0x6a},
573 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
574 ErrorCode: []byte{0, 0, 0, 0},
575 Fields: []Field{
576 NewField(fieldChatID, []byte{0, 0, 0, 1}),
577 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
578 },
579 },
580 {
581 clientID: &[]byte{0, 2},
582 Flags: 0x00,
583 IsReply: 0x00,
584 Type: []byte{0, 0x6a},
585 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
586 ErrorCode: []byte{0, 0, 0, 0},
587 Fields: []Field{
588 NewField(fieldChatID, []byte{0, 0, 0, 1}),
589 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
590 },
591 },
592 },
593 wantErr: false,
594 },
6988a057
JH
595 }
596 for _, tt := range tests {
6988a057
JH
597 t.Run(tt.name, func(t *testing.T) {
598 got, err := HandleChatSend(tt.args.cc, tt.args.t)
599
600 if (err != nil) != tt.wantErr {
601 t.Errorf("HandleChatSend() error = %v, wantErr %v", err, tt.wantErr)
602 return
603 }
9ebf276d 604 tranAssertEqual(t, tt.want, got)
6988a057
JH
605 })
606 }
607}
72dd37f1
JH
608
609func TestHandleGetFileInfo(t *testing.T) {
610 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
611
612 type args struct {
613 cc *ClientConn
614 t *Transaction
615 }
616 tests := []struct {
617 name string
618 args args
619 wantRes []Transaction
620 wantErr bool
621 }{
622 {
623 name: "returns expected fields when a valid file is requested",
624 args: args{
625 cc: &ClientConn{
626 ID: &[]byte{0x00, 0x01},
627 Server: &Server{
7cd900d6 628 FS: &OSFileStore{},
72dd37f1 629 Config: &Config{
29f329ae
JH
630 FileRoot: func() string {
631 path, _ := os.Getwd()
f22acf38 632 return filepath.Join(path, "/test/config/Files")
29f329ae 633 }(),
72dd37f1
JH
634 },
635 },
636 },
637 t: NewTransaction(
638 tranGetFileInfo, nil,
639 NewField(fieldFileName, []byte("testfile.txt")),
640 NewField(fieldFilePath, []byte{0x00, 0x00}),
72dd37f1
JH
641 ),
642 },
643 wantRes: []Transaction{
644 {
645 clientID: &[]byte{0, 1},
646 Flags: 0x00,
647 IsReply: 0x01,
648 Type: []byte{0, 0xce},
649 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
650 ErrorCode: []byte{0, 0, 0, 0},
651 Fields: []Field{
652 NewField(fieldFileName, []byte("testfile.txt")),
2d52424e 653 NewField(fieldFileTypeString, []byte("Text File")),
2728d12b 654 NewField(fieldFileCreatorString, []byte("ttxt")),
5218c782 655 NewField(fieldFileComment, []byte{}),
72dd37f1 656 NewField(fieldFileType, []byte("TEXT")),
29f329ae
JH
657 NewField(fieldFileCreateDate, make([]byte, 8)),
658 NewField(fieldFileModifyDate, make([]byte, 8)),
72dd37f1
JH
659 NewField(fieldFileSize, []byte{0x0, 0x0, 0x0, 0x17}),
660 },
661 },
662 },
663 wantErr: false,
664 },
665 }
666 for _, tt := range tests {
667 t.Run(tt.name, func(t *testing.T) {
668 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
669
670 gotRes, err := HandleGetFileInfo(tt.args.cc, tt.args.t)
671 if (err != nil) != tt.wantErr {
672 t.Errorf("HandleGetFileInfo() error = %v, wantErr %v", err, tt.wantErr)
673 return
674 }
29f329ae 675
7cd900d6 676 // Clear the fileWrapper timestamp fields to work around problems running the tests in multiple timezones
29f329ae
JH
677 // TODO: revisit how to test this by mocking the stat calls
678 gotRes[0].Fields[5].Data = make([]byte, 8)
679 gotRes[0].Fields[6].Data = make([]byte, 8)
00d1ef67 680 if !assert.Equal(t, tt.wantRes, gotRes) {
72dd37f1
JH
681 t.Errorf("HandleGetFileInfo() gotRes = %v, want %v", gotRes, tt.wantRes)
682 }
683 })
684 }
685}
00d1ef67
JH
686
687func TestHandleNewFolder(t *testing.T) {
688 type args struct {
689 cc *ClientConn
690 t *Transaction
691 }
692 tests := []struct {
00d1ef67
JH
693 name string
694 args args
695 wantRes []Transaction
696 wantErr bool
697 }{
d4c152a4 698 {
b196a50a 699 name: "without required permission",
d4c152a4
JH
700 args: args{
701 cc: &ClientConn{
702 Account: &Account{
187d6dc5 703 Access: func() accessBitmap {
d4c152a4 704 var bits accessBitmap
187d6dc5 705 return bits
d4c152a4
JH
706 }(),
707 },
708 },
709 t: NewTransaction(
710 accessCreateFolder,
711 &[]byte{0, 0},
712 ),
713 },
714 wantRes: []Transaction{
715 {
716 Flags: 0x00,
717 IsReply: 0x01,
718 Type: []byte{0, 0x00},
719 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
720 ErrorCode: []byte{0, 0, 0, 1},
721 Fields: []Field{
722 NewField(fieldError, []byte("You are not allowed to create folders.")),
723 },
724 },
725 },
726 wantErr: false,
727 },
00d1ef67
JH
728 {
729 name: "when path is nested",
730 args: args{
731 cc: &ClientConn{
d4c152a4 732 Account: &Account{
187d6dc5 733 Access: func() accessBitmap {
d4c152a4
JH
734 var bits accessBitmap
735 bits.Set(accessCreateFolder)
187d6dc5 736 return bits
d4c152a4
JH
737 }(),
738 },
00d1ef67
JH
739 ID: &[]byte{0, 1},
740 Server: &Server{
741 Config: &Config{
742 FileRoot: "/Files/",
743 },
b196a50a
JH
744 FS: func() *MockFileStore {
745 mfs := &MockFileStore{}
746 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
747 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
748 return mfs
749 }(),
00d1ef67
JH
750 },
751 },
752 t: NewTransaction(
753 tranNewFolder, &[]byte{0, 1},
754 NewField(fieldFileName, []byte("testFolder")),
755 NewField(fieldFilePath, []byte{
756 0x00, 0x01,
757 0x00, 0x00,
758 0x03,
759 0x61, 0x61, 0x61,
760 }),
761 ),
762 },
00d1ef67
JH
763 wantRes: []Transaction{
764 {
765 clientID: &[]byte{0, 1},
766 Flags: 0x00,
767 IsReply: 0x01,
768 Type: []byte{0, 0xcd},
769 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
770 ErrorCode: []byte{0, 0, 0, 0},
771 },
772 },
773 wantErr: false,
774 },
775 {
776 name: "when path is not nested",
777 args: args{
778 cc: &ClientConn{
d4c152a4 779 Account: &Account{
187d6dc5 780 Access: func() accessBitmap {
d4c152a4
JH
781 var bits accessBitmap
782 bits.Set(accessCreateFolder)
187d6dc5 783 return bits
d4c152a4
JH
784 }(),
785 },
00d1ef67
JH
786 ID: &[]byte{0, 1},
787 Server: &Server{
788 Config: &Config{
789 FileRoot: "/Files",
790 },
b196a50a
JH
791 FS: func() *MockFileStore {
792 mfs := &MockFileStore{}
793 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
794 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
795 return mfs
796 }(),
00d1ef67
JH
797 },
798 },
799 t: NewTransaction(
800 tranNewFolder, &[]byte{0, 1},
801 NewField(fieldFileName, []byte("testFolder")),
802 ),
803 },
00d1ef67
JH
804 wantRes: []Transaction{
805 {
806 clientID: &[]byte{0, 1},
807 Flags: 0x00,
808 IsReply: 0x01,
809 Type: []byte{0, 0xcd},
810 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
811 ErrorCode: []byte{0, 0, 0, 0},
812 },
813 },
814 wantErr: false,
815 },
816 {
8fc43f8e 817 name: "when Write returns an err",
00d1ef67
JH
818 args: args{
819 cc: &ClientConn{
d4c152a4 820 Account: &Account{
187d6dc5 821 Access: func() accessBitmap {
d4c152a4
JH
822 var bits accessBitmap
823 bits.Set(accessCreateFolder)
187d6dc5 824 return bits
d4c152a4
JH
825 }(),
826 },
00d1ef67
JH
827 ID: &[]byte{0, 1},
828 Server: &Server{
829 Config: &Config{
830 FileRoot: "/Files/",
831 },
b196a50a
JH
832 FS: func() *MockFileStore {
833 mfs := &MockFileStore{}
834 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
835 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
836 return mfs
837 }(),
00d1ef67
JH
838 },
839 },
840 t: NewTransaction(
841 tranNewFolder, &[]byte{0, 1},
842 NewField(fieldFileName, []byte("testFolder")),
843 NewField(fieldFilePath, []byte{
844 0x00,
845 }),
846 ),
847 },
00d1ef67
JH
848 wantRes: []Transaction{},
849 wantErr: true,
850 },
851 {
852 name: "fieldFileName does not allow directory traversal",
853 args: args{
854 cc: &ClientConn{
d4c152a4 855 Account: &Account{
187d6dc5 856 Access: func() accessBitmap {
d4c152a4
JH
857 var bits accessBitmap
858 bits.Set(accessCreateFolder)
187d6dc5 859 return bits
d4c152a4
JH
860 }(),
861 },
00d1ef67
JH
862 ID: &[]byte{0, 1},
863 Server: &Server{
864 Config: &Config{
865 FileRoot: "/Files/",
866 },
b196a50a
JH
867 FS: func() *MockFileStore {
868 mfs := &MockFileStore{}
869 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
870 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
871 return mfs
872 }(),
00d1ef67
JH
873 },
874 },
875 t: NewTransaction(
876 tranNewFolder, &[]byte{0, 1},
877 NewField(fieldFileName, []byte("../../testFolder")),
00d1ef67
JH
878 ),
879 },
00d1ef67
JH
880 wantRes: []Transaction{
881 {
882 clientID: &[]byte{0, 1},
883 Flags: 0x00,
884 IsReply: 0x01,
885 Type: []byte{0, 0xcd},
886 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
887 ErrorCode: []byte{0, 0, 0, 0},
888 },
92a7e455 889 }, wantErr: false,
00d1ef67
JH
890 },
891 {
892 name: "fieldFilePath does not allow directory traversal",
893 args: args{
894 cc: &ClientConn{
d4c152a4 895 Account: &Account{
187d6dc5 896 Access: func() accessBitmap {
d4c152a4
JH
897 var bits accessBitmap
898 bits.Set(accessCreateFolder)
187d6dc5 899 return bits
d4c152a4
JH
900 }(),
901 },
00d1ef67
JH
902 ID: &[]byte{0, 1},
903 Server: &Server{
904 Config: &Config{
905 FileRoot: "/Files/",
906 },
b196a50a
JH
907 FS: func() *MockFileStore {
908 mfs := &MockFileStore{}
909 mfs.On("Mkdir", "/Files/foo/testFolder", fs.FileMode(0777)).Return(nil)
910 mfs.On("Stat", "/Files/foo/testFolder").Return(nil, os.ErrNotExist)
911 return mfs
912 }(),
00d1ef67
JH
913 },
914 },
915 t: NewTransaction(
916 tranNewFolder, &[]byte{0, 1},
917 NewField(fieldFileName, []byte("testFolder")),
918 NewField(fieldFilePath, []byte{
919 0x00, 0x02,
920 0x00, 0x00,
921 0x03,
922 0x2e, 0x2e, 0x2f,
923 0x00, 0x00,
924 0x03,
925 0x66, 0x6f, 0x6f,
926 }),
927 ),
928 },
00d1ef67
JH
929 wantRes: []Transaction{
930 {
931 clientID: &[]byte{0, 1},
932 Flags: 0x00,
933 IsReply: 0x01,
934 Type: []byte{0, 0xcd},
935 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
936 ErrorCode: []byte{0, 0, 0, 0},
937 },
92a7e455 938 }, wantErr: false,
00d1ef67
JH
939 },
940 }
941 for _, tt := range tests {
942 t.Run(tt.name, func(t *testing.T) {
00d1ef67
JH
943
944 gotRes, err := HandleNewFolder(tt.args.cc, tt.args.t)
945 if (err != nil) != tt.wantErr {
946 t.Errorf("HandleNewFolder() error = %v, wantErr %v", err, tt.wantErr)
947 return
948 }
d4c152a4 949
00d1ef67
JH
950 if !tranAssertEqual(t, tt.wantRes, gotRes) {
951 t.Errorf("HandleNewFolder() gotRes = %v, want %v", gotRes, tt.wantRes)
952 }
953 })
954 }
955}
956
92a7e455
JH
957func TestHandleUploadFile(t *testing.T) {
958 type args struct {
959 cc *ClientConn
960 t *Transaction
961 }
962 tests := []struct {
963 name string
964 args args
965 wantRes []Transaction
966 wantErr bool
967 }{
968 {
7e2e07da 969 name: "when request is valid and user has Upload Anywhere permission",
92a7e455
JH
970 args: args{
971 cc: &ClientConn{
972 Server: &Server{
df1ade54
JH
973 FS: &OSFileStore{},
974 fileTransfers: map[[4]byte]*FileTransfer{},
975 Config: &Config{
976 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
977 }},
978 transfers: map[int]map[[4]byte]*FileTransfer{
979 FileUpload: {},
92a7e455
JH
980 },
981 Account: &Account{
187d6dc5 982 Access: func() accessBitmap {
92a7e455
JH
983 var bits accessBitmap
984 bits.Set(accessUploadFile)
7e2e07da 985 bits.Set(accessUploadAnywhere)
187d6dc5 986 return bits
92a7e455
JH
987 }(),
988 },
989 },
990 t: NewTransaction(
991 tranUploadFile, &[]byte{0, 1},
992 NewField(fieldFileName, []byte("testFile")),
993 NewField(fieldFilePath, []byte{
994 0x00, 0x01,
995 0x00, 0x00,
996 0x03,
997 0x2e, 0x2e, 0x2f,
998 }),
999 ),
1000 },
1001 wantRes: []Transaction{
1002 {
1003 Flags: 0x00,
1004 IsReply: 0x01,
1005 Type: []byte{0, 0xcb},
1006 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1007 ErrorCode: []byte{0, 0, 0, 0},
1008 Fields: []Field{
1009 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}), // rand.Seed(1)
1010 },
1011 },
1012 },
1013 wantErr: false,
1014 },
1015 {
1016 name: "when user does not have required access",
1017 args: args{
1018 cc: &ClientConn{
1019 Account: &Account{
187d6dc5 1020 Access: func() accessBitmap {
92a7e455 1021 var bits accessBitmap
187d6dc5 1022 return bits
92a7e455
JH
1023 }(),
1024 },
92a7e455
JH
1025 },
1026 t: NewTransaction(
1027 tranUploadFile, &[]byte{0, 1},
1028 NewField(fieldFileName, []byte("testFile")),
1029 NewField(fieldFilePath, []byte{
1030 0x00, 0x01,
1031 0x00, 0x00,
1032 0x03,
1033 0x2e, 0x2e, 0x2f,
1034 }),
1035 ),
1036 },
1037 wantRes: []Transaction{
1038 {
1039 Flags: 0x00,
1040 IsReply: 0x01,
1041 Type: []byte{0, 0x00},
1042 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1043 ErrorCode: []byte{0, 0, 0, 1},
1044 Fields: []Field{
1045 NewField(fieldError, []byte("You are not allowed to upload files.")), // rand.Seed(1)
1046 },
1047 },
1048 },
1049 wantErr: false,
1050 },
1051 }
1052 for _, tt := range tests {
1053 t.Run(tt.name, func(t *testing.T) {
1054 rand.Seed(1)
1055 gotRes, err := HandleUploadFile(tt.args.cc, tt.args.t)
1056 if (err != nil) != tt.wantErr {
1057 t.Errorf("HandleUploadFile() error = %v, wantErr %v", err, tt.wantErr)
1058 return
1059 }
aebc4d36
JH
1060
1061 tranAssertEqual(t, tt.wantRes, gotRes)
1062
92a7e455
JH
1063 })
1064 }
1065}
decc2fbf
JH
1066
1067func TestHandleMakeAlias(t *testing.T) {
1068 type args struct {
1069 cc *ClientConn
1070 t *Transaction
1071 }
1072 tests := []struct {
1073 name string
decc2fbf
JH
1074 args args
1075 wantRes []Transaction
1076 wantErr bool
1077 }{
1078 {
1079 name: "with valid input and required permissions",
decc2fbf
JH
1080 args: args{
1081 cc: &ClientConn{
02b446d8 1082 logger: NewTestLogger(),
decc2fbf 1083 Account: &Account{
187d6dc5 1084 Access: func() accessBitmap {
decc2fbf
JH
1085 var bits accessBitmap
1086 bits.Set(accessMakeAlias)
187d6dc5 1087 return bits
decc2fbf
JH
1088 }(),
1089 },
1090 Server: &Server{
1091 Config: &Config{
1092 FileRoot: func() string {
1093 path, _ := os.Getwd()
1094 return path + "/test/config/Files"
1095 }(),
1096 },
1097 Logger: NewTestLogger(),
b196a50a
JH
1098 FS: func() *MockFileStore {
1099 mfs := &MockFileStore{}
1100 path, _ := os.Getwd()
1101 mfs.On(
1102 "Symlink",
1103 path+"/test/config/Files/foo/testFile",
1104 path+"/test/config/Files/bar/testFile",
1105 ).Return(nil)
1106 return mfs
1107 }(),
decc2fbf
JH
1108 },
1109 },
1110 t: NewTransaction(
1111 tranMakeFileAlias, &[]byte{0, 1},
1112 NewField(fieldFileName, []byte("testFile")),
1113 NewField(fieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1114 NewField(fieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1115 ),
1116 },
1117 wantRes: []Transaction{
1118 {
1119 Flags: 0x00,
1120 IsReply: 0x01,
1121 Type: []byte{0, 0xd1},
1122 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1123 ErrorCode: []byte{0, 0, 0, 0},
1124 Fields: []Field(nil),
1125 },
1126 },
1127 wantErr: false,
1128 },
1129 {
1130 name: "when symlink returns an error",
decc2fbf
JH
1131 args: args{
1132 cc: &ClientConn{
02b446d8 1133 logger: NewTestLogger(),
decc2fbf 1134 Account: &Account{
187d6dc5 1135 Access: func() accessBitmap {
decc2fbf
JH
1136 var bits accessBitmap
1137 bits.Set(accessMakeAlias)
187d6dc5 1138 return bits
decc2fbf
JH
1139 }(),
1140 },
1141 Server: &Server{
1142 Config: &Config{
1143 FileRoot: func() string {
1144 path, _ := os.Getwd()
1145 return path + "/test/config/Files"
1146 }(),
1147 },
1148 Logger: NewTestLogger(),
b196a50a
JH
1149 FS: func() *MockFileStore {
1150 mfs := &MockFileStore{}
1151 path, _ := os.Getwd()
1152 mfs.On(
1153 "Symlink",
1154 path+"/test/config/Files/foo/testFile",
1155 path+"/test/config/Files/bar/testFile",
1156 ).Return(errors.New("ohno"))
1157 return mfs
1158 }(),
decc2fbf
JH
1159 },
1160 },
1161 t: NewTransaction(
1162 tranMakeFileAlias, &[]byte{0, 1},
1163 NewField(fieldFileName, []byte("testFile")),
1164 NewField(fieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1165 NewField(fieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1166 ),
1167 },
1168 wantRes: []Transaction{
1169 {
1170 Flags: 0x00,
1171 IsReply: 0x01,
1172 Type: []byte{0, 0x00},
1173 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1174 ErrorCode: []byte{0, 0, 0, 1},
1175 Fields: []Field{
1176 NewField(fieldError, []byte("Error creating alias")),
1177 },
1178 },
1179 },
1180 wantErr: false,
1181 },
1182 {
b196a50a 1183 name: "when user does not have required permission",
decc2fbf
JH
1184 args: args{
1185 cc: &ClientConn{
02b446d8 1186 logger: NewTestLogger(),
decc2fbf 1187 Account: &Account{
187d6dc5 1188 Access: func() accessBitmap {
decc2fbf 1189 var bits accessBitmap
187d6dc5 1190 return bits
decc2fbf
JH
1191 }(),
1192 },
1193 Server: &Server{
1194 Config: &Config{
1195 FileRoot: func() string {
1196 path, _ := os.Getwd()
1197 return path + "/test/config/Files"
1198 }(),
1199 },
1200 },
1201 },
1202 t: NewTransaction(
1203 tranMakeFileAlias, &[]byte{0, 1},
1204 NewField(fieldFileName, []byte("testFile")),
1205 NewField(fieldFilePath, []byte{
1206 0x00, 0x01,
1207 0x00, 0x00,
1208 0x03,
1209 0x2e, 0x2e, 0x2e,
1210 }),
1211 NewField(fieldFileNewPath, []byte{
1212 0x00, 0x01,
1213 0x00, 0x00,
1214 0x03,
1215 0x2e, 0x2e, 0x2e,
1216 }),
1217 ),
1218 },
1219 wantRes: []Transaction{
1220 {
1221 Flags: 0x00,
1222 IsReply: 0x01,
1223 Type: []byte{0, 0x00},
1224 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1225 ErrorCode: []byte{0, 0, 0, 1},
1226 Fields: []Field{
1227 NewField(fieldError, []byte("You are not allowed to make aliases.")),
1228 },
1229 },
1230 },
1231 wantErr: false,
1232 },
1233 }
1234 for _, tt := range tests {
1235 t.Run(tt.name, func(t *testing.T) {
decc2fbf
JH
1236 gotRes, err := HandleMakeAlias(tt.args.cc, tt.args.t)
1237 if (err != nil) != tt.wantErr {
1238 t.Errorf("HandleMakeAlias(%v, %v)", tt.args.cc, tt.args.t)
1239 return
1240 }
1241
1242 tranAssertEqual(t, tt.wantRes, gotRes)
1243 })
1244 }
1245}
9ebf276d
JH
1246
1247func TestHandleGetUser(t *testing.T) {
1248 type args struct {
1249 cc *ClientConn
1250 t *Transaction
1251 }
1252 tests := []struct {
1253 name string
1254 args args
1255 wantRes []Transaction
1256 wantErr assert.ErrorAssertionFunc
1257 }{
1258 {
1259 name: "when account is valid",
1260 args: args{
1261 cc: &ClientConn{
1262 Account: &Account{
187d6dc5 1263 Access: func() accessBitmap {
9ebf276d
JH
1264 var bits accessBitmap
1265 bits.Set(accessOpenUser)
187d6dc5 1266 return bits
9ebf276d
JH
1267 }(),
1268 },
1269 Server: &Server{
1270 Accounts: map[string]*Account{
1271 "guest": {
1272 Login: "guest",
1273 Name: "Guest",
1274 Password: "password",
187d6dc5 1275 Access: accessBitmap{},
9ebf276d
JH
1276 },
1277 },
1278 },
1279 },
1280 t: NewTransaction(
1281 tranGetUser, &[]byte{0, 1},
1282 NewField(fieldUserLogin, []byte("guest")),
1283 ),
1284 },
1285 wantRes: []Transaction{
1286 {
1287 Flags: 0x00,
1288 IsReply: 0x01,
1289 Type: []byte{0x01, 0x60},
1290 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1291 ErrorCode: []byte{0, 0, 0, 0},
1292 Fields: []Field{
1293 NewField(fieldUserName, []byte("Guest")),
1294 NewField(fieldUserLogin, negateString([]byte("guest"))),
1295 NewField(fieldUserPassword, []byte("password")),
187d6dc5 1296 NewField(fieldUserAccess, []byte{0, 0, 0, 0, 0, 0, 0, 0}),
9ebf276d
JH
1297 },
1298 },
1299 },
1300 wantErr: assert.NoError,
1301 },
1302 {
1303 name: "when user does not have required permission",
1304 args: args{
1305 cc: &ClientConn{
1306 Account: &Account{
187d6dc5 1307 Access: func() accessBitmap {
9ebf276d 1308 var bits accessBitmap
187d6dc5 1309 return bits
9ebf276d
JH
1310 }(),
1311 },
1312 Server: &Server{
1313 Accounts: map[string]*Account{},
1314 },
1315 },
1316 t: NewTransaction(
1317 tranGetUser, &[]byte{0, 1},
1318 NewField(fieldUserLogin, []byte("nonExistentUser")),
1319 ),
1320 },
1321 wantRes: []Transaction{
1322 {
1323 Flags: 0x00,
1324 IsReply: 0x01,
1325 Type: []byte{0, 0x00},
1326 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1327 ErrorCode: []byte{0, 0, 0, 1},
1328 Fields: []Field{
1329 NewField(fieldError, []byte("You are not allowed to view accounts.")),
1330 },
1331 },
1332 },
1333 wantErr: assert.NoError,
1334 },
1335 {
1336 name: "when account does not exist",
1337 args: args{
1338 cc: &ClientConn{
1339 Account: &Account{
187d6dc5 1340 Access: func() accessBitmap {
9ebf276d
JH
1341 var bits accessBitmap
1342 bits.Set(accessOpenUser)
187d6dc5 1343 return bits
9ebf276d
JH
1344 }(),
1345 },
1346 Server: &Server{
1347 Accounts: map[string]*Account{},
1348 },
1349 },
1350 t: NewTransaction(
1351 tranGetUser, &[]byte{0, 1},
1352 NewField(fieldUserLogin, []byte("nonExistentUser")),
1353 ),
1354 },
1355 wantRes: []Transaction{
1356 {
1357 Flags: 0x00,
1358 IsReply: 0x01,
1359 Type: []byte{0, 0x00},
1360 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1361 ErrorCode: []byte{0, 0, 0, 1},
1362 Fields: []Field{
1363 NewField(fieldError, []byte("Account does not exist.")),
1364 },
1365 },
1366 },
1367 wantErr: assert.NoError,
1368 },
1369 }
1370 for _, tt := range tests {
1371 t.Run(tt.name, func(t *testing.T) {
1372 gotRes, err := HandleGetUser(tt.args.cc, tt.args.t)
1373 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetUser(%v, %v)", tt.args.cc, tt.args.t)) {
1374 return
1375 }
1376
1377 tranAssertEqual(t, tt.wantRes, gotRes)
1378 })
1379 }
1380}
1381
1382func TestHandleDeleteUser(t *testing.T) {
1383 type args struct {
1384 cc *ClientConn
1385 t *Transaction
1386 }
1387 tests := []struct {
1388 name string
9ebf276d
JH
1389 args args
1390 wantRes []Transaction
1391 wantErr assert.ErrorAssertionFunc
1392 }{
1393 {
7cd900d6 1394 name: "when user dataFile",
9ebf276d
JH
1395 args: args{
1396 cc: &ClientConn{
1397 Account: &Account{
187d6dc5 1398 Access: func() accessBitmap {
9ebf276d
JH
1399 var bits accessBitmap
1400 bits.Set(accessDeleteUser)
187d6dc5 1401 return bits
9ebf276d
JH
1402 }(),
1403 },
1404 Server: &Server{
1405 Accounts: map[string]*Account{
1406 "testuser": {
1407 Login: "testuser",
1408 Name: "Testy McTest",
1409 Password: "password",
187d6dc5 1410 Access: accessBitmap{},
9ebf276d
JH
1411 },
1412 },
b196a50a
JH
1413 FS: func() *MockFileStore {
1414 mfs := &MockFileStore{}
1415 mfs.On("Remove", "Users/testuser.yaml").Return(nil)
1416 return mfs
1417 }(),
9ebf276d
JH
1418 },
1419 },
1420 t: NewTransaction(
1421 tranDeleteUser, &[]byte{0, 1},
1422 NewField(fieldUserLogin, negateString([]byte("testuser"))),
1423 ),
1424 },
1425 wantRes: []Transaction{
1426 {
1427 Flags: 0x00,
1428 IsReply: 0x01,
1429 Type: []byte{0x1, 0x5f},
1430 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1431 ErrorCode: []byte{0, 0, 0, 0},
1432 Fields: []Field(nil),
1433 },
1434 },
1435 wantErr: assert.NoError,
1436 },
1437 {
b196a50a 1438 name: "when user does not have required permission",
9ebf276d
JH
1439 args: args{
1440 cc: &ClientConn{
1441 Account: &Account{
187d6dc5 1442 Access: func() accessBitmap {
9ebf276d 1443 var bits accessBitmap
187d6dc5 1444 return bits
9ebf276d
JH
1445 }(),
1446 },
1447 Server: &Server{
1448 Accounts: map[string]*Account{},
1449 },
1450 },
1451 t: NewTransaction(
1452 tranDeleteUser, &[]byte{0, 1},
1453 NewField(fieldUserLogin, negateString([]byte("testuser"))),
1454 ),
1455 },
1456 wantRes: []Transaction{
1457 {
1458 Flags: 0x00,
1459 IsReply: 0x01,
1460 Type: []byte{0, 0x00},
1461 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1462 ErrorCode: []byte{0, 0, 0, 1},
1463 Fields: []Field{
1464 NewField(fieldError, []byte("You are not allowed to delete accounts.")),
1465 },
1466 },
1467 },
1468 wantErr: assert.NoError,
1469 },
1470 }
1471 for _, tt := range tests {
1472 t.Run(tt.name, func(t *testing.T) {
9ebf276d
JH
1473 gotRes, err := HandleDeleteUser(tt.args.cc, tt.args.t)
1474 if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteUser(%v, %v)", tt.args.cc, tt.args.t)) {
1475 return
1476 }
1477
1478 tranAssertEqual(t, tt.wantRes, gotRes)
1479 })
1480 }
1481}
481631f6
JH
1482
1483func TestHandleGetMsgs(t *testing.T) {
1484 type args struct {
1485 cc *ClientConn
1486 t *Transaction
1487 }
1488 tests := []struct {
1489 name string
1490 args args
1491 wantRes []Transaction
1492 wantErr assert.ErrorAssertionFunc
1493 }{
1494 {
1495 name: "returns news data",
1496 args: args{
1497 cc: &ClientConn{
1498 Account: &Account{
187d6dc5 1499 Access: func() accessBitmap {
481631f6
JH
1500 var bits accessBitmap
1501 bits.Set(accessNewsReadArt)
187d6dc5 1502 return bits
481631f6
JH
1503 }(),
1504 },
1505 Server: &Server{
1506 FlatNews: []byte("TEST"),
1507 },
1508 },
1509 t: NewTransaction(
1510 tranGetMsgs, &[]byte{0, 1},
1511 ),
1512 },
1513 wantRes: []Transaction{
1514 {
1515 Flags: 0x00,
1516 IsReply: 0x01,
1517 Type: []byte{0, 0x65},
1518 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1519 ErrorCode: []byte{0, 0, 0, 0},
1520 Fields: []Field{
1521 NewField(fieldData, []byte("TEST")),
1522 },
1523 },
1524 },
1525 wantErr: assert.NoError,
1526 },
1527 {
1528 name: "when user does not have required permission",
1529 args: args{
1530 cc: &ClientConn{
1531 Account: &Account{
187d6dc5 1532 Access: func() accessBitmap {
481631f6 1533 var bits accessBitmap
187d6dc5 1534 return bits
481631f6
JH
1535 }(),
1536 },
1537 Server: &Server{
1538 Accounts: map[string]*Account{},
1539 },
1540 },
1541 t: NewTransaction(
1542 tranGetMsgs, &[]byte{0, 1},
1543 ),
1544 },
1545 wantRes: []Transaction{
1546 {
1547 Flags: 0x00,
1548 IsReply: 0x01,
1549 Type: []byte{0, 0x00},
1550 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1551 ErrorCode: []byte{0, 0, 0, 1},
1552 Fields: []Field{
1553 NewField(fieldError, []byte("You are not allowed to read news.")),
1554 },
1555 },
1556 },
1557 wantErr: assert.NoError,
1558 },
1559 }
1560 for _, tt := range tests {
1561 t.Run(tt.name, func(t *testing.T) {
1562 gotRes, err := HandleGetMsgs(tt.args.cc, tt.args.t)
1563 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetMsgs(%v, %v)", tt.args.cc, tt.args.t)) {
1564 return
1565 }
1566
1567 tranAssertEqual(t, tt.wantRes, gotRes)
1568 })
1569 }
1570}
1571
1572func TestHandleNewUser(t *testing.T) {
1573 type args struct {
1574 cc *ClientConn
1575 t *Transaction
1576 }
1577 tests := []struct {
1578 name string
1579 args args
1580 wantRes []Transaction
1581 wantErr assert.ErrorAssertionFunc
1582 }{
1583 {
1584 name: "when user does not have required permission",
1585 args: args{
1586 cc: &ClientConn{
1587 Account: &Account{
187d6dc5 1588 Access: func() accessBitmap {
481631f6 1589 var bits accessBitmap
187d6dc5 1590 return bits
481631f6
JH
1591 }(),
1592 },
1593 Server: &Server{
1594 Accounts: map[string]*Account{},
1595 },
1596 },
1597 t: NewTransaction(
1598 tranNewUser, &[]byte{0, 1},
1599 ),
1600 },
1601 wantRes: []Transaction{
1602 {
1603 Flags: 0x00,
1604 IsReply: 0x01,
1605 Type: []byte{0, 0x00},
1606 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1607 ErrorCode: []byte{0, 0, 0, 1},
1608 Fields: []Field{
1609 NewField(fieldError, []byte("You are not allowed to create new accounts.")),
1610 },
1611 },
1612 },
1613 wantErr: assert.NoError,
1614 },
1615 }
1616 for _, tt := range tests {
1617 t.Run(tt.name, func(t *testing.T) {
1618 gotRes, err := HandleNewUser(tt.args.cc, tt.args.t)
1619 if !tt.wantErr(t, err, fmt.Sprintf("HandleNewUser(%v, %v)", tt.args.cc, tt.args.t)) {
1620 return
1621 }
1622
1623 tranAssertEqual(t, tt.wantRes, gotRes)
1624 })
1625 }
1626}
1627
1628func TestHandleListUsers(t *testing.T) {
1629 type args struct {
1630 cc *ClientConn
1631 t *Transaction
1632 }
1633 tests := []struct {
1634 name string
1635 args args
1636 wantRes []Transaction
1637 wantErr assert.ErrorAssertionFunc
1638 }{
1639 {
1640 name: "when user does not have required permission",
1641 args: args{
1642 cc: &ClientConn{
1643 Account: &Account{
187d6dc5 1644 Access: func() accessBitmap {
481631f6 1645 var bits accessBitmap
187d6dc5 1646 return bits
481631f6
JH
1647 }(),
1648 },
1649 Server: &Server{
1650 Accounts: map[string]*Account{},
1651 },
1652 },
1653 t: NewTransaction(
1654 tranNewUser, &[]byte{0, 1},
1655 ),
1656 },
1657 wantRes: []Transaction{
1658 {
1659 Flags: 0x00,
1660 IsReply: 0x01,
1661 Type: []byte{0, 0x00},
1662 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1663 ErrorCode: []byte{0, 0, 0, 1},
1664 Fields: []Field{
1665 NewField(fieldError, []byte("You are not allowed to view accounts.")),
1666 },
1667 },
1668 },
1669 wantErr: assert.NoError,
1670 },
60ec6281
JH
1671 {
1672 name: "when user has required permission",
1673 args: args{
1674 cc: &ClientConn{
1675 Account: &Account{
187d6dc5 1676 Access: func() accessBitmap {
60ec6281
JH
1677 var bits accessBitmap
1678 bits.Set(accessOpenUser)
187d6dc5 1679 return bits
60ec6281
JH
1680 }(),
1681 },
1682 Server: &Server{
1683 Accounts: map[string]*Account{
1684 "guest": {
1685 Name: "guest",
1686 Login: "guest",
1687 Password: "zz",
187d6dc5 1688 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
60ec6281
JH
1689 },
1690 },
1691 },
1692 },
1693 t: NewTransaction(
1694 tranGetClientInfoText, &[]byte{0, 1},
1695 NewField(fieldUserID, []byte{0, 1}),
1696 ),
1697 },
1698 wantRes: []Transaction{
1699 {
1700 Flags: 0x00,
1701 IsReply: 0x01,
1702 Type: []byte{0x01, 0x2f},
1703 ID: []byte{0, 0, 0, 0},
1704 ErrorCode: []byte{0, 0, 0, 0},
1705 Fields: []Field{
1706 NewField(fieldData, []byte{
1707 0x00, 0x04, 0x00, 0x66, 0x00, 0x05, 0x67, 0x75, 0x65, 0x73, 0x74, 0x00, 0x69, 0x00, 0x05, 0x98,
1708 0x8a, 0x9a, 0x8c, 0x8b, 0x00, 0x6e, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1709 0x00, 0x6a, 0x00, 0x01, 0x78,
1710 }),
1711 },
1712 },
1713 },
1714 wantErr: assert.NoError,
1715 },
481631f6
JH
1716 }
1717 for _, tt := range tests {
1718 t.Run(tt.name, func(t *testing.T) {
1719 gotRes, err := HandleListUsers(tt.args.cc, tt.args.t)
1720 if !tt.wantErr(t, err, fmt.Sprintf("HandleListUsers(%v, %v)", tt.args.cc, tt.args.t)) {
1721 return
1722 }
1723
1724 tranAssertEqual(t, tt.wantRes, gotRes)
1725 })
1726 }
1727}
1728
1729func TestHandleDownloadFile(t *testing.T) {
1730 type args struct {
1731 cc *ClientConn
1732 t *Transaction
1733 }
1734 tests := []struct {
1735 name string
1736 args args
1737 wantRes []Transaction
1738 wantErr assert.ErrorAssertionFunc
1739 }{
1740 {
1741 name: "when user does not have required permission",
1742 args: args{
1743 cc: &ClientConn{
1744 Account: &Account{
187d6dc5 1745 Access: func() accessBitmap {
481631f6 1746 var bits accessBitmap
187d6dc5 1747 return bits
481631f6
JH
1748 }(),
1749 },
1750 Server: &Server{},
1751 },
1752 t: NewTransaction(tranDownloadFile, &[]byte{0, 1}),
1753 },
1754 wantRes: []Transaction{
1755 {
1756 Flags: 0x00,
1757 IsReply: 0x01,
1758 Type: []byte{0, 0x00},
1759 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1760 ErrorCode: []byte{0, 0, 0, 1},
1761 Fields: []Field{
1762 NewField(fieldError, []byte("You are not allowed to download files.")),
1763 },
1764 },
1765 },
1766 wantErr: assert.NoError,
1767 },
1768 {
1769 name: "with a valid file",
1770 args: args{
1771 cc: &ClientConn{
df1ade54
JH
1772 transfers: map[int]map[[4]byte]*FileTransfer{
1773 FileDownload: {},
1774 },
481631f6 1775 Account: &Account{
187d6dc5 1776 Access: func() accessBitmap {
481631f6
JH
1777 var bits accessBitmap
1778 bits.Set(accessDownloadFile)
187d6dc5 1779 return bits
481631f6
JH
1780 }(),
1781 },
1782 Server: &Server{
7cd900d6 1783 FS: &OSFileStore{},
df1ade54 1784 fileTransfers: map[[4]byte]*FileTransfer{},
481631f6
JH
1785 Config: &Config{
1786 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1787 },
1788 Accounts: map[string]*Account{},
1789 },
1790 },
1791 t: NewTransaction(
1792 accessDownloadFile,
1793 &[]byte{0, 1},
1794 NewField(fieldFileName, []byte("testfile.txt")),
1795 NewField(fieldFilePath, []byte{0x0, 0x00}),
1796 ),
1797 },
1798 wantRes: []Transaction{
1799 {
1800 Flags: 0x00,
1801 IsReply: 0x01,
1802 Type: []byte{0, 0x2},
1803 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1804 ErrorCode: []byte{0, 0, 0, 0},
1805 Fields: []Field{
1806 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1807 NewField(fieldWaitingCount, []byte{0x00, 0x00}),
1808 NewField(fieldTransferSize, []byte{0x00, 0x00, 0x00, 0xa5}),
1809 NewField(fieldFileSize, []byte{0x00, 0x00, 0x00, 0x17}),
1810 },
1811 },
1812 },
1813 wantErr: assert.NoError,
1814 },
7cd900d6
JH
1815 {
1816 name: "when client requests to resume 1k test file at offset 256",
1817 args: args{
1818 cc: &ClientConn{
df1ade54
JH
1819 transfers: map[int]map[[4]byte]*FileTransfer{
1820 FileDownload: {},
1821 }, Account: &Account{
187d6dc5 1822 Access: func() accessBitmap {
7cd900d6
JH
1823 var bits accessBitmap
1824 bits.Set(accessDownloadFile)
187d6dc5 1825 return bits
7cd900d6
JH
1826 }(),
1827 },
1828 Server: &Server{
1829 FS: &OSFileStore{},
df1ade54 1830
7cd900d6
JH
1831 // FS: func() *MockFileStore {
1832 // path, _ := os.Getwd()
1833 // testFile, err := os.Open(path + "/test/config/Files/testfile-1k")
1834 // if err != nil {
1835 // panic(err)
1836 // }
1837 //
1838 // mfi := &MockFileInfo{}
1839 // mfi.On("Mode").Return(fs.FileMode(0))
1840 // mfs := &MockFileStore{}
1841 // mfs.On("Stat", "/fakeRoot/Files/testfile.txt").Return(mfi, nil)
1842 // mfs.On("Open", "/fakeRoot/Files/testfile.txt").Return(testFile, nil)
1843 // mfs.On("Stat", "/fakeRoot/Files/.info_testfile.txt").Return(nil, errors.New("no"))
1844 // mfs.On("Stat", "/fakeRoot/Files/.rsrc_testfile.txt").Return(nil, errors.New("no"))
1845 //
1846 // return mfs
1847 // }(),
df1ade54 1848 fileTransfers: map[[4]byte]*FileTransfer{},
7cd900d6
JH
1849 Config: &Config{
1850 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1851 },
1852 Accounts: map[string]*Account{},
1853 },
1854 },
1855 t: NewTransaction(
1856 accessDownloadFile,
1857 &[]byte{0, 1},
1858 NewField(fieldFileName, []byte("testfile-1k")),
1859 NewField(fieldFilePath, []byte{0x00, 0x00}),
1860 NewField(
1861 fieldFileResumeData,
1862 func() []byte {
1863 frd := FileResumeData{
1864 Format: [4]byte{},
1865 Version: [2]byte{},
1866 RSVD: [34]byte{},
1867 ForkCount: [2]byte{0, 2},
1868 ForkInfoList: []ForkInfoList{
1869 {
1870 Fork: [4]byte{0x44, 0x41, 0x54, 0x41}, // "DATA"
1871 DataSize: [4]byte{0, 0, 0x01, 0x00}, // request offset 256
1872 RSVDA: [4]byte{},
1873 RSVDB: [4]byte{},
1874 },
1875 {
1876 Fork: [4]byte{0x4d, 0x41, 0x43, 0x52}, // "MACR"
1877 DataSize: [4]byte{0, 0, 0, 0},
1878 RSVDA: [4]byte{},
1879 RSVDB: [4]byte{},
1880 },
1881 },
1882 }
1883 b, _ := frd.BinaryMarshal()
1884 return b
1885 }(),
1886 ),
1887 ),
1888 },
1889 wantRes: []Transaction{
1890 {
1891 Flags: 0x00,
1892 IsReply: 0x01,
1893 Type: []byte{0, 0x2},
1894 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1895 ErrorCode: []byte{0, 0, 0, 0},
1896 Fields: []Field{
1897 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1898 NewField(fieldWaitingCount, []byte{0x00, 0x00}),
1899 NewField(fieldTransferSize, []byte{0x00, 0x00, 0x03, 0x8d}),
1900 NewField(fieldFileSize, []byte{0x00, 0x00, 0x03, 0x00}),
1901 },
1902 },
1903 },
1904 wantErr: assert.NoError,
1905 },
481631f6
JH
1906 }
1907 for _, tt := range tests {
1908 t.Run(tt.name, func(t *testing.T) {
481631f6
JH
1909 gotRes, err := HandleDownloadFile(tt.args.cc, tt.args.t)
1910 if !tt.wantErr(t, err, fmt.Sprintf("HandleDownloadFile(%v, %v)", tt.args.cc, tt.args.t)) {
1911 return
1912 }
1913
1914 tranAssertEqual(t, tt.wantRes, gotRes)
1915 })
1916 }
1917}
d2810ae9
JH
1918
1919func TestHandleUpdateUser(t *testing.T) {
1920 type args struct {
1921 cc *ClientConn
1922 t *Transaction
1923 }
1924 tests := []struct {
1925 name string
1926 args args
1927 wantRes []Transaction
1928 wantErr assert.ErrorAssertionFunc
1929 }{
1930 {
1931 name: "when action is create user without required permission",
1932 args: args{
1933 cc: &ClientConn{
02b446d8 1934 logger: NewTestLogger(),
d2810ae9
JH
1935 Server: &Server{
1936 Logger: NewTestLogger(),
1937 },
1938 Account: &Account{
187d6dc5 1939 Access: func() accessBitmap {
d2810ae9 1940 var bits accessBitmap
187d6dc5 1941 return bits
d2810ae9
JH
1942 }(),
1943 },
1944 },
1945 t: NewTransaction(
1946 tranUpdateUser,
1947 &[]byte{0, 0},
1948 NewField(fieldData, []byte{
1949 0x00, 0x04, // field count
1950
1951 0x00, 0x69, // fieldUserLogin = 105
1952 0x00, 0x03,
1953 0x9d, 0x9d, 0x9d,
1954
1955 0x00, 0x6a, // fieldUserPassword = 106
1956 0x00, 0x03,
1957 0x9c, 0x9c, 0x9c,
1958
1959 0x00, 0x66, // fieldUserName = 102
1960 0x00, 0x03,
1961 0x61, 0x61, 0x61,
1962
1963 0x00, 0x6e, // fieldUserAccess = 110
1964 0x00, 0x08,
1965 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
1966 }),
1967 ),
1968 },
1969 wantRes: []Transaction{
1970 {
1971 Flags: 0x00,
1972 IsReply: 0x01,
1973 Type: []byte{0, 0x00},
1974 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1975 ErrorCode: []byte{0, 0, 0, 1},
1976 Fields: []Field{
1977 NewField(fieldError, []byte("You are not allowed to create new accounts.")),
1978 },
1979 },
1980 },
1981 wantErr: assert.NoError,
1982 },
1983 {
1984 name: "when action is modify user without required permission",
1985 args: args{
1986 cc: &ClientConn{
02b446d8 1987 logger: NewTestLogger(),
d2810ae9
JH
1988 Server: &Server{
1989 Logger: NewTestLogger(),
1990 Accounts: map[string]*Account{
1991 "bbb": {},
1992 },
1993 },
1994 Account: &Account{
187d6dc5 1995 Access: func() accessBitmap {
d2810ae9 1996 var bits accessBitmap
187d6dc5 1997 return bits
d2810ae9
JH
1998 }(),
1999 },
2000 },
2001 t: NewTransaction(
2002 tranUpdateUser,
2003 &[]byte{0, 0},
2004 NewField(fieldData, []byte{
2005 0x00, 0x04, // field count
2006
2007 0x00, 0x69, // fieldUserLogin = 105
2008 0x00, 0x03,
2009 0x9d, 0x9d, 0x9d,
2010
2011 0x00, 0x6a, // fieldUserPassword = 106
2012 0x00, 0x03,
2013 0x9c, 0x9c, 0x9c,
2014
2015 0x00, 0x66, // fieldUserName = 102
2016 0x00, 0x03,
2017 0x61, 0x61, 0x61,
2018
2019 0x00, 0x6e, // fieldUserAccess = 110
2020 0x00, 0x08,
2021 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
2022 }),
2023 ),
2024 },
2025 wantRes: []Transaction{
2026 {
2027 Flags: 0x00,
2028 IsReply: 0x01,
2029 Type: []byte{0, 0x00},
2030 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2031 ErrorCode: []byte{0, 0, 0, 1},
2032 Fields: []Field{
2033 NewField(fieldError, []byte("You are not allowed to modify accounts.")),
2034 },
2035 },
2036 },
2037 wantErr: assert.NoError,
2038 },
2039 {
2040 name: "when action is delete user without required permission",
2041 args: args{
2042 cc: &ClientConn{
02b446d8 2043 logger: NewTestLogger(),
d2810ae9 2044 Server: &Server{
d2810ae9
JH
2045 Accounts: map[string]*Account{
2046 "bbb": {},
2047 },
2048 },
2049 Account: &Account{
187d6dc5 2050 Access: func() accessBitmap {
d2810ae9 2051 var bits accessBitmap
187d6dc5 2052 return bits
d2810ae9
JH
2053 }(),
2054 },
2055 },
2056 t: NewTransaction(
2057 tranUpdateUser,
2058 &[]byte{0, 0},
2059 NewField(fieldData, []byte{
2060 0x00, 0x01,
2061 0x00, 0x65,
2062 0x00, 0x03,
2063 0x88, 0x9e, 0x8b,
2064 }),
2065 ),
2066 },
2067 wantRes: []Transaction{
2068 {
2069 Flags: 0x00,
2070 IsReply: 0x01,
2071 Type: []byte{0, 0x00},
2072 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2073 ErrorCode: []byte{0, 0, 0, 1},
2074 Fields: []Field{
2075 NewField(fieldError, []byte("You are not allowed to delete accounts.")),
2076 },
2077 },
2078 },
2079 wantErr: assert.NoError,
2080 },
2081 }
2082 for _, tt := range tests {
2083 t.Run(tt.name, func(t *testing.T) {
2084 gotRes, err := HandleUpdateUser(tt.args.cc, tt.args.t)
2085 if !tt.wantErr(t, err, fmt.Sprintf("HandleUpdateUser(%v, %v)", tt.args.cc, tt.args.t)) {
2086 return
2087 }
2088
2089 tranAssertEqual(t, tt.wantRes, gotRes)
2090 })
2091 }
2092}
d4c152a4
JH
2093
2094func TestHandleDelNewsArt(t *testing.T) {
2095 type args struct {
2096 cc *ClientConn
2097 t *Transaction
2098 }
2099 tests := []struct {
2100 name string
2101 args args
2102 wantRes []Transaction
2103 wantErr assert.ErrorAssertionFunc
2104 }{
2105 {
2106 name: "without required permission",
2107 args: args{
2108 cc: &ClientConn{
2109 Account: &Account{
187d6dc5 2110 Access: func() accessBitmap {
d4c152a4 2111 var bits accessBitmap
187d6dc5 2112 return bits
d4c152a4
JH
2113 }(),
2114 },
2115 },
2116 t: NewTransaction(
2117 tranDelNewsArt,
2118 &[]byte{0, 0},
2119 ),
2120 },
2121 wantRes: []Transaction{
2122 {
2123 Flags: 0x00,
2124 IsReply: 0x01,
2125 Type: []byte{0, 0x00},
2126 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2127 ErrorCode: []byte{0, 0, 0, 1},
2128 Fields: []Field{
2129 NewField(fieldError, []byte("You are not allowed to delete news articles.")),
2130 },
2131 },
2132 },
2133 wantErr: assert.NoError,
2134 },
2135 }
2136 for _, tt := range tests {
2137 t.Run(tt.name, func(t *testing.T) {
2138 gotRes, err := HandleDelNewsArt(tt.args.cc, tt.args.t)
2139 if !tt.wantErr(t, err, fmt.Sprintf("HandleDelNewsArt(%v, %v)", tt.args.cc, tt.args.t)) {
2140 return
2141 }
2142 tranAssertEqual(t, tt.wantRes, gotRes)
2143 })
2144 }
2145}
2146
2147func TestHandleDisconnectUser(t *testing.T) {
2148 type args struct {
2149 cc *ClientConn
2150 t *Transaction
2151 }
2152 tests := []struct {
2153 name string
2154 args args
2155 wantRes []Transaction
2156 wantErr assert.ErrorAssertionFunc
2157 }{
2158 {
2159 name: "without required permission",
2160 args: args{
2161 cc: &ClientConn{
2162 Account: &Account{
187d6dc5 2163 Access: func() accessBitmap {
d4c152a4 2164 var bits accessBitmap
187d6dc5 2165 return bits
d4c152a4
JH
2166 }(),
2167 },
2168 },
2169 t: NewTransaction(
2170 tranDelNewsArt,
2171 &[]byte{0, 0},
2172 ),
2173 },
2174 wantRes: []Transaction{
2175 {
2176 Flags: 0x00,
2177 IsReply: 0x01,
2178 Type: []byte{0, 0x00},
2179 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2180 ErrorCode: []byte{0, 0, 0, 1},
2181 Fields: []Field{
2182 NewField(fieldError, []byte("You are not allowed to disconnect users.")),
2183 },
2184 },
2185 },
2186 wantErr: assert.NoError,
2187 },
2188 {
2189 name: "when target user has 'cannot be disconnected' priv",
2190 args: args{
2191 cc: &ClientConn{
2192 Server: &Server{
2193 Clients: map[uint16]*ClientConn{
2194 uint16(1): {
2195 Account: &Account{
2196 Login: "unnamed",
187d6dc5 2197 Access: func() accessBitmap {
d4c152a4
JH
2198 var bits accessBitmap
2199 bits.Set(accessCannotBeDiscon)
187d6dc5 2200 return bits
d4c152a4
JH
2201 }(),
2202 },
2203 },
2204 },
2205 },
2206 Account: &Account{
187d6dc5 2207 Access: func() accessBitmap {
d4c152a4
JH
2208 var bits accessBitmap
2209 bits.Set(accessDisconUser)
187d6dc5 2210 return bits
d4c152a4
JH
2211 }(),
2212 },
2213 },
2214 t: NewTransaction(
2215 tranDelNewsArt,
2216 &[]byte{0, 0},
2217 NewField(fieldUserID, []byte{0, 1}),
2218 ),
2219 },
2220 wantRes: []Transaction{
2221 {
2222 Flags: 0x00,
2223 IsReply: 0x01,
2224 Type: []byte{0, 0x00},
2225 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2226 ErrorCode: []byte{0, 0, 0, 1},
2227 Fields: []Field{
2228 NewField(fieldError, []byte("unnamed is not allowed to be disconnected.")),
2229 },
2230 },
2231 },
2232 wantErr: assert.NoError,
2233 },
2234 }
2235 for _, tt := range tests {
2236 t.Run(tt.name, func(t *testing.T) {
2237 gotRes, err := HandleDisconnectUser(tt.args.cc, tt.args.t)
2238 if !tt.wantErr(t, err, fmt.Sprintf("HandleDisconnectUser(%v, %v)", tt.args.cc, tt.args.t)) {
2239 return
2240 }
2241 tranAssertEqual(t, tt.wantRes, gotRes)
2242 })
2243 }
2244}
aeec1015
JH
2245
2246func TestHandleSendInstantMsg(t *testing.T) {
2247 type args struct {
2248 cc *ClientConn
2249 t *Transaction
2250 }
2251 tests := []struct {
2252 name string
2253 args args
2254 wantRes []Transaction
2255 wantErr assert.ErrorAssertionFunc
2256 }{
69c2fb50
JH
2257 {
2258 name: "without required permission",
2259 args: args{
2260 cc: &ClientConn{
2261 Account: &Account{
187d6dc5 2262 Access: func() accessBitmap {
69c2fb50 2263 var bits accessBitmap
187d6dc5 2264 return bits
69c2fb50
JH
2265 }(),
2266 },
2267 },
2268 t: NewTransaction(
2269 tranDelNewsArt,
2270 &[]byte{0, 0},
2271 ),
2272 },
2273 wantRes: []Transaction{
2274 {
2275 Flags: 0x00,
2276 IsReply: 0x01,
2277 Type: []byte{0, 0x00},
2278 ID: []byte{0, 0, 0, 0},
2279 ErrorCode: []byte{0, 0, 0, 1},
2280 Fields: []Field{
2281 NewField(fieldError, []byte("You are not allowed to send private messages.")),
2282 },
2283 },
2284 },
2285 wantErr: assert.NoError,
2286 },
aeec1015
JH
2287 {
2288 name: "when client 1 sends a message to client 2",
2289 args: args{
2290 cc: &ClientConn{
69c2fb50 2291 Account: &Account{
187d6dc5 2292 Access: func() accessBitmap {
69c2fb50
JH
2293 var bits accessBitmap
2294 bits.Set(accessSendPrivMsg)
187d6dc5 2295 return bits
69c2fb50
JH
2296 }(),
2297 },
aeec1015
JH
2298 ID: &[]byte{0, 1},
2299 UserName: []byte("User1"),
2300 Server: &Server{
2301 Clients: map[uint16]*ClientConn{
2302 uint16(2): {
2303 AutoReply: []byte(nil),
2304 },
2305 },
2306 },
2307 },
2308 t: NewTransaction(
2309 tranSendInstantMsg,
2310 &[]byte{0, 1},
2311 NewField(fieldData, []byte("hai")),
2312 NewField(fieldUserID, []byte{0, 2}),
2313 ),
2314 },
2315 wantRes: []Transaction{
2316 *NewTransaction(
2317 tranServerMsg,
2318 &[]byte{0, 2},
2319 NewField(fieldData, []byte("hai")),
2320 NewField(fieldUserName, []byte("User1")),
2321 NewField(fieldUserID, []byte{0, 1}),
2322 NewField(fieldOptions, []byte{0, 1}),
2323 ),
2324 {
2325 clientID: &[]byte{0, 1},
2326 Flags: 0x00,
2327 IsReply: 0x01,
2328 Type: []byte{0x0, 0x6c},
2329 ID: []byte{0, 0, 0, 0},
2330 ErrorCode: []byte{0, 0, 0, 0},
2331 Fields: []Field(nil),
2332 },
2333 },
2334 wantErr: assert.NoError,
2335 },
2336 {
2337 name: "when client 2 has autoreply enabled",
2338 args: args{
2339 cc: &ClientConn{
69c2fb50 2340 Account: &Account{
187d6dc5 2341 Access: func() accessBitmap {
69c2fb50
JH
2342 var bits accessBitmap
2343 bits.Set(accessSendPrivMsg)
187d6dc5 2344 return bits
69c2fb50
JH
2345 }(),
2346 },
aeec1015
JH
2347 ID: &[]byte{0, 1},
2348 UserName: []byte("User1"),
2349 Server: &Server{
2350 Clients: map[uint16]*ClientConn{
2351 uint16(2): {
2352 ID: &[]byte{0, 2},
2353 UserName: []byte("User2"),
2354 AutoReply: []byte("autohai"),
2355 },
2356 },
2357 },
2358 },
2359 t: NewTransaction(
2360 tranSendInstantMsg,
2361 &[]byte{0, 1},
2362 NewField(fieldData, []byte("hai")),
2363 NewField(fieldUserID, []byte{0, 2}),
2364 ),
2365 },
2366 wantRes: []Transaction{
2367 *NewTransaction(
2368 tranServerMsg,
2369 &[]byte{0, 2},
2370 NewField(fieldData, []byte("hai")),
2371 NewField(fieldUserName, []byte("User1")),
2372 NewField(fieldUserID, []byte{0, 1}),
2373 NewField(fieldOptions, []byte{0, 1}),
2374 ),
2375 *NewTransaction(
2376 tranServerMsg,
2377 &[]byte{0, 1},
2378 NewField(fieldData, []byte("autohai")),
2379 NewField(fieldUserName, []byte("User2")),
2380 NewField(fieldUserID, []byte{0, 2}),
2381 NewField(fieldOptions, []byte{0, 1}),
2382 ),
2383 {
2384 clientID: &[]byte{0, 1},
2385 Flags: 0x00,
2386 IsReply: 0x01,
2387 Type: []byte{0x0, 0x6c},
2388 ID: []byte{0, 0, 0, 0},
2389 ErrorCode: []byte{0, 0, 0, 0},
2390 Fields: []Field(nil),
2391 },
2392 },
2393 wantErr: assert.NoError,
2394 },
2395 }
2396 for _, tt := range tests {
2397 t.Run(tt.name, func(t *testing.T) {
2398 gotRes, err := HandleSendInstantMsg(tt.args.cc, tt.args.t)
2399 if !tt.wantErr(t, err, fmt.Sprintf("HandleSendInstantMsg(%v, %v)", tt.args.cc, tt.args.t)) {
2400 return
2401 }
2402
2403 tranAssertEqual(t, tt.wantRes, gotRes)
2404 })
2405 }
2406}
7cd900d6
JH
2407
2408func TestHandleDeleteFile(t *testing.T) {
2409 type args struct {
2410 cc *ClientConn
2411 t *Transaction
2412 }
2413 tests := []struct {
2414 name string
2415 args args
2416 wantRes []Transaction
2417 wantErr assert.ErrorAssertionFunc
2418 }{
2419 {
2420 name: "when user does not have required permission to delete a folder",
2421 args: args{
2422 cc: &ClientConn{
2423 Account: &Account{
187d6dc5 2424 Access: func() accessBitmap {
7cd900d6 2425 var bits accessBitmap
187d6dc5 2426 return bits
7cd900d6
JH
2427 }(),
2428 },
2429 Server: &Server{
2430 Config: &Config{
2431 FileRoot: func() string {
2432 return "/fakeRoot/Files"
2433 }(),
2434 },
2435 FS: func() *MockFileStore {
2436 mfi := &MockFileInfo{}
2437 mfi.On("Mode").Return(fs.FileMode(0))
2438 mfi.On("Size").Return(int64(100))
2439 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2440 mfi.On("IsDir").Return(false)
2441 mfi.On("Name").Return("testfile")
2442
2443 mfs := &MockFileStore{}
2444 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2445 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2446 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2447
2448 return mfs
2449 }(),
2450 Accounts: map[string]*Account{},
2451 },
2452 },
2453 t: NewTransaction(
2454 tranDeleteFile, &[]byte{0, 1},
2455 NewField(fieldFileName, []byte("testfile")),
2456 NewField(fieldFilePath, []byte{
2457 0x00, 0x01,
2458 0x00, 0x00,
2459 0x03,
2460 0x61, 0x61, 0x61,
2461 }),
2462 ),
2463 },
2464 wantRes: []Transaction{
2465 {
2466 Flags: 0x00,
2467 IsReply: 0x01,
2468 Type: []byte{0, 0x00},
2469 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2470 ErrorCode: []byte{0, 0, 0, 1},
2471 Fields: []Field{
2472 NewField(fieldError, []byte("You are not allowed to delete files.")),
2473 },
2474 },
2475 },
2476 wantErr: assert.NoError,
2477 },
2478 {
2479 name: "deletes all associated metadata files",
2480 args: args{
2481 cc: &ClientConn{
2482 Account: &Account{
187d6dc5 2483 Access: func() accessBitmap {
7cd900d6
JH
2484 var bits accessBitmap
2485 bits.Set(accessDeleteFile)
187d6dc5 2486 return bits
7cd900d6
JH
2487 }(),
2488 },
2489 Server: &Server{
2490 Config: &Config{
2491 FileRoot: func() string {
2492 return "/fakeRoot/Files"
2493 }(),
2494 },
2495 FS: func() *MockFileStore {
2496 mfi := &MockFileInfo{}
2497 mfi.On("Mode").Return(fs.FileMode(0))
2498 mfi.On("Size").Return(int64(100))
2499 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2500 mfi.On("IsDir").Return(false)
2501 mfi.On("Name").Return("testfile")
2502
2503 mfs := &MockFileStore{}
2504 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2505 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2506 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2507
2508 mfs.On("RemoveAll", "/fakeRoot/Files/aaa/testfile").Return(nil)
2509 mfs.On("Remove", "/fakeRoot/Files/aaa/testfile.incomplete").Return(nil)
2510 mfs.On("Remove", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil)
2511 mfs.On("Remove", "/fakeRoot/Files/aaa/.info_testfile").Return(nil)
2512
2513 return mfs
2514 }(),
2515 Accounts: map[string]*Account{},
2516 },
2517 },
2518 t: NewTransaction(
2519 tranDeleteFile, &[]byte{0, 1},
2520 NewField(fieldFileName, []byte("testfile")),
2521 NewField(fieldFilePath, []byte{
2522 0x00, 0x01,
2523 0x00, 0x00,
2524 0x03,
2525 0x61, 0x61, 0x61,
2526 }),
2527 ),
2528 },
2529 wantRes: []Transaction{
2530 {
2531 Flags: 0x00,
2532 IsReply: 0x01,
2533 Type: []byte{0x0, 0xcc},
2534 ID: []byte{0x0, 0x0, 0x0, 0x0},
2535 ErrorCode: []byte{0, 0, 0, 0},
2536 Fields: []Field(nil),
2537 },
2538 },
2539 wantErr: assert.NoError,
2540 },
2541 }
2542 for _, tt := range tests {
2543 t.Run(tt.name, func(t *testing.T) {
2544 gotRes, err := HandleDeleteFile(tt.args.cc, tt.args.t)
2545 if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteFile(%v, %v)", tt.args.cc, tt.args.t)) {
2546 return
2547 }
2548
2549 tranAssertEqual(t, tt.wantRes, gotRes)
2550
2551 tt.args.cc.Server.FS.(*MockFileStore).AssertExpectations(t)
2552 })
2553 }
2554}
2e08be58
JH
2555
2556func TestHandleGetFileNameList(t *testing.T) {
2557 type args struct {
2558 cc *ClientConn
2559 t *Transaction
2560 }
2561 tests := []struct {
2562 name string
2563 args args
2564 wantRes []Transaction
2565 wantErr assert.ErrorAssertionFunc
2566 }{
2567 {
2568 name: "when fieldFilePath is a drop box, but user does not have accessViewDropBoxes ",
2569 args: args{
2570 cc: &ClientConn{
2571 Account: &Account{
187d6dc5 2572 Access: func() accessBitmap {
2e08be58 2573 var bits accessBitmap
187d6dc5 2574 return bits
2e08be58
JH
2575 }(),
2576 },
2577 Server: &Server{
2578
2579 Config: &Config{
2580 FileRoot: func() string {
2581 path, _ := os.Getwd()
2582 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2583 }(),
2584 },
2585 },
2586 },
2587 t: NewTransaction(
2588 tranGetFileNameList, &[]byte{0, 1},
2589 NewField(fieldFilePath, []byte{
2590 0x00, 0x01,
2591 0x00, 0x00,
2592 0x08,
2593 0x64, 0x72, 0x6f, 0x70, 0x20, 0x62, 0x6f, 0x78, // "drop box"
2594 }),
2595 ),
2596 },
2597 wantRes: []Transaction{
2598 {
2599 Flags: 0x00,
2600 IsReply: 0x01,
2601 Type: []byte{0, 0x00},
2602 ID: []byte{0, 0, 0, 0},
2603 ErrorCode: []byte{0, 0, 0, 1},
2604 Fields: []Field{
2605 NewField(fieldError, []byte("You are not allowed to view drop boxes.")),
2606 },
2607 },
2608 },
2609 wantErr: assert.NoError,
2610 },
2611 {
2612 name: "with file root",
2613 args: args{
2614 cc: &ClientConn{
2615 Server: &Server{
2616 Config: &Config{
2617 FileRoot: func() string {
2618 path, _ := os.Getwd()
2619 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2620 }(),
2621 },
2622 },
2623 },
2624 t: NewTransaction(
2625 tranGetFileNameList, &[]byte{0, 1},
2626 NewField(fieldFilePath, []byte{
2627 0x00, 0x00,
2628 0x00, 0x00,
2629 }),
2630 ),
2631 },
2632 wantRes: []Transaction{
2633 {
2634 Flags: 0x00,
2635 IsReply: 0x01,
2636 Type: []byte{0, 0xc8},
2637 ID: []byte{0, 0, 0, 0},
2638 ErrorCode: []byte{0, 0, 0, 0},
2639 Fields: []Field{
2640 NewField(
2641 fieldFileNameWithInfo,
2642 func() []byte {
2643 fnwi := FileNameWithInfo{
2644 fileNameWithInfoHeader: fileNameWithInfoHeader{
2645 Type: [4]byte{0x54, 0x45, 0x58, 0x54},
2646 Creator: [4]byte{0x54, 0x54, 0x58, 0x54},
2647 FileSize: [4]byte{0, 0, 0x04, 0},
2648 RSVD: [4]byte{},
2649 NameScript: [2]byte{},
2650 NameSize: [2]byte{0, 0x0b},
2651 },
2652 name: []byte("testfile-1k"),
2653 }
2654 b, _ := fnwi.MarshalBinary()
2655 return b
2656 }(),
2657 ),
2658 },
2659 },
2660 },
2661 wantErr: assert.NoError,
2662 },
2663 }
2664 for _, tt := range tests {
2665 t.Run(tt.name, func(t *testing.T) {
2666 gotRes, err := HandleGetFileNameList(tt.args.cc, tt.args.t)
2667 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetFileNameList(%v, %v)", tt.args.cc, tt.args.t)) {
2668 return
2669 }
2670
2671 tranAssertEqual(t, tt.wantRes, gotRes)
2672 })
2673 }
2674}
df1ade54
JH
2675
2676func TestHandleGetClientInfoText(t *testing.T) {
2677 type args struct {
2678 cc *ClientConn
2679 t *Transaction
2680 }
2681 tests := []struct {
2682 name string
2683 args args
2684 wantRes []Transaction
2685 wantErr assert.ErrorAssertionFunc
2686 }{
2687 {
2688 name: "when user does not have required permission",
2689 args: args{
2690 cc: &ClientConn{
2691 Account: &Account{
187d6dc5 2692 Access: func() accessBitmap {
df1ade54 2693 var bits accessBitmap
187d6dc5 2694 return bits
df1ade54
JH
2695 }(),
2696 },
2697 Server: &Server{
2698 Accounts: map[string]*Account{},
2699 },
2700 },
2701 t: NewTransaction(
2702 tranGetClientInfoText, &[]byte{0, 1},
2703 NewField(fieldUserID, []byte{0, 1}),
2704 ),
2705 },
2706 wantRes: []Transaction{
2707 {
2708 Flags: 0x00,
2709 IsReply: 0x01,
2710 Type: []byte{0, 0x00},
2711 ID: []byte{0, 0, 0, 0},
2712 ErrorCode: []byte{0, 0, 0, 1},
2713 Fields: []Field{
2714 NewField(fieldError, []byte("You are not allowed to get client info.")),
2715 },
2716 },
2717 },
2718 wantErr: assert.NoError,
2719 },
2720 {
2721 name: "with a valid user",
2722 args: args{
2723 cc: &ClientConn{
2724 UserName: []byte("Testy McTest"),
2725 RemoteAddr: "1.2.3.4:12345",
2726 Account: &Account{
187d6dc5 2727 Access: func() accessBitmap {
df1ade54
JH
2728 var bits accessBitmap
2729 bits.Set(accessGetClientInfo)
187d6dc5 2730 return bits
df1ade54
JH
2731 }(),
2732 Name: "test",
2733 Login: "test",
2734 },
2735 Server: &Server{
2736 Accounts: map[string]*Account{},
2737 Clients: map[uint16]*ClientConn{
2738 uint16(1): {
2739 UserName: []byte("Testy McTest"),
2740 RemoteAddr: "1.2.3.4:12345",
2741 Account: &Account{
187d6dc5 2742 Access: func() accessBitmap {
df1ade54
JH
2743 var bits accessBitmap
2744 bits.Set(accessGetClientInfo)
187d6dc5 2745 return bits
df1ade54
JH
2746 }(),
2747 Name: "test",
2748 Login: "test",
2749 },
2750 },
2751 },
2752 },
2753 transfers: map[int]map[[4]byte]*FileTransfer{
2754 FileDownload: {},
2755 FileUpload: {},
2756 FolderDownload: {},
2757 FolderUpload: {},
2758 },
2759 },
2760 t: NewTransaction(
2761 tranGetClientInfoText, &[]byte{0, 1},
2762 NewField(fieldUserID, []byte{0, 1}),
2763 ),
2764 },
2765 wantRes: []Transaction{
2766 {
2767 Flags: 0x00,
2768 IsReply: 0x01,
2769 Type: []byte{0x1, 0x2f},
2770 ID: []byte{0, 0, 0, 0},
2771 ErrorCode: []byte{0, 0, 0, 0},
2772 Fields: []Field{
2773 NewField(fieldData, []byte(
2774 strings.Replace(`Nickname: Testy McTest
2775Name: test
2776Account: test
2777Address: 1.2.3.4:12345
2778
2779-------- File Downloads ---------
2780
2781None.
2782
2783------- Folder Downloads --------
2784
2785None.
2786
2787--------- File Uploads ----------
2788
2789None.
2790
2791-------- Folder Uploads ---------
2792
2793None.
2794
2795------- Waiting Downloads -------
2796
2797None.
2798
2799`, "\n", "\r", -1)),
2800 ),
2801 NewField(fieldUserName, []byte("Testy McTest")),
2802 },
2803 },
2804 },
2805 wantErr: assert.NoError,
2806 },
2807 }
2808 for _, tt := range tests {
2809 t.Run(tt.name, func(t *testing.T) {
2810 gotRes, err := HandleGetClientInfoText(tt.args.cc, tt.args.t)
2811 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetClientInfoText(%v, %v)", tt.args.cc, tt.args.t)) {
2812 return
2813 }
2814 tranAssertEqual(t, tt.wantRes, gotRes)
2815 })
2816 }
2817}
ea5d8c51
JH
2818
2819func TestHandleTranAgreed(t *testing.T) {
2820 type args struct {
2821 cc *ClientConn
2822 t *Transaction
2823 }
2824 tests := []struct {
2825 name string
2826 args args
2827 wantRes []Transaction
2828 wantErr assert.ErrorAssertionFunc
2829 }{
2830 {
2831 name: "normal request flow",
2832 args: args{
2833 cc: &ClientConn{
2834 Account: &Account{
187d6dc5 2835 Access: func() accessBitmap {
ea5d8c51
JH
2836 var bits accessBitmap
2837 bits.Set(accessDisconUser)
2838 bits.Set(accessAnyName)
187d6dc5 2839 return bits
ea5d8c51 2840 }()},
a7216f67
JH
2841 Icon: []byte{0, 1},
2842 Flags: []byte{0, 1},
2843 Version: []byte{0, 1},
ea5d8c51
JH
2844 ID: &[]byte{0, 1},
2845 logger: NewTestLogger(),
2846 Server: &Server{
2847 Config: &Config{
2848 BannerFile: "banner.jpg",
2849 },
2850 },
2851 },
2852 t: NewTransaction(
2853 tranAgreed, nil,
2854 NewField(fieldUserName, []byte("username")),
2855 NewField(fieldUserIconID, []byte{0, 1}),
2856 NewField(fieldOptions, []byte{0, 0}),
2857 ),
2858 },
2859 wantRes: []Transaction{
2860 {
2861 clientID: &[]byte{0, 1},
2862 Flags: 0x00,
2863 IsReply: 0x00,
2864 Type: []byte{0, 0x7a},
2865 ID: []byte{0, 0, 0, 0},
2866 ErrorCode: []byte{0, 0, 0, 0},
2867 Fields: []Field{
2868 NewField(fieldBannerType, []byte("JPEG")),
2869 },
2870 },
2871 {
2872 clientID: &[]byte{0, 1},
2873 Flags: 0x00,
2874 IsReply: 0x01,
2875 Type: []byte{0, 0x79},
2876 ID: []byte{0, 0, 0, 0},
2877 ErrorCode: []byte{0, 0, 0, 0},
2878 Fields: []Field{},
2879 },
2880 },
2881 wantErr: assert.NoError,
2882 },
2883 }
2884 for _, tt := range tests {
2885 t.Run(tt.name, func(t *testing.T) {
2886 gotRes, err := HandleTranAgreed(tt.args.cc, tt.args.t)
2887 if !tt.wantErr(t, err, fmt.Sprintf("HandleTranAgreed(%v, %v)", tt.args.cc, tt.args.t)) {
2888 return
2889 }
2890 tranAssertEqual(t, tt.wantRes, gotRes)
2891 })
2892 }
2893}
264b7c27
JH
2894
2895func TestHandleSetClientUserInfo(t *testing.T) {
2896 type args struct {
2897 cc *ClientConn
2898 t *Transaction
2899 }
2900 tests := []struct {
2901 name string
2902 args args
2903 wantRes []Transaction
2904 wantErr assert.ErrorAssertionFunc
2905 }{
2906 {
2907 name: "when client does not have accessAnyName",
2908 args: args{
2909 cc: &ClientConn{
2910 Account: &Account{
187d6dc5 2911 Access: func() accessBitmap {
264b7c27 2912 var bits accessBitmap
187d6dc5 2913 return bits
264b7c27
JH
2914 }(),
2915 },
2916 ID: &[]byte{0, 1},
2917 UserName: []byte("Guest"),
2918 Flags: []byte{0, 1},
2919 Server: &Server{
2920 Clients: map[uint16]*ClientConn{
2921 uint16(1): {
2922 ID: &[]byte{0, 1},
2923 },
2924 },
2925 },
2926 },
2927 t: NewTransaction(
2928 tranSetClientUserInfo, nil,
2929 NewField(fieldUserIconID, []byte{0, 1}),
2930 NewField(fieldUserName, []byte("NOPE")),
2931 ),
2932 },
2933 wantRes: []Transaction{
2934 {
2935 clientID: &[]byte{0, 1},
2936 Flags: 0x00,
2937 IsReply: 0x00,
2938 Type: []byte{0x01, 0x2d},
2939 ID: []byte{0, 0, 0, 0},
2940 ErrorCode: []byte{0, 0, 0, 0},
2941 Fields: []Field{
2942 NewField(fieldUserID, []byte{0, 1}),
2943 NewField(fieldUserIconID, []byte{0, 1}),
2944 NewField(fieldUserFlags, []byte{0, 1}),
2945 NewField(fieldUserName, []byte("Guest"))},
2946 },
2947 },
2948 wantErr: assert.NoError,
2949 },
2950 }
2951 for _, tt := range tests {
2952 t.Run(tt.name, func(t *testing.T) {
2953 gotRes, err := HandleSetClientUserInfo(tt.args.cc, tt.args.t)
2954 if !tt.wantErr(t, err, fmt.Sprintf("HandleSetClientUserInfo(%v, %v)", tt.args.cc, tt.args.t)) {
2955 return
2956 }
2957
2958 tranAssertEqual(t, tt.wantRes, gotRes)
2959 })
2960 }
2961}