]> git.r.bdr.sh - rbdr/mobius/blame - hotline/transaction_handlers_test.go
Revert change to effectiveFile func
[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"
decc2fbf 10 "strings"
6988a057
JH
11 "testing"
12)
13
14func TestHandleSetChatSubject(t *testing.T) {
15 type args struct {
16 cc *ClientConn
17 t *Transaction
18 }
19 tests := []struct {
20 name string
21 args args
22 want []Transaction
23 wantErr bool
24 }{
25 {
26 name: "sends chat subject to private chat members",
27 args: args{
28 cc: &ClientConn{
72dd37f1 29 UserName: []byte{0x00, 0x01},
6988a057
JH
30 Server: &Server{
31 PrivateChats: map[uint32]*PrivateChat{
32 uint32(1): {
33 Subject: "unset",
34 ClientConn: map[uint16]*ClientConn{
35 uint16(1): {
36 Account: &Account{
37 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
38 },
39 ID: &[]byte{0, 1},
40 },
41 uint16(2): {
42 Account: &Account{
43 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
44 },
45 ID: &[]byte{0, 2},
46 },
47 },
48 },
49 },
50 Clients: map[uint16]*ClientConn{
51 uint16(1): {
52 Account: &Account{
53 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
54 },
55 ID: &[]byte{0, 1},
56 },
57 uint16(2): {
58 Account: &Account{
59 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
60 },
61 ID: &[]byte{0, 2},
62 },
63 },
64 },
65 },
66 t: &Transaction{
67 Flags: 0x00,
68 IsReply: 0x00,
69 Type: []byte{0, 0x6a},
70 ID: []byte{0, 0, 0, 1},
71 ErrorCode: []byte{0, 0, 0, 0},
72 Fields: []Field{
73 NewField(fieldChatID, []byte{0, 0, 0, 1}),
74 NewField(fieldChatSubject, []byte("Test Subject")),
75 },
76 },
77 },
78 want: []Transaction{
79 {
80 clientID: &[]byte{0, 1},
81 Flags: 0x00,
82 IsReply: 0x00,
83 Type: []byte{0, 0x77},
84 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
85 ErrorCode: []byte{0, 0, 0, 0},
86 Fields: []Field{
87 NewField(fieldChatID, []byte{0, 0, 0, 1}),
88 NewField(fieldChatSubject, []byte("Test Subject")),
89 },
90 },
91 {
92 clientID: &[]byte{0, 2},
93 Flags: 0x00,
94 IsReply: 0x00,
95 Type: []byte{0, 0x77},
96 ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
97 ErrorCode: []byte{0, 0, 0, 0},
98 Fields: []Field{
99 NewField(fieldChatID, []byte{0, 0, 0, 1}),
100 NewField(fieldChatSubject, []byte("Test Subject")),
101 },
102 },
103 },
104 wantErr: false,
105 },
106 }
107 for _, tt := range tests {
108 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
109
110 t.Run(tt.name, func(t *testing.T) {
111 got, err := HandleSetChatSubject(tt.args.cc, tt.args.t)
112 if (err != nil) != tt.wantErr {
113 t.Errorf("HandleSetChatSubject() error = %v, wantErr %v", err, tt.wantErr)
114 return
115 }
116 if !assert.Equal(t, tt.want, got) {
117 t.Errorf("HandleSetChatSubject() got = %v, want %v", got, tt.want)
118 }
119 })
120 }
121}
122
123func TestHandleLeaveChat(t *testing.T) {
124 type args struct {
125 cc *ClientConn
126 t *Transaction
127 }
128 tests := []struct {
129 name string
130 args args
131 want []Transaction
132 wantErr bool
133 }{
134 {
135 name: "returns expected transactions",
136 args: args{
137 cc: &ClientConn{
138 ID: &[]byte{0, 2},
139 Server: &Server{
140 PrivateChats: map[uint32]*PrivateChat{
141 uint32(1): {
142 ClientConn: map[uint16]*ClientConn{
143 uint16(1): {
144 Account: &Account{
145 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
146 },
147 ID: &[]byte{0, 1},
148 },
149 uint16(2): {
150 Account: &Account{
151 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
152 },
153 ID: &[]byte{0, 2},
154 },
155 },
156 },
157 },
158 Clients: map[uint16]*ClientConn{
159 uint16(1): {
160 Account: &Account{
161 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
162 },
163 ID: &[]byte{0, 1},
164 },
165 uint16(2): {
166 Account: &Account{
167 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
168 },
169 ID: &[]byte{0, 2},
170 },
171 },
172 },
173 },
5c34f875 174 t: NewTransaction(tranDeleteUser, nil, NewField(fieldChatID, []byte{0, 0, 0, 1})),
6988a057
JH
175 },
176 want: []Transaction{
177 {
178 clientID: &[]byte{0, 1},
179 Flags: 0x00,
180 IsReply: 0x00,
181 Type: []byte{0, 0x76},
182 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
183 ErrorCode: []byte{0, 0, 0, 0},
184 Fields: []Field{
185 NewField(fieldChatID, []byte{0, 0, 0, 1}),
186 NewField(fieldUserID, []byte{0, 2}),
187 },
188 },
189 },
190 wantErr: false,
191 },
192 }
193 for _, tt := range tests {
194 rand.Seed(1)
195 t.Run(tt.name, func(t *testing.T) {
196 got, err := HandleLeaveChat(tt.args.cc, tt.args.t)
197 if (err != nil) != tt.wantErr {
198 t.Errorf("HandleLeaveChat() error = %v, wantErr %v", err, tt.wantErr)
199 return
200 }
201 if !assert.Equal(t, tt.want, got) {
202 t.Errorf("HandleLeaveChat() got = %v, want %v", got, tt.want)
203 }
204 })
205 }
206}
207
6988a057
JH
208func TestHandleGetUserNameList(t *testing.T) {
209 type args struct {
210 cc *ClientConn
211 t *Transaction
212 }
213 tests := []struct {
214 name string
215 args args
216 want []Transaction
217 wantErr bool
218 }{
219 {
220 name: "replies with userlist transaction",
221 args: args{
222 cc: &ClientConn{
223
224 ID: &[]byte{1, 1},
225 Server: &Server{
226 Clients: map[uint16]*ClientConn{
227 uint16(1): {
228 ID: &[]byte{0, 1},
229 Icon: &[]byte{0, 2},
230 Flags: &[]byte{0, 3},
72dd37f1 231 UserName: []byte{0, 4},
bd1ce113 232 Agreed: true,
6988a057 233 },
c7e932c0
JH
234 uint16(2): {
235 ID: &[]byte{0, 2},
236 Icon: &[]byte{0, 2},
237 Flags: &[]byte{0, 3},
238 UserName: []byte{0, 4},
bd1ce113
JH
239 Agreed: true,
240 },
241 uint16(3): {
242 ID: &[]byte{0, 3},
243 Icon: &[]byte{0, 2},
244 Flags: &[]byte{0, 3},
245 UserName: []byte{0, 4},
246 Agreed: false,
c7e932c0 247 },
6988a057
JH
248 },
249 },
250 },
251 t: &Transaction{
252 ID: []byte{0, 0, 0, 1},
253 Type: []byte{0, 1},
254 },
255 },
256 want: []Transaction{
257 {
258 clientID: &[]byte{1, 1},
259 Flags: 0x00,
260 IsReply: 0x01,
261 Type: []byte{0, 1},
262 ID: []byte{0, 0, 0, 1},
263 ErrorCode: []byte{0, 0, 0, 0},
264 Fields: []Field{
265 NewField(
266 fieldUsernameWithInfo,
267 []byte{00, 01, 00, 02, 00, 03, 00, 02, 00, 04},
268 ),
c7e932c0
JH
269 NewField(
270 fieldUsernameWithInfo,
271 []byte{00, 02, 00, 02, 00, 03, 00, 02, 00, 04},
272 ),
6988a057
JH
273 },
274 },
275 },
276 wantErr: false,
277 },
278 }
279 for _, tt := range tests {
280 t.Run(tt.name, func(t *testing.T) {
281 got, err := HandleGetUserNameList(tt.args.cc, tt.args.t)
282 if (err != nil) != tt.wantErr {
283 t.Errorf("HandleGetUserNameList() error = %v, wantErr %v", err, tt.wantErr)
284 return
285 }
bd1ce113 286 assert.Equal(t, tt.want, got)
6988a057
JH
287 })
288 }
289}
290
291func TestHandleChatSend(t *testing.T) {
292 type args struct {
293 cc *ClientConn
294 t *Transaction
295 }
296 tests := []struct {
297 name string
298 args args
299 want []Transaction
300 wantErr bool
301 }{
302 {
303 name: "sends chat msg transaction to all clients",
304 args: args{
305 cc: &ClientConn{
9ebf276d
JH
306 Account: &Account{
307 Access: func() *[]byte {
308 var bits accessBitmap
309 bits.Set(accessSendChat)
310 access := bits[:]
311 return &access
312 }(),
313 },
72dd37f1 314 UserName: []byte{0x00, 0x01},
6988a057
JH
315 Server: &Server{
316 Clients: map[uint16]*ClientConn{
317 uint16(1): {
318 Account: &Account{
319 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
320 },
321 ID: &[]byte{0, 1},
322 },
323 uint16(2): {
324 Account: &Account{
325 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
326 },
327 ID: &[]byte{0, 2},
328 },
329 },
330 },
331 },
332 t: &Transaction{
333 Fields: []Field{
334 NewField(fieldData, []byte("hai")),
335 },
336 },
337 },
338 want: []Transaction{
339 {
340 clientID: &[]byte{0, 1},
341 Flags: 0x00,
342 IsReply: 0x00,
343 Type: []byte{0, 0x6a},
344 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
345 ErrorCode: []byte{0, 0, 0, 0},
346 Fields: []Field{
347 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
348 },
349 },
350 {
351 clientID: &[]byte{0, 2},
352 Flags: 0x00,
353 IsReply: 0x00,
354 Type: []byte{0, 0x6a},
355 ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
356 ErrorCode: []byte{0, 0, 0, 0},
357 Fields: []Field{
358 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
359 },
360 },
361 },
362 wantErr: false,
363 },
9ebf276d
JH
364 {
365 name: "when user does not have required permission",
366 args: args{
367 cc: &ClientConn{
368 Account: &Account{
369 Access: func() *[]byte {
370 var bits accessBitmap
371 access := bits[:]
372 return &access
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
JH
402 Account: &Account{
403 Access: func() *[]byte {
404 var bits accessBitmap
405 bits.Set(accessSendChat)
406 access := bits[:]
407 return &access
408 }(),
409 },
72dd37f1
JH
410 UserName: []byte("Testy McTest"),
411 Server: &Server{
412 Clients: map[uint16]*ClientConn{
413 uint16(1): {
414 Account: &Account{
415 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
416 },
417 ID: &[]byte{0, 1},
418 },
419 uint16(2): {
420 Account: &Account{
421 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
422 },
423 ID: &[]byte{0, 2},
424 },
425 },
426 },
427 },
428 t: &Transaction{
429 Fields: []Field{
430 NewField(fieldData, []byte("performed action")),
431 NewField(fieldChatOptions, []byte{0x00, 0x01}),
432 },
433 },
434 },
435 want: []Transaction{
436 {
437 clientID: &[]byte{0, 1},
438 Flags: 0x00,
439 IsReply: 0x00,
440 Type: []byte{0, 0x6a},
481631f6 441 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
72dd37f1
JH
442 ErrorCode: []byte{0, 0, 0, 0},
443 Fields: []Field{
444 NewField(fieldData, []byte("\r*** Testy McTest performed action")),
445 },
446 },
447 {
448 clientID: &[]byte{0, 2},
449 Flags: 0x00,
450 IsReply: 0x00,
451 Type: []byte{0, 0x6a},
481631f6 452 ID: []byte{0xf0, 0xc5, 0x34, 0x1e},
72dd37f1
JH
453 ErrorCode: []byte{0, 0, 0, 0},
454 Fields: []Field{
455 NewField(fieldData, []byte("\r*** Testy McTest performed action")),
456 },
457 },
458 },
459 wantErr: false,
460 },
6988a057
JH
461 {
462 name: "only sends chat msg to clients with accessReadChat permission",
463 args: args{
464 cc: &ClientConn{
9ebf276d
JH
465 Account: &Account{
466 Access: func() *[]byte {
467 var bits accessBitmap
468 bits.Set(accessSendChat)
469 access := bits[:]
470 return &access
471 }(),
472 },
72dd37f1 473 UserName: []byte{0x00, 0x01},
6988a057
JH
474 Server: &Server{
475 Clients: map[uint16]*ClientConn{
476 uint16(1): {
477 Account: &Account{
478 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
479 },
480 ID: &[]byte{0, 1},
481 },
482 uint16(2): {
483 Account: &Account{
484 Access: &[]byte{0, 0, 0, 0, 0, 0, 0, 0},
485 },
486 ID: &[]byte{0, 2},
487 },
488 },
489 },
490 },
491 t: &Transaction{
492 Fields: []Field{
493 NewField(fieldData, []byte("hai")),
494 },
495 },
496 },
497 want: []Transaction{
498 {
499 clientID: &[]byte{0, 1},
500 Flags: 0x00,
501 IsReply: 0x00,
502 Type: []byte{0, 0x6a},
503 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
504 ErrorCode: []byte{0, 0, 0, 0},
505 Fields: []Field{
506 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
507 },
508 },
509 },
510 wantErr: false,
511 },
481631f6
JH
512 {
513 name: "only sends private chat msg to members of private chat",
514 args: args{
515 cc: &ClientConn{
516 Account: &Account{
517 Access: func() *[]byte {
518 var bits accessBitmap
519 bits.Set(accessSendChat)
520 access := bits[:]
521 return &access
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{
541 Access: &[]byte{255, 255, 255, 255, 255, 255, 255, 255},
542 },
543 ID: &[]byte{0, 1},
544 },
545 uint16(2): {
546 Account: &Account{
547 Access: &[]byte{0, 0, 0, 0, 0, 0, 0, 0},
548 },
549 ID: &[]byte{0, 2},
550 },
551 uint16(3): {
552 Account: &Account{
553 Access: &[]byte{0, 0, 0, 0, 0, 0, 0, 0},
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{
628 Config: &Config{
29f329ae
JH
629 FileRoot: func() string {
630 path, _ := os.Getwd()
631 return path + "/test/config/Files"
632 }(),
72dd37f1
JH
633 },
634 },
635 },
636 t: NewTransaction(
637 tranGetFileInfo, nil,
638 NewField(fieldFileName, []byte("testfile.txt")),
639 NewField(fieldFilePath, []byte{0x00, 0x00}),
72dd37f1
JH
640 ),
641 },
642 wantRes: []Transaction{
643 {
644 clientID: &[]byte{0, 1},
645 Flags: 0x00,
646 IsReply: 0x01,
647 Type: []byte{0, 0xce},
648 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
649 ErrorCode: []byte{0, 0, 0, 0},
650 Fields: []Field{
651 NewField(fieldFileName, []byte("testfile.txt")),
2d52424e 652 NewField(fieldFileTypeString, []byte("Text File")),
2728d12b 653 NewField(fieldFileCreatorString, []byte("ttxt")),
5218c782 654 NewField(fieldFileComment, []byte{}),
72dd37f1 655 NewField(fieldFileType, []byte("TEXT")),
29f329ae
JH
656 NewField(fieldFileCreateDate, make([]byte, 8)),
657 NewField(fieldFileModifyDate, make([]byte, 8)),
72dd37f1
JH
658 NewField(fieldFileSize, []byte{0x0, 0x0, 0x0, 0x17}),
659 },
660 },
661 },
662 wantErr: false,
663 },
664 }
665 for _, tt := range tests {
666 t.Run(tt.name, func(t *testing.T) {
667 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
668
669 gotRes, err := HandleGetFileInfo(tt.args.cc, tt.args.t)
670 if (err != nil) != tt.wantErr {
671 t.Errorf("HandleGetFileInfo() error = %v, wantErr %v", err, tt.wantErr)
672 return
673 }
29f329ae
JH
674
675 // Clear the file timestamp fields to work around problems running the tests in multiple timezones
676 // TODO: revisit how to test this by mocking the stat calls
677 gotRes[0].Fields[5].Data = make([]byte, 8)
678 gotRes[0].Fields[6].Data = make([]byte, 8)
00d1ef67 679 if !assert.Equal(t, tt.wantRes, gotRes) {
72dd37f1
JH
680 t.Errorf("HandleGetFileInfo() gotRes = %v, want %v", gotRes, tt.wantRes)
681 }
682 })
683 }
684}
00d1ef67
JH
685
686func TestHandleNewFolder(t *testing.T) {
687 type args struct {
688 cc *ClientConn
689 t *Transaction
690 }
691 tests := []struct {
692 setup func()
693 name string
694 args args
695 wantRes []Transaction
696 wantErr bool
697 }{
698 {
699 name: "when path is nested",
700 args: args{
701 cc: &ClientConn{
702 ID: &[]byte{0, 1},
703 Server: &Server{
704 Config: &Config{
705 FileRoot: "/Files/",
706 },
707 },
708 },
709 t: NewTransaction(
710 tranNewFolder, &[]byte{0, 1},
711 NewField(fieldFileName, []byte("testFolder")),
712 NewField(fieldFilePath, []byte{
713 0x00, 0x01,
714 0x00, 0x00,
715 0x03,
716 0x61, 0x61, 0x61,
717 }),
718 ),
719 },
720 setup: func() {
aebc4d36 721 mfs := &MockFileStore{}
00d1ef67
JH
722 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
723 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
724 FS = mfs
725 },
726 wantRes: []Transaction{
727 {
728 clientID: &[]byte{0, 1},
729 Flags: 0x00,
730 IsReply: 0x01,
731 Type: []byte{0, 0xcd},
732 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
733 ErrorCode: []byte{0, 0, 0, 0},
734 },
735 },
736 wantErr: false,
737 },
738 {
739 name: "when path is not nested",
740 args: args{
741 cc: &ClientConn{
742 ID: &[]byte{0, 1},
743 Server: &Server{
744 Config: &Config{
745 FileRoot: "/Files",
746 },
747 },
748 },
749 t: NewTransaction(
750 tranNewFolder, &[]byte{0, 1},
751 NewField(fieldFileName, []byte("testFolder")),
752 ),
753 },
754 setup: func() {
aebc4d36 755 mfs := &MockFileStore{}
00d1ef67
JH
756 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
757 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
758 FS = mfs
759 },
760 wantRes: []Transaction{
761 {
762 clientID: &[]byte{0, 1},
763 Flags: 0x00,
764 IsReply: 0x01,
765 Type: []byte{0, 0xcd},
766 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
767 ErrorCode: []byte{0, 0, 0, 0},
768 },
769 },
770 wantErr: false,
771 },
772 {
773 name: "when UnmarshalBinary returns an err",
774 args: args{
775 cc: &ClientConn{
776 ID: &[]byte{0, 1},
777 Server: &Server{
778 Config: &Config{
779 FileRoot: "/Files/",
780 },
781 },
782 },
783 t: NewTransaction(
784 tranNewFolder, &[]byte{0, 1},
785 NewField(fieldFileName, []byte("testFolder")),
786 NewField(fieldFilePath, []byte{
787 0x00,
788 }),
789 ),
790 },
791 setup: func() {
aebc4d36 792 mfs := &MockFileStore{}
00d1ef67
JH
793 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
794 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
795 FS = mfs
796 },
797 wantRes: []Transaction{},
798 wantErr: true,
799 },
800 {
801 name: "fieldFileName does not allow directory traversal",
802 args: args{
803 cc: &ClientConn{
804 ID: &[]byte{0, 1},
805 Server: &Server{
806 Config: &Config{
807 FileRoot: "/Files/",
808 },
809 },
810 },
811 t: NewTransaction(
812 tranNewFolder, &[]byte{0, 1},
813 NewField(fieldFileName, []byte("../../testFolder")),
00d1ef67
JH
814 ),
815 },
816 setup: func() {
aebc4d36 817 mfs := &MockFileStore{}
00d1ef67
JH
818 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
819 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
820 FS = mfs
821 },
822 wantRes: []Transaction{
823 {
824 clientID: &[]byte{0, 1},
825 Flags: 0x00,
826 IsReply: 0x01,
827 Type: []byte{0, 0xcd},
828 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
829 ErrorCode: []byte{0, 0, 0, 0},
830 },
92a7e455 831 }, wantErr: false,
00d1ef67
JH
832 },
833 {
834 name: "fieldFilePath does not allow directory traversal",
835 args: args{
836 cc: &ClientConn{
837 ID: &[]byte{0, 1},
838 Server: &Server{
839 Config: &Config{
840 FileRoot: "/Files/",
841 },
842 },
843 },
844 t: NewTransaction(
845 tranNewFolder, &[]byte{0, 1},
846 NewField(fieldFileName, []byte("testFolder")),
847 NewField(fieldFilePath, []byte{
848 0x00, 0x02,
849 0x00, 0x00,
850 0x03,
851 0x2e, 0x2e, 0x2f,
852 0x00, 0x00,
853 0x03,
854 0x66, 0x6f, 0x6f,
855 }),
856 ),
857 },
858 setup: func() {
aebc4d36 859 mfs := &MockFileStore{}
00d1ef67
JH
860 mfs.On("Mkdir", "/Files/foo/testFolder", fs.FileMode(0777)).Return(nil)
861 mfs.On("Stat", "/Files/foo/testFolder").Return(nil, os.ErrNotExist)
862 FS = mfs
863 },
864 wantRes: []Transaction{
865 {
866 clientID: &[]byte{0, 1},
867 Flags: 0x00,
868 IsReply: 0x01,
869 Type: []byte{0, 0xcd},
870 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
871 ErrorCode: []byte{0, 0, 0, 0},
872 },
92a7e455 873 }, wantErr: false,
00d1ef67
JH
874 },
875 }
876 for _, tt := range tests {
877 t.Run(tt.name, func(t *testing.T) {
878 tt.setup()
879
880 gotRes, err := HandleNewFolder(tt.args.cc, tt.args.t)
881 if (err != nil) != tt.wantErr {
882 t.Errorf("HandleNewFolder() error = %v, wantErr %v", err, tt.wantErr)
883 return
884 }
885 if !tranAssertEqual(t, tt.wantRes, gotRes) {
886 t.Errorf("HandleNewFolder() gotRes = %v, want %v", gotRes, tt.wantRes)
887 }
888 })
889 }
890}
891
92a7e455
JH
892func TestHandleUploadFile(t *testing.T) {
893 type args struct {
894 cc *ClientConn
895 t *Transaction
896 }
897 tests := []struct {
898 name string
899 args args
900 wantRes []Transaction
901 wantErr bool
902 }{
903 {
7e2e07da 904 name: "when request is valid and user has Upload Anywhere permission",
92a7e455
JH
905 args: args{
906 cc: &ClientConn{
907 Server: &Server{
908 FileTransfers: map[uint32]*FileTransfer{},
909 },
910 Account: &Account{
911 Access: func() *[]byte {
912 var bits accessBitmap
913 bits.Set(accessUploadFile)
7e2e07da 914 bits.Set(accessUploadAnywhere)
92a7e455
JH
915 access := bits[:]
916 return &access
917 }(),
918 },
919 },
920 t: NewTransaction(
921 tranUploadFile, &[]byte{0, 1},
922 NewField(fieldFileName, []byte("testFile")),
923 NewField(fieldFilePath, []byte{
924 0x00, 0x01,
925 0x00, 0x00,
926 0x03,
927 0x2e, 0x2e, 0x2f,
928 }),
929 ),
930 },
931 wantRes: []Transaction{
932 {
933 Flags: 0x00,
934 IsReply: 0x01,
935 Type: []byte{0, 0xcb},
936 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
937 ErrorCode: []byte{0, 0, 0, 0},
938 Fields: []Field{
939 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}), // rand.Seed(1)
940 },
941 },
942 },
943 wantErr: false,
944 },
945 {
946 name: "when user does not have required access",
947 args: args{
948 cc: &ClientConn{
949 Account: &Account{
950 Access: func() *[]byte {
951 var bits accessBitmap
952 access := bits[:]
953 return &access
954 }(),
955 },
956 Server: &Server{
957 FileTransfers: map[uint32]*FileTransfer{},
958 },
959 },
960 t: NewTransaction(
961 tranUploadFile, &[]byte{0, 1},
962 NewField(fieldFileName, []byte("testFile")),
963 NewField(fieldFilePath, []byte{
964 0x00, 0x01,
965 0x00, 0x00,
966 0x03,
967 0x2e, 0x2e, 0x2f,
968 }),
969 ),
970 },
971 wantRes: []Transaction{
972 {
973 Flags: 0x00,
974 IsReply: 0x01,
975 Type: []byte{0, 0x00},
976 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
977 ErrorCode: []byte{0, 0, 0, 1},
978 Fields: []Field{
979 NewField(fieldError, []byte("You are not allowed to upload files.")), // rand.Seed(1)
980 },
981 },
982 },
983 wantErr: false,
984 },
985 }
986 for _, tt := range tests {
987 t.Run(tt.name, func(t *testing.T) {
988 rand.Seed(1)
989 gotRes, err := HandleUploadFile(tt.args.cc, tt.args.t)
990 if (err != nil) != tt.wantErr {
991 t.Errorf("HandleUploadFile() error = %v, wantErr %v", err, tt.wantErr)
992 return
993 }
aebc4d36
JH
994
995 tranAssertEqual(t, tt.wantRes, gotRes)
996
92a7e455
JH
997 })
998 }
999}
decc2fbf
JH
1000
1001func TestHandleMakeAlias(t *testing.T) {
1002 type args struct {
1003 cc *ClientConn
1004 t *Transaction
1005 }
1006 tests := []struct {
1007 name string
1008 setup func()
1009 args args
1010 wantRes []Transaction
1011 wantErr bool
1012 }{
1013 {
1014 name: "with valid input and required permissions",
1015 setup: func() {
aebc4d36 1016 mfs := &MockFileStore{}
decc2fbf
JH
1017 path, _ := os.Getwd()
1018 mfs.On(
1019 "Symlink",
1020 path+"/test/config/Files/foo/testFile",
1021 path+"/test/config/Files/bar/testFile",
1022 ).Return(nil)
1023 FS = mfs
1024 },
1025 args: args{
1026 cc: &ClientConn{
1027 Account: &Account{
1028 Access: func() *[]byte {
1029 var bits accessBitmap
1030 bits.Set(accessMakeAlias)
1031 access := bits[:]
1032 return &access
1033 }(),
1034 },
1035 Server: &Server{
1036 Config: &Config{
1037 FileRoot: func() string {
1038 path, _ := os.Getwd()
1039 return path + "/test/config/Files"
1040 }(),
1041 },
1042 Logger: NewTestLogger(),
1043 },
1044 },
1045 t: NewTransaction(
1046 tranMakeFileAlias, &[]byte{0, 1},
1047 NewField(fieldFileName, []byte("testFile")),
1048 NewField(fieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1049 NewField(fieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1050 ),
1051 },
1052 wantRes: []Transaction{
1053 {
1054 Flags: 0x00,
1055 IsReply: 0x01,
1056 Type: []byte{0, 0xd1},
1057 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1058 ErrorCode: []byte{0, 0, 0, 0},
1059 Fields: []Field(nil),
1060 },
1061 },
1062 wantErr: false,
1063 },
1064 {
1065 name: "when symlink returns an error",
1066 setup: func() {
aebc4d36 1067 mfs := &MockFileStore{}
decc2fbf
JH
1068 path, _ := os.Getwd()
1069 mfs.On(
1070 "Symlink",
1071 path+"/test/config/Files/foo/testFile",
1072 path+"/test/config/Files/bar/testFile",
1073 ).Return(errors.New("ohno"))
1074 FS = mfs
1075 },
1076 args: args{
1077 cc: &ClientConn{
1078 Account: &Account{
1079 Access: func() *[]byte {
1080 var bits accessBitmap
1081 bits.Set(accessMakeAlias)
1082 access := bits[:]
1083 return &access
1084 }(),
1085 },
1086 Server: &Server{
1087 Config: &Config{
1088 FileRoot: func() string {
1089 path, _ := os.Getwd()
1090 return path + "/test/config/Files"
1091 }(),
1092 },
1093 Logger: NewTestLogger(),
1094 },
1095 },
1096 t: NewTransaction(
1097 tranMakeFileAlias, &[]byte{0, 1},
1098 NewField(fieldFileName, []byte("testFile")),
1099 NewField(fieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1100 NewField(fieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1101 ),
1102 },
1103 wantRes: []Transaction{
1104 {
1105 Flags: 0x00,
1106 IsReply: 0x01,
1107 Type: []byte{0, 0x00},
1108 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1109 ErrorCode: []byte{0, 0, 0, 1},
1110 Fields: []Field{
1111 NewField(fieldError, []byte("Error creating alias")),
1112 },
1113 },
1114 },
1115 wantErr: false,
1116 },
1117 {
1118 name: "when user does not have required permission",
1119 setup: func() {},
1120 args: args{
1121 cc: &ClientConn{
1122 Account: &Account{
1123 Access: func() *[]byte {
1124 var bits accessBitmap
1125 access := bits[:]
1126 return &access
1127 }(),
1128 },
1129 Server: &Server{
1130 Config: &Config{
1131 FileRoot: func() string {
1132 path, _ := os.Getwd()
1133 return path + "/test/config/Files"
1134 }(),
1135 },
1136 },
1137 },
1138 t: NewTransaction(
1139 tranMakeFileAlias, &[]byte{0, 1},
1140 NewField(fieldFileName, []byte("testFile")),
1141 NewField(fieldFilePath, []byte{
1142 0x00, 0x01,
1143 0x00, 0x00,
1144 0x03,
1145 0x2e, 0x2e, 0x2e,
1146 }),
1147 NewField(fieldFileNewPath, []byte{
1148 0x00, 0x01,
1149 0x00, 0x00,
1150 0x03,
1151 0x2e, 0x2e, 0x2e,
1152 }),
1153 ),
1154 },
1155 wantRes: []Transaction{
1156 {
1157 Flags: 0x00,
1158 IsReply: 0x01,
1159 Type: []byte{0, 0x00},
1160 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1161 ErrorCode: []byte{0, 0, 0, 1},
1162 Fields: []Field{
1163 NewField(fieldError, []byte("You are not allowed to make aliases.")),
1164 },
1165 },
1166 },
1167 wantErr: false,
1168 },
1169 }
1170 for _, tt := range tests {
1171 t.Run(tt.name, func(t *testing.T) {
1172 tt.setup()
1173
1174 gotRes, err := HandleMakeAlias(tt.args.cc, tt.args.t)
1175 if (err != nil) != tt.wantErr {
1176 t.Errorf("HandleMakeAlias(%v, %v)", tt.args.cc, tt.args.t)
1177 return
1178 }
1179
1180 tranAssertEqual(t, tt.wantRes, gotRes)
1181 })
1182 }
1183}
9ebf276d
JH
1184
1185func TestHandleGetUser(t *testing.T) {
1186 type args struct {
1187 cc *ClientConn
1188 t *Transaction
1189 }
1190 tests := []struct {
1191 name string
1192 args args
1193 wantRes []Transaction
1194 wantErr assert.ErrorAssertionFunc
1195 }{
1196 {
1197 name: "when account is valid",
1198 args: args{
1199 cc: &ClientConn{
1200 Account: &Account{
1201 Access: func() *[]byte {
1202 var bits accessBitmap
1203 bits.Set(accessOpenUser)
1204 access := bits[:]
1205 return &access
1206 }(),
1207 },
1208 Server: &Server{
1209 Accounts: map[string]*Account{
1210 "guest": {
1211 Login: "guest",
1212 Name: "Guest",
1213 Password: "password",
1214 Access: &[]byte{1},
1215 },
1216 },
1217 },
1218 },
1219 t: NewTransaction(
1220 tranGetUser, &[]byte{0, 1},
1221 NewField(fieldUserLogin, []byte("guest")),
1222 ),
1223 },
1224 wantRes: []Transaction{
1225 {
1226 Flags: 0x00,
1227 IsReply: 0x01,
1228 Type: []byte{0x01, 0x60},
1229 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1230 ErrorCode: []byte{0, 0, 0, 0},
1231 Fields: []Field{
1232 NewField(fieldUserName, []byte("Guest")),
1233 NewField(fieldUserLogin, negateString([]byte("guest"))),
1234 NewField(fieldUserPassword, []byte("password")),
1235 NewField(fieldUserAccess, []byte{1}),
1236 },
1237 },
1238 },
1239 wantErr: assert.NoError,
1240 },
1241 {
1242 name: "when user does not have required permission",
1243 args: args{
1244 cc: &ClientConn{
1245 Account: &Account{
1246 Access: func() *[]byte {
1247 var bits accessBitmap
1248 access := bits[:]
1249 return &access
1250 }(),
1251 },
1252 Server: &Server{
1253 Accounts: map[string]*Account{},
1254 },
1255 },
1256 t: NewTransaction(
1257 tranGetUser, &[]byte{0, 1},
1258 NewField(fieldUserLogin, []byte("nonExistentUser")),
1259 ),
1260 },
1261 wantRes: []Transaction{
1262 {
1263 Flags: 0x00,
1264 IsReply: 0x01,
1265 Type: []byte{0, 0x00},
1266 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1267 ErrorCode: []byte{0, 0, 0, 1},
1268 Fields: []Field{
1269 NewField(fieldError, []byte("You are not allowed to view accounts.")),
1270 },
1271 },
1272 },
1273 wantErr: assert.NoError,
1274 },
1275 {
1276 name: "when account does not exist",
1277 args: args{
1278 cc: &ClientConn{
1279 Account: &Account{
1280 Access: func() *[]byte {
1281 var bits accessBitmap
1282 bits.Set(accessOpenUser)
1283 access := bits[:]
1284 return &access
1285 }(),
1286 },
1287 Server: &Server{
1288 Accounts: map[string]*Account{},
1289 },
1290 },
1291 t: NewTransaction(
1292 tranGetUser, &[]byte{0, 1},
1293 NewField(fieldUserLogin, []byte("nonExistentUser")),
1294 ),
1295 },
1296 wantRes: []Transaction{
1297 {
1298 Flags: 0x00,
1299 IsReply: 0x01,
1300 Type: []byte{0, 0x00},
1301 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1302 ErrorCode: []byte{0, 0, 0, 1},
1303 Fields: []Field{
1304 NewField(fieldError, []byte("Account does not exist.")),
1305 },
1306 },
1307 },
1308 wantErr: assert.NoError,
1309 },
1310 }
1311 for _, tt := range tests {
1312 t.Run(tt.name, func(t *testing.T) {
1313 gotRes, err := HandleGetUser(tt.args.cc, tt.args.t)
1314 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetUser(%v, %v)", tt.args.cc, tt.args.t)) {
1315 return
1316 }
1317
1318 tranAssertEqual(t, tt.wantRes, gotRes)
1319 })
1320 }
1321}
1322
1323func TestHandleDeleteUser(t *testing.T) {
1324 type args struct {
1325 cc *ClientConn
1326 t *Transaction
1327 }
1328 tests := []struct {
1329 name string
1330 setup func()
1331 args args
1332 wantRes []Transaction
1333 wantErr assert.ErrorAssertionFunc
1334 }{
1335 {
1336 name: "when user exists",
1337 setup: func() {
1338 mfs := &MockFileStore{}
1339 mfs.On("Remove", "Users/testuser.yaml").Return(nil)
1340 FS = mfs
1341 },
1342 args: args{
1343 cc: &ClientConn{
1344 Account: &Account{
1345 Access: func() *[]byte {
1346 var bits accessBitmap
1347 bits.Set(accessDeleteUser)
1348 access := bits[:]
1349 return &access
1350 }(),
1351 },
1352 Server: &Server{
1353 Accounts: map[string]*Account{
1354 "testuser": {
1355 Login: "testuser",
1356 Name: "Testy McTest",
1357 Password: "password",
1358 Access: &[]byte{1},
1359 },
1360 },
1361 },
1362 },
1363 t: NewTransaction(
1364 tranDeleteUser, &[]byte{0, 1},
1365 NewField(fieldUserLogin, negateString([]byte("testuser"))),
1366 ),
1367 },
1368 wantRes: []Transaction{
1369 {
1370 Flags: 0x00,
1371 IsReply: 0x01,
1372 Type: []byte{0x1, 0x5f},
1373 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1374 ErrorCode: []byte{0, 0, 0, 0},
1375 Fields: []Field(nil),
1376 },
1377 },
1378 wantErr: assert.NoError,
1379 },
1380 {
1381 name: "when user does not have required permission",
1382 setup: func() {},
1383 args: args{
1384 cc: &ClientConn{
1385 Account: &Account{
1386 Access: func() *[]byte {
1387 var bits accessBitmap
1388 access := bits[:]
1389 return &access
1390 }(),
1391 },
1392 Server: &Server{
1393 Accounts: map[string]*Account{},
1394 },
1395 },
1396 t: NewTransaction(
1397 tranDeleteUser, &[]byte{0, 1},
1398 NewField(fieldUserLogin, negateString([]byte("testuser"))),
1399 ),
1400 },
1401 wantRes: []Transaction{
1402 {
1403 Flags: 0x00,
1404 IsReply: 0x01,
1405 Type: []byte{0, 0x00},
1406 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1407 ErrorCode: []byte{0, 0, 0, 1},
1408 Fields: []Field{
1409 NewField(fieldError, []byte("You are not allowed to delete accounts.")),
1410 },
1411 },
1412 },
1413 wantErr: assert.NoError,
1414 },
1415 }
1416 for _, tt := range tests {
1417 t.Run(tt.name, func(t *testing.T) {
1418 tt.setup()
1419 gotRes, err := HandleDeleteUser(tt.args.cc, tt.args.t)
1420 if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteUser(%v, %v)", tt.args.cc, tt.args.t)) {
1421 return
1422 }
1423
1424 tranAssertEqual(t, tt.wantRes, gotRes)
1425 })
1426 }
1427}
481631f6
JH
1428
1429func TestHandleGetMsgs(t *testing.T) {
1430 type args struct {
1431 cc *ClientConn
1432 t *Transaction
1433 }
1434 tests := []struct {
1435 name string
1436 args args
1437 wantRes []Transaction
1438 wantErr assert.ErrorAssertionFunc
1439 }{
1440 {
1441 name: "returns news data",
1442 args: args{
1443 cc: &ClientConn{
1444 Account: &Account{
1445 Access: func() *[]byte {
1446 var bits accessBitmap
1447 bits.Set(accessNewsReadArt)
1448 access := bits[:]
1449 return &access
1450 }(),
1451 },
1452 Server: &Server{
1453 FlatNews: []byte("TEST"),
1454 },
1455 },
1456 t: NewTransaction(
1457 tranGetMsgs, &[]byte{0, 1},
1458 ),
1459 },
1460 wantRes: []Transaction{
1461 {
1462 Flags: 0x00,
1463 IsReply: 0x01,
1464 Type: []byte{0, 0x65},
1465 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1466 ErrorCode: []byte{0, 0, 0, 0},
1467 Fields: []Field{
1468 NewField(fieldData, []byte("TEST")),
1469 },
1470 },
1471 },
1472 wantErr: assert.NoError,
1473 },
1474 {
1475 name: "when user does not have required permission",
1476 args: args{
1477 cc: &ClientConn{
1478 Account: &Account{
1479 Access: func() *[]byte {
1480 var bits accessBitmap
1481 access := bits[:]
1482 return &access
1483 }(),
1484 },
1485 Server: &Server{
1486 Accounts: map[string]*Account{},
1487 },
1488 },
1489 t: NewTransaction(
1490 tranGetMsgs, &[]byte{0, 1},
1491 ),
1492 },
1493 wantRes: []Transaction{
1494 {
1495 Flags: 0x00,
1496 IsReply: 0x01,
1497 Type: []byte{0, 0x00},
1498 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1499 ErrorCode: []byte{0, 0, 0, 1},
1500 Fields: []Field{
1501 NewField(fieldError, []byte("You are not allowed to read news.")),
1502 },
1503 },
1504 },
1505 wantErr: assert.NoError,
1506 },
1507 }
1508 for _, tt := range tests {
1509 t.Run(tt.name, func(t *testing.T) {
1510 gotRes, err := HandleGetMsgs(tt.args.cc, tt.args.t)
1511 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetMsgs(%v, %v)", tt.args.cc, tt.args.t)) {
1512 return
1513 }
1514
1515 tranAssertEqual(t, tt.wantRes, gotRes)
1516 })
1517 }
1518}
1519
1520func TestHandleNewUser(t *testing.T) {
1521 type args struct {
1522 cc *ClientConn
1523 t *Transaction
1524 }
1525 tests := []struct {
1526 name string
1527 args args
1528 wantRes []Transaction
1529 wantErr assert.ErrorAssertionFunc
1530 }{
1531 {
1532 name: "when user does not have required permission",
1533 args: args{
1534 cc: &ClientConn{
1535 Account: &Account{
1536 Access: func() *[]byte {
1537 var bits accessBitmap
1538 access := bits[:]
1539 return &access
1540 }(),
1541 },
1542 Server: &Server{
1543 Accounts: map[string]*Account{},
1544 },
1545 },
1546 t: NewTransaction(
1547 tranNewUser, &[]byte{0, 1},
1548 ),
1549 },
1550 wantRes: []Transaction{
1551 {
1552 Flags: 0x00,
1553 IsReply: 0x01,
1554 Type: []byte{0, 0x00},
1555 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1556 ErrorCode: []byte{0, 0, 0, 1},
1557 Fields: []Field{
1558 NewField(fieldError, []byte("You are not allowed to create new accounts.")),
1559 },
1560 },
1561 },
1562 wantErr: assert.NoError,
1563 },
1564 }
1565 for _, tt := range tests {
1566 t.Run(tt.name, func(t *testing.T) {
1567 gotRes, err := HandleNewUser(tt.args.cc, tt.args.t)
1568 if !tt.wantErr(t, err, fmt.Sprintf("HandleNewUser(%v, %v)", tt.args.cc, tt.args.t)) {
1569 return
1570 }
1571
1572 tranAssertEqual(t, tt.wantRes, gotRes)
1573 })
1574 }
1575}
1576
1577func TestHandleListUsers(t *testing.T) {
1578 type args struct {
1579 cc *ClientConn
1580 t *Transaction
1581 }
1582 tests := []struct {
1583 name string
1584 args args
1585 wantRes []Transaction
1586 wantErr assert.ErrorAssertionFunc
1587 }{
1588 {
1589 name: "when user does not have required permission",
1590 args: args{
1591 cc: &ClientConn{
1592 Account: &Account{
1593 Access: func() *[]byte {
1594 var bits accessBitmap
1595 access := bits[:]
1596 return &access
1597 }(),
1598 },
1599 Server: &Server{
1600 Accounts: map[string]*Account{},
1601 },
1602 },
1603 t: NewTransaction(
1604 tranNewUser, &[]byte{0, 1},
1605 ),
1606 },
1607 wantRes: []Transaction{
1608 {
1609 Flags: 0x00,
1610 IsReply: 0x01,
1611 Type: []byte{0, 0x00},
1612 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1613 ErrorCode: []byte{0, 0, 0, 1},
1614 Fields: []Field{
1615 NewField(fieldError, []byte("You are not allowed to view accounts.")),
1616 },
1617 },
1618 },
1619 wantErr: assert.NoError,
1620 },
1621 }
1622 for _, tt := range tests {
1623 t.Run(tt.name, func(t *testing.T) {
1624 gotRes, err := HandleListUsers(tt.args.cc, tt.args.t)
1625 if !tt.wantErr(t, err, fmt.Sprintf("HandleListUsers(%v, %v)", tt.args.cc, tt.args.t)) {
1626 return
1627 }
1628
1629 tranAssertEqual(t, tt.wantRes, gotRes)
1630 })
1631 }
1632}
1633
1634func TestHandleDownloadFile(t *testing.T) {
1635 type args struct {
1636 cc *ClientConn
1637 t *Transaction
1638 }
1639 tests := []struct {
1640 name string
1641 args args
1642 wantRes []Transaction
1643 wantErr assert.ErrorAssertionFunc
1644 }{
1645 {
1646 name: "when user does not have required permission",
1647 args: args{
1648 cc: &ClientConn{
1649 Account: &Account{
1650 Access: func() *[]byte {
1651 var bits accessBitmap
1652 access := bits[:]
1653 return &access
1654 }(),
1655 },
1656 Server: &Server{},
1657 },
1658 t: NewTransaction(tranDownloadFile, &[]byte{0, 1}),
1659 },
1660 wantRes: []Transaction{
1661 {
1662 Flags: 0x00,
1663 IsReply: 0x01,
1664 Type: []byte{0, 0x00},
1665 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1666 ErrorCode: []byte{0, 0, 0, 1},
1667 Fields: []Field{
1668 NewField(fieldError, []byte("You are not allowed to download files.")),
1669 },
1670 },
1671 },
1672 wantErr: assert.NoError,
1673 },
1674 {
1675 name: "with a valid file",
1676 args: args{
1677 cc: &ClientConn{
1678 Transfers: make(map[int][]*FileTransfer),
1679 Account: &Account{
1680 Access: func() *[]byte {
1681 var bits accessBitmap
1682 bits.Set(accessDownloadFile)
1683 access := bits[:]
1684 return &access
1685 }(),
1686 },
1687 Server: &Server{
1688 FileTransfers: make(map[uint32]*FileTransfer),
1689 Config: &Config{
1690 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1691 },
1692 Accounts: map[string]*Account{},
1693 },
1694 },
1695 t: NewTransaction(
1696 accessDownloadFile,
1697 &[]byte{0, 1},
1698 NewField(fieldFileName, []byte("testfile.txt")),
1699 NewField(fieldFilePath, []byte{0x0, 0x00}),
1700 ),
1701 },
1702 wantRes: []Transaction{
1703 {
1704 Flags: 0x00,
1705 IsReply: 0x01,
1706 Type: []byte{0, 0x2},
1707 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1708 ErrorCode: []byte{0, 0, 0, 0},
1709 Fields: []Field{
1710 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1711 NewField(fieldWaitingCount, []byte{0x00, 0x00}),
1712 NewField(fieldTransferSize, []byte{0x00, 0x00, 0x00, 0xa5}),
1713 NewField(fieldFileSize, []byte{0x00, 0x00, 0x00, 0x17}),
1714 },
1715 },
1716 },
1717 wantErr: assert.NoError,
1718 },
1719 }
1720 for _, tt := range tests {
1721 t.Run(tt.name, func(t *testing.T) {
1722 // reset the rand seed so that the random fieldRefNum will be deterministic
1723 rand.Seed(1)
1724
1725 gotRes, err := HandleDownloadFile(tt.args.cc, tt.args.t)
1726 if !tt.wantErr(t, err, fmt.Sprintf("HandleDownloadFile(%v, %v)", tt.args.cc, tt.args.t)) {
1727 return
1728 }
1729
1730 tranAssertEqual(t, tt.wantRes, gotRes)
1731 })
1732 }
1733}
d2810ae9
JH
1734
1735func TestHandleUpdateUser(t *testing.T) {
1736 type args struct {
1737 cc *ClientConn
1738 t *Transaction
1739 }
1740 tests := []struct {
1741 name string
1742 args args
1743 wantRes []Transaction
1744 wantErr assert.ErrorAssertionFunc
1745 }{
1746 {
1747 name: "when action is create user without required permission",
1748 args: args{
1749 cc: &ClientConn{
1750 Server: &Server{
1751 Logger: NewTestLogger(),
1752 },
1753 Account: &Account{
1754 Access: func() *[]byte {
1755 var bits accessBitmap
1756 access := bits[:]
1757 return &access
1758 }(),
1759 },
1760 },
1761 t: NewTransaction(
1762 tranUpdateUser,
1763 &[]byte{0, 0},
1764 NewField(fieldData, []byte{
1765 0x00, 0x04, // field count
1766
1767 0x00, 0x69, // fieldUserLogin = 105
1768 0x00, 0x03,
1769 0x9d, 0x9d, 0x9d,
1770
1771 0x00, 0x6a, // fieldUserPassword = 106
1772 0x00, 0x03,
1773 0x9c, 0x9c, 0x9c,
1774
1775 0x00, 0x66, // fieldUserName = 102
1776 0x00, 0x03,
1777 0x61, 0x61, 0x61,
1778
1779 0x00, 0x6e, // fieldUserAccess = 110
1780 0x00, 0x08,
1781 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
1782 }),
1783 ),
1784 },
1785 wantRes: []Transaction{
1786 {
1787 Flags: 0x00,
1788 IsReply: 0x01,
1789 Type: []byte{0, 0x00},
1790 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1791 ErrorCode: []byte{0, 0, 0, 1},
1792 Fields: []Field{
1793 NewField(fieldError, []byte("You are not allowed to create new accounts.")),
1794 },
1795 },
1796 },
1797 wantErr: assert.NoError,
1798 },
1799 {
1800 name: "when action is modify user without required permission",
1801 args: args{
1802 cc: &ClientConn{
1803 Server: &Server{
1804 Logger: NewTestLogger(),
1805 Accounts: map[string]*Account{
1806 "bbb": {},
1807 },
1808 },
1809 Account: &Account{
1810 Access: func() *[]byte {
1811 var bits accessBitmap
1812 access := bits[:]
1813 return &access
1814 }(),
1815 },
1816 },
1817 t: NewTransaction(
1818 tranUpdateUser,
1819 &[]byte{0, 0},
1820 NewField(fieldData, []byte{
1821 0x00, 0x04, // field count
1822
1823 0x00, 0x69, // fieldUserLogin = 105
1824 0x00, 0x03,
1825 0x9d, 0x9d, 0x9d,
1826
1827 0x00, 0x6a, // fieldUserPassword = 106
1828 0x00, 0x03,
1829 0x9c, 0x9c, 0x9c,
1830
1831 0x00, 0x66, // fieldUserName = 102
1832 0x00, 0x03,
1833 0x61, 0x61, 0x61,
1834
1835 0x00, 0x6e, // fieldUserAccess = 110
1836 0x00, 0x08,
1837 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
1838 }),
1839 ),
1840 },
1841 wantRes: []Transaction{
1842 {
1843 Flags: 0x00,
1844 IsReply: 0x01,
1845 Type: []byte{0, 0x00},
1846 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1847 ErrorCode: []byte{0, 0, 0, 1},
1848 Fields: []Field{
1849 NewField(fieldError, []byte("You are not allowed to modify accounts.")),
1850 },
1851 },
1852 },
1853 wantErr: assert.NoError,
1854 },
1855 {
1856 name: "when action is delete user without required permission",
1857 args: args{
1858 cc: &ClientConn{
1859 Server: &Server{
1860 Logger: NewTestLogger(),
1861 Accounts: map[string]*Account{
1862 "bbb": {},
1863 },
1864 },
1865 Account: &Account{
1866 Access: func() *[]byte {
1867 var bits accessBitmap
1868 access := bits[:]
1869 return &access
1870 }(),
1871 },
1872 },
1873 t: NewTransaction(
1874 tranUpdateUser,
1875 &[]byte{0, 0},
1876 NewField(fieldData, []byte{
1877 0x00, 0x01,
1878 0x00, 0x65,
1879 0x00, 0x03,
1880 0x88, 0x9e, 0x8b,
1881 }),
1882 ),
1883 },
1884 wantRes: []Transaction{
1885 {
1886 Flags: 0x00,
1887 IsReply: 0x01,
1888 Type: []byte{0, 0x00},
1889 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1890 ErrorCode: []byte{0, 0, 0, 1},
1891 Fields: []Field{
1892 NewField(fieldError, []byte("You are not allowed to delete accounts.")),
1893 },
1894 },
1895 },
1896 wantErr: assert.NoError,
1897 },
1898 }
1899 for _, tt := range tests {
1900 t.Run(tt.name, func(t *testing.T) {
1901 gotRes, err := HandleUpdateUser(tt.args.cc, tt.args.t)
1902 if !tt.wantErr(t, err, fmt.Sprintf("HandleUpdateUser(%v, %v)", tt.args.cc, tt.args.t)) {
1903 return
1904 }
1905
1906 tranAssertEqual(t, tt.wantRes, gotRes)
1907 })
1908 }
1909}