]> git.r.bdr.sh - rbdr/mobius/blob - hotline/transaction_handlers_test.go
Fix handling of refuse PM flag
[rbdr/mobius] / hotline / transaction_handlers_test.go
1 package hotline
2
3 import (
4 "errors"
5 "fmt"
6 "github.com/stretchr/testify/assert"
7 "github.com/stretchr/testify/mock"
8 "io/fs"
9 "math/rand"
10 "os"
11 "path/filepath"
12 "strings"
13 "testing"
14 "time"
15 )
16
17 func TestHandleSetChatSubject(t *testing.T) {
18 type args struct {
19 cc *ClientConn
20 t *Transaction
21 }
22 tests := []struct {
23 name string
24 args args
25 want []Transaction
26 wantErr bool
27 }{
28 {
29 name: "sends chat subject to private chat members",
30 args: args{
31 cc: &ClientConn{
32 UserName: []byte{0x00, 0x01},
33 Server: &Server{
34 PrivateChats: map[uint32]*PrivateChat{
35 uint32(1): {
36 Subject: "unset",
37 ClientConn: map[uint16]*ClientConn{
38 uint16(1): {
39 Account: &Account{
40 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
41 },
42 ID: &[]byte{0, 1},
43 },
44 uint16(2): {
45 Account: &Account{
46 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
47 },
48 ID: &[]byte{0, 2},
49 },
50 },
51 },
52 },
53 Clients: map[uint16]*ClientConn{
54 uint16(1): {
55 Account: &Account{
56 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
57 },
58 ID: &[]byte{0, 1},
59 },
60 uint16(2): {
61 Account: &Account{
62 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
63 },
64 ID: &[]byte{0, 2},
65 },
66 },
67 },
68 },
69 t: &Transaction{
70 Flags: 0x00,
71 IsReply: 0x00,
72 Type: []byte{0, 0x6a},
73 ID: []byte{0, 0, 0, 1},
74 ErrorCode: []byte{0, 0, 0, 0},
75 Fields: []Field{
76 NewField(FieldChatID, []byte{0, 0, 0, 1}),
77 NewField(FieldChatSubject, []byte("Test Subject")),
78 },
79 },
80 },
81 want: []Transaction{
82 {
83 clientID: &[]byte{0, 1},
84 Flags: 0x00,
85 IsReply: 0x00,
86 Type: []byte{0, 0x77},
87 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
88 ErrorCode: []byte{0, 0, 0, 0},
89 Fields: []Field{
90 NewField(FieldChatID, []byte{0, 0, 0, 1}),
91 NewField(FieldChatSubject, []byte("Test Subject")),
92 },
93 },
94 {
95 clientID: &[]byte{0, 2},
96 Flags: 0x00,
97 IsReply: 0x00,
98 Type: []byte{0, 0x77},
99 ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
100 ErrorCode: []byte{0, 0, 0, 0},
101 Fields: []Field{
102 NewField(FieldChatID, []byte{0, 0, 0, 1}),
103 NewField(FieldChatSubject, []byte("Test Subject")),
104 },
105 },
106 },
107 wantErr: false,
108 },
109 }
110 for _, tt := range tests {
111 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
112
113 t.Run(tt.name, func(t *testing.T) {
114 got, err := HandleSetChatSubject(tt.args.cc, tt.args.t)
115 if (err != nil) != tt.wantErr {
116 t.Errorf("HandleSetChatSubject() error = %v, wantErr %v", err, tt.wantErr)
117 return
118 }
119 if !assert.Equal(t, tt.want, got) {
120 t.Errorf("HandleSetChatSubject() got = %v, want %v", got, tt.want)
121 }
122 })
123 }
124 }
125
126 func TestHandleLeaveChat(t *testing.T) {
127 type args struct {
128 cc *ClientConn
129 t *Transaction
130 }
131 tests := []struct {
132 name string
133 args args
134 want []Transaction
135 wantErr bool
136 }{
137 {
138 name: "returns expected transactions",
139 args: args{
140 cc: &ClientConn{
141 ID: &[]byte{0, 2},
142 Server: &Server{
143 PrivateChats: map[uint32]*PrivateChat{
144 uint32(1): {
145 ClientConn: map[uint16]*ClientConn{
146 uint16(1): {
147 Account: &Account{
148 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
149 },
150 ID: &[]byte{0, 1},
151 },
152 uint16(2): {
153 Account: &Account{
154 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
155 },
156 ID: &[]byte{0, 2},
157 },
158 },
159 },
160 },
161 Clients: map[uint16]*ClientConn{
162 uint16(1): {
163 Account: &Account{
164 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
165 },
166 ID: &[]byte{0, 1},
167 },
168 uint16(2): {
169 Account: &Account{
170 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
171 },
172 ID: &[]byte{0, 2},
173 },
174 },
175 },
176 },
177 t: NewTransaction(TranDeleteUser, nil, NewField(FieldChatID, []byte{0, 0, 0, 1})),
178 },
179 want: []Transaction{
180 {
181 clientID: &[]byte{0, 1},
182 Flags: 0x00,
183 IsReply: 0x00,
184 Type: []byte{0, 0x76},
185 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
186 ErrorCode: []byte{0, 0, 0, 0},
187 Fields: []Field{
188 NewField(FieldChatID, []byte{0, 0, 0, 1}),
189 NewField(FieldUserID, []byte{0, 2}),
190 },
191 },
192 },
193 wantErr: false,
194 },
195 }
196 for _, tt := range tests {
197 rand.Seed(1)
198 t.Run(tt.name, func(t *testing.T) {
199 got, err := HandleLeaveChat(tt.args.cc, tt.args.t)
200 if (err != nil) != tt.wantErr {
201 t.Errorf("HandleLeaveChat() error = %v, wantErr %v", err, tt.wantErr)
202 return
203 }
204 if !assert.Equal(t, tt.want, got) {
205 t.Errorf("HandleLeaveChat() got = %v, want %v", got, tt.want)
206 }
207 })
208 }
209 }
210
211 func TestHandleGetUserNameList(t *testing.T) {
212 type args struct {
213 cc *ClientConn
214 t *Transaction
215 }
216 tests := []struct {
217 name string
218 args args
219 want []Transaction
220 wantErr bool
221 }{
222 {
223 name: "replies with userlist transaction",
224 args: args{
225 cc: &ClientConn{
226
227 ID: &[]byte{1, 1},
228 Server: &Server{
229 Clients: map[uint16]*ClientConn{
230 uint16(1): {
231 ID: &[]byte{0, 1},
232 Icon: []byte{0, 2},
233 Flags: []byte{0, 3},
234 UserName: []byte{0, 4},
235 },
236 uint16(2): {
237 ID: &[]byte{0, 2},
238 Icon: []byte{0, 2},
239 Flags: []byte{0, 3},
240 UserName: []byte{0, 4},
241 },
242 },
243 },
244 },
245 t: &Transaction{
246 ID: []byte{0, 0, 0, 1},
247 Type: []byte{0, 1},
248 },
249 },
250 want: []Transaction{
251 {
252 clientID: &[]byte{1, 1},
253 Flags: 0x00,
254 IsReply: 0x01,
255 Type: []byte{0, 0},
256 ID: []byte{0, 0, 0, 1},
257 ErrorCode: []byte{0, 0, 0, 0},
258 Fields: []Field{
259 NewField(
260 FieldUsernameWithInfo,
261 []byte{00, 01, 00, 02, 00, 03, 00, 02, 00, 04},
262 ),
263 NewField(
264 FieldUsernameWithInfo,
265 []byte{00, 02, 00, 02, 00, 03, 00, 02, 00, 04},
266 ),
267 },
268 },
269 },
270 wantErr: false,
271 },
272 }
273 for _, tt := range tests {
274 t.Run(tt.name, func(t *testing.T) {
275 got, err := HandleGetUserNameList(tt.args.cc, tt.args.t)
276 if (err != nil) != tt.wantErr {
277 t.Errorf("HandleGetUserNameList() error = %v, wantErr %v", err, tt.wantErr)
278 return
279 }
280 assert.Equal(t, tt.want, got)
281 })
282 }
283 }
284
285 func TestHandleChatSend(t *testing.T) {
286 type args struct {
287 cc *ClientConn
288 t *Transaction
289 }
290 tests := []struct {
291 name string
292 args args
293 want []Transaction
294 wantErr bool
295 }{
296 {
297 name: "sends chat msg transaction to all clients",
298 args: args{
299 cc: &ClientConn{
300 Account: &Account{
301 Access: func() accessBitmap {
302 var bits accessBitmap
303 bits.Set(accessSendChat)
304 return bits
305 }(),
306 },
307 UserName: []byte{0x00, 0x01},
308 Server: &Server{
309 Clients: map[uint16]*ClientConn{
310 uint16(1): {
311 Account: &Account{
312 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
313 },
314 ID: &[]byte{0, 1},
315 },
316 uint16(2): {
317 Account: &Account{
318 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
319 },
320 ID: &[]byte{0, 2},
321 },
322 },
323 },
324 },
325 t: &Transaction{
326 Fields: []Field{
327 NewField(FieldData, []byte("hai")),
328 },
329 },
330 },
331 want: []Transaction{
332 {
333 clientID: &[]byte{0, 1},
334 Flags: 0x00,
335 IsReply: 0x00,
336 Type: []byte{0, 0x6a},
337 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
338 ErrorCode: []byte{0, 0, 0, 0},
339 Fields: []Field{
340 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
341 },
342 },
343 {
344 clientID: &[]byte{0, 2},
345 Flags: 0x00,
346 IsReply: 0x00,
347 Type: []byte{0, 0x6a},
348 ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
349 ErrorCode: []byte{0, 0, 0, 0},
350 Fields: []Field{
351 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
352 },
353 },
354 },
355 wantErr: false,
356 },
357 {
358 name: "treats Chat ID 00 00 00 00 as a public chat message",
359 args: args{
360 cc: &ClientConn{
361 Account: &Account{
362 Access: func() accessBitmap {
363 var bits accessBitmap
364 bits.Set(accessSendChat)
365 return bits
366 }(),
367 },
368 UserName: []byte{0x00, 0x01},
369 Server: &Server{
370 Clients: map[uint16]*ClientConn{
371 uint16(1): {
372 Account: &Account{
373 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
374 },
375 ID: &[]byte{0, 1},
376 },
377 uint16(2): {
378 Account: &Account{
379 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
380 },
381 ID: &[]byte{0, 2},
382 },
383 },
384 },
385 },
386 t: &Transaction{
387 Fields: []Field{
388 NewField(FieldData, []byte("hai")),
389 NewField(FieldChatID, []byte{0, 0, 0, 0}),
390 },
391 },
392 },
393 want: []Transaction{
394 {
395 clientID: &[]byte{0, 1},
396 Flags: 0x00,
397 IsReply: 0x00,
398 Type: []byte{0, 0x6a},
399 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
400 ErrorCode: []byte{0, 0, 0, 0},
401 Fields: []Field{
402 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
403 },
404 },
405 {
406 clientID: &[]byte{0, 2},
407 Flags: 0x00,
408 IsReply: 0x00,
409 Type: []byte{0, 0x6a},
410 ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
411 ErrorCode: []byte{0, 0, 0, 0},
412 Fields: []Field{
413 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
414 },
415 },
416 },
417 wantErr: false,
418 },
419 {
420 name: "when user does not have required permission",
421 args: args{
422 cc: &ClientConn{
423 Account: &Account{
424 Access: func() accessBitmap {
425 var bits accessBitmap
426 return bits
427 }(),
428 },
429 Server: &Server{
430 Accounts: map[string]*Account{},
431 },
432 },
433 t: NewTransaction(
434 TranChatSend, &[]byte{0, 1},
435 NewField(FieldData, []byte("hai")),
436 ),
437 },
438 want: []Transaction{
439 {
440 Flags: 0x00,
441 IsReply: 0x01,
442 Type: []byte{0, 0},
443 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
444 ErrorCode: []byte{0, 0, 0, 1},
445 Fields: []Field{
446 NewField(FieldError, []byte("You are not allowed to participate in chat.")),
447 },
448 },
449 },
450 wantErr: false,
451 },
452 {
453 name: "sends chat msg as emote if FieldChatOptions is set to 1",
454 args: args{
455 cc: &ClientConn{
456 Account: &Account{
457 Access: func() accessBitmap {
458 var bits accessBitmap
459 bits.Set(accessSendChat)
460 return bits
461 }(),
462 },
463 UserName: []byte("Testy McTest"),
464 Server: &Server{
465 Clients: map[uint16]*ClientConn{
466 uint16(1): {
467 Account: &Account{
468 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
469 },
470 ID: &[]byte{0, 1},
471 },
472 uint16(2): {
473 Account: &Account{
474 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
475 },
476 ID: &[]byte{0, 2},
477 },
478 },
479 },
480 },
481 t: &Transaction{
482 Fields: []Field{
483 NewField(FieldData, []byte("performed action")),
484 NewField(FieldChatOptions, []byte{0x00, 0x01}),
485 },
486 },
487 },
488 want: []Transaction{
489 {
490 clientID: &[]byte{0, 1},
491 Flags: 0x00,
492 IsReply: 0x00,
493 Type: []byte{0, 0x6a},
494 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
495 ErrorCode: []byte{0, 0, 0, 0},
496 Fields: []Field{
497 NewField(FieldData, []byte("\r*** Testy McTest performed action")),
498 },
499 },
500 {
501 clientID: &[]byte{0, 2},
502 Flags: 0x00,
503 IsReply: 0x00,
504 Type: []byte{0, 0x6a},
505 ID: []byte{0xf0, 0xc5, 0x34, 0x1e},
506 ErrorCode: []byte{0, 0, 0, 0},
507 Fields: []Field{
508 NewField(FieldData, []byte("\r*** Testy McTest performed action")),
509 },
510 },
511 },
512 wantErr: false,
513 },
514 {
515 name: "does not send chat msg as emote if FieldChatOptions is set to 0",
516 args: args{
517 cc: &ClientConn{
518 Account: &Account{
519 Access: func() accessBitmap {
520 var bits accessBitmap
521 bits.Set(accessSendChat)
522 return bits
523 }(),
524 },
525 UserName: []byte("Testy McTest"),
526 Server: &Server{
527 Clients: map[uint16]*ClientConn{
528 uint16(1): {
529 Account: &Account{
530 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
531 },
532 ID: &[]byte{0, 1},
533 },
534 uint16(2): {
535 Account: &Account{
536 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
537 },
538 ID: &[]byte{0, 2},
539 },
540 },
541 },
542 },
543 t: &Transaction{
544 Fields: []Field{
545 NewField(FieldData, []byte("hello")),
546 NewField(FieldChatOptions, []byte{0x00, 0x00}),
547 },
548 },
549 },
550 want: []Transaction{
551 {
552 clientID: &[]byte{0, 1},
553 Flags: 0x00,
554 IsReply: 0x00,
555 Type: []byte{0, 0x6a},
556 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
557 ErrorCode: []byte{0, 0, 0, 0},
558 Fields: []Field{
559 NewField(FieldData, []byte("\r Testy McTest: hello")),
560 },
561 },
562 {
563 clientID: &[]byte{0, 2},
564 Flags: 0x00,
565 IsReply: 0x00,
566 Type: []byte{0, 0x6a},
567 ID: []byte{0xf0, 0xc5, 0x34, 0x1e},
568 ErrorCode: []byte{0, 0, 0, 0},
569 Fields: []Field{
570 NewField(FieldData, []byte("\r Testy McTest: hello")),
571 },
572 },
573 },
574 wantErr: false,
575 },
576 {
577 name: "only sends chat msg to clients with accessReadChat permission",
578 args: args{
579 cc: &ClientConn{
580 Account: &Account{
581 Access: func() accessBitmap {
582 var bits accessBitmap
583 bits.Set(accessSendChat)
584 return bits
585 }(),
586 },
587 UserName: []byte{0x00, 0x01},
588 Server: &Server{
589 Clients: map[uint16]*ClientConn{
590 uint16(1): {
591 Account: &Account{
592 Access: func() accessBitmap {
593 var bits accessBitmap
594 bits.Set(accessReadChat)
595 return bits
596 }()},
597 ID: &[]byte{0, 1},
598 },
599 uint16(2): {
600 Account: &Account{
601 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
602 },
603 ID: &[]byte{0, 2},
604 },
605 },
606 },
607 },
608 t: &Transaction{
609 Fields: []Field{
610 NewField(FieldData, []byte("hai")),
611 },
612 },
613 },
614 want: []Transaction{
615 {
616 clientID: &[]byte{0, 1},
617 Flags: 0x00,
618 IsReply: 0x00,
619 Type: []byte{0, 0x6a},
620 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
621 ErrorCode: []byte{0, 0, 0, 0},
622 Fields: []Field{
623 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
624 },
625 },
626 },
627 wantErr: false,
628 },
629 {
630 name: "only sends private chat msg to members of private chat",
631 args: args{
632 cc: &ClientConn{
633 Account: &Account{
634 Access: func() accessBitmap {
635 var bits accessBitmap
636 bits.Set(accessSendChat)
637 return bits
638 }(),
639 },
640 UserName: []byte{0x00, 0x01},
641 Server: &Server{
642 PrivateChats: map[uint32]*PrivateChat{
643 uint32(1): {
644 ClientConn: map[uint16]*ClientConn{
645 uint16(1): {
646 ID: &[]byte{0, 1},
647 },
648 uint16(2): {
649 ID: &[]byte{0, 2},
650 },
651 },
652 },
653 },
654 Clients: map[uint16]*ClientConn{
655 uint16(1): {
656 Account: &Account{
657 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
658 },
659 ID: &[]byte{0, 1},
660 },
661 uint16(2): {
662 Account: &Account{
663 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
664 },
665 ID: &[]byte{0, 2},
666 },
667 uint16(3): {
668 Account: &Account{
669 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
670 },
671 ID: &[]byte{0, 3},
672 },
673 },
674 },
675 },
676 t: &Transaction{
677 Fields: []Field{
678 NewField(FieldData, []byte("hai")),
679 NewField(FieldChatID, []byte{0, 0, 0, 1}),
680 },
681 },
682 },
683 want: []Transaction{
684 {
685 clientID: &[]byte{0, 1},
686 Flags: 0x00,
687 IsReply: 0x00,
688 Type: []byte{0, 0x6a},
689 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
690 ErrorCode: []byte{0, 0, 0, 0},
691 Fields: []Field{
692 NewField(FieldChatID, []byte{0, 0, 0, 1}),
693 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
694 },
695 },
696 {
697 clientID: &[]byte{0, 2},
698 Flags: 0x00,
699 IsReply: 0x00,
700 Type: []byte{0, 0x6a},
701 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
702 ErrorCode: []byte{0, 0, 0, 0},
703 Fields: []Field{
704 NewField(FieldChatID, []byte{0, 0, 0, 1}),
705 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
706 },
707 },
708 },
709 wantErr: false,
710 },
711 }
712 for _, tt := range tests {
713 t.Run(tt.name, func(t *testing.T) {
714 got, err := HandleChatSend(tt.args.cc, tt.args.t)
715
716 if (err != nil) != tt.wantErr {
717 t.Errorf("HandleChatSend() error = %v, wantErr %v", err, tt.wantErr)
718 return
719 }
720 tranAssertEqual(t, tt.want, got)
721 })
722 }
723 }
724
725 func TestHandleGetFileInfo(t *testing.T) {
726 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
727
728 type args struct {
729 cc *ClientConn
730 t *Transaction
731 }
732 tests := []struct {
733 name string
734 args args
735 wantRes []Transaction
736 wantErr bool
737 }{
738 {
739 name: "returns expected fields when a valid file is requested",
740 args: args{
741 cc: &ClientConn{
742 ID: &[]byte{0x00, 0x01},
743 Server: &Server{
744 FS: &OSFileStore{},
745 Config: &Config{
746 FileRoot: func() string {
747 path, _ := os.Getwd()
748 return filepath.Join(path, "/test/config/Files")
749 }(),
750 },
751 },
752 },
753 t: NewTransaction(
754 TranGetFileInfo, nil,
755 NewField(FieldFileName, []byte("testfile.txt")),
756 NewField(FieldFilePath, []byte{0x00, 0x00}),
757 ),
758 },
759 wantRes: []Transaction{
760 {
761 clientID: &[]byte{0, 1},
762 Flags: 0x00,
763 IsReply: 0x01,
764 Type: []byte{0, 0},
765 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
766 ErrorCode: []byte{0, 0, 0, 0},
767 Fields: []Field{
768 NewField(FieldFileName, []byte("testfile.txt")),
769 NewField(FieldFileTypeString, []byte("Text File")),
770 NewField(FieldFileCreatorString, []byte("ttxt")),
771 NewField(FieldFileType, []byte("TEXT")),
772 NewField(FieldFileCreateDate, make([]byte, 8)),
773 NewField(FieldFileModifyDate, make([]byte, 8)),
774 NewField(FieldFileSize, []byte{0x0, 0x0, 0x0, 0x17}),
775 },
776 },
777 },
778 wantErr: false,
779 },
780 }
781 for _, tt := range tests {
782 t.Run(tt.name, func(t *testing.T) {
783 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
784
785 gotRes, err := HandleGetFileInfo(tt.args.cc, tt.args.t)
786 if (err != nil) != tt.wantErr {
787 t.Errorf("HandleGetFileInfo() error = %v, wantErr %v", err, tt.wantErr)
788 return
789 }
790
791 // Clear the fileWrapper timestamp fields to work around problems running the tests in multiple timezones
792 // TODO: revisit how to test this by mocking the stat calls
793 gotRes[0].Fields[4].Data = make([]byte, 8)
794 gotRes[0].Fields[5].Data = make([]byte, 8)
795 if !assert.Equal(t, tt.wantRes, gotRes) {
796 t.Errorf("HandleGetFileInfo() gotRes = %v, want %v", gotRes, tt.wantRes)
797 }
798 })
799 }
800 }
801
802 func TestHandleNewFolder(t *testing.T) {
803 type args struct {
804 cc *ClientConn
805 t *Transaction
806 }
807 tests := []struct {
808 name string
809 args args
810 wantRes []Transaction
811 wantErr bool
812 }{
813 {
814 name: "without required permission",
815 args: args{
816 cc: &ClientConn{
817 Account: &Account{
818 Access: func() accessBitmap {
819 var bits accessBitmap
820 return bits
821 }(),
822 },
823 },
824 t: NewTransaction(
825 accessCreateFolder,
826 &[]byte{0, 0},
827 ),
828 },
829 wantRes: []Transaction{
830 {
831 Flags: 0x00,
832 IsReply: 0x01,
833 Type: []byte{0, 0},
834 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
835 ErrorCode: []byte{0, 0, 0, 1},
836 Fields: []Field{
837 NewField(FieldError, []byte("You are not allowed to create folders.")),
838 },
839 },
840 },
841 wantErr: false,
842 },
843 {
844 name: "when path is nested",
845 args: args{
846 cc: &ClientConn{
847 Account: &Account{
848 Access: func() accessBitmap {
849 var bits accessBitmap
850 bits.Set(accessCreateFolder)
851 return bits
852 }(),
853 },
854 ID: &[]byte{0, 1},
855 Server: &Server{
856 Config: &Config{
857 FileRoot: "/Files/",
858 },
859 FS: func() *MockFileStore {
860 mfs := &MockFileStore{}
861 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
862 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
863 return mfs
864 }(),
865 },
866 },
867 t: NewTransaction(
868 TranNewFolder, &[]byte{0, 1},
869 NewField(FieldFileName, []byte("testFolder")),
870 NewField(FieldFilePath, []byte{
871 0x00, 0x01,
872 0x00, 0x00,
873 0x03,
874 0x61, 0x61, 0x61,
875 }),
876 ),
877 },
878 wantRes: []Transaction{
879 {
880 clientID: &[]byte{0, 1},
881 Flags: 0x00,
882 IsReply: 0x01,
883 Type: []byte{0, 0},
884 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
885 ErrorCode: []byte{0, 0, 0, 0},
886 },
887 },
888 wantErr: false,
889 },
890 {
891 name: "when path is not nested",
892 args: args{
893 cc: &ClientConn{
894 Account: &Account{
895 Access: func() accessBitmap {
896 var bits accessBitmap
897 bits.Set(accessCreateFolder)
898 return bits
899 }(),
900 },
901 ID: &[]byte{0, 1},
902 Server: &Server{
903 Config: &Config{
904 FileRoot: "/Files",
905 },
906 FS: func() *MockFileStore {
907 mfs := &MockFileStore{}
908 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
909 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
910 return mfs
911 }(),
912 },
913 },
914 t: NewTransaction(
915 TranNewFolder, &[]byte{0, 1},
916 NewField(FieldFileName, []byte("testFolder")),
917 ),
918 },
919 wantRes: []Transaction{
920 {
921 clientID: &[]byte{0, 1},
922 Flags: 0x00,
923 IsReply: 0x01,
924 Type: []byte{0, 0},
925 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
926 ErrorCode: []byte{0, 0, 0, 0},
927 },
928 },
929 wantErr: false,
930 },
931 {
932 name: "when Write returns an err",
933 args: args{
934 cc: &ClientConn{
935 Account: &Account{
936 Access: func() accessBitmap {
937 var bits accessBitmap
938 bits.Set(accessCreateFolder)
939 return bits
940 }(),
941 },
942 ID: &[]byte{0, 1},
943 Server: &Server{
944 Config: &Config{
945 FileRoot: "/Files/",
946 },
947 FS: func() *MockFileStore {
948 mfs := &MockFileStore{}
949 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
950 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
951 return mfs
952 }(),
953 },
954 },
955 t: NewTransaction(
956 TranNewFolder, &[]byte{0, 1},
957 NewField(FieldFileName, []byte("testFolder")),
958 NewField(FieldFilePath, []byte{
959 0x00,
960 }),
961 ),
962 },
963 wantRes: []Transaction{},
964 wantErr: true,
965 },
966 {
967 name: "FieldFileName does not allow directory traversal",
968 args: args{
969 cc: &ClientConn{
970 Account: &Account{
971 Access: func() accessBitmap {
972 var bits accessBitmap
973 bits.Set(accessCreateFolder)
974 return bits
975 }(),
976 },
977 ID: &[]byte{0, 1},
978 Server: &Server{
979 Config: &Config{
980 FileRoot: "/Files/",
981 },
982 FS: func() *MockFileStore {
983 mfs := &MockFileStore{}
984 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
985 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
986 return mfs
987 }(),
988 },
989 },
990 t: NewTransaction(
991 TranNewFolder, &[]byte{0, 1},
992 NewField(FieldFileName, []byte("../../testFolder")),
993 ),
994 },
995 wantRes: []Transaction{
996 {
997 clientID: &[]byte{0, 1},
998 Flags: 0x00,
999 IsReply: 0x01,
1000 Type: []byte{0, 0},
1001 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
1002 ErrorCode: []byte{0, 0, 0, 0},
1003 },
1004 }, wantErr: false,
1005 },
1006 {
1007 name: "FieldFilePath does not allow directory traversal",
1008 args: args{
1009 cc: &ClientConn{
1010 Account: &Account{
1011 Access: func() accessBitmap {
1012 var bits accessBitmap
1013 bits.Set(accessCreateFolder)
1014 return bits
1015 }(),
1016 },
1017 ID: &[]byte{0, 1},
1018 Server: &Server{
1019 Config: &Config{
1020 FileRoot: "/Files/",
1021 },
1022 FS: func() *MockFileStore {
1023 mfs := &MockFileStore{}
1024 mfs.On("Mkdir", "/Files/foo/testFolder", fs.FileMode(0777)).Return(nil)
1025 mfs.On("Stat", "/Files/foo/testFolder").Return(nil, os.ErrNotExist)
1026 return mfs
1027 }(),
1028 },
1029 },
1030 t: NewTransaction(
1031 TranNewFolder, &[]byte{0, 1},
1032 NewField(FieldFileName, []byte("testFolder")),
1033 NewField(FieldFilePath, []byte{
1034 0x00, 0x02,
1035 0x00, 0x00,
1036 0x03,
1037 0x2e, 0x2e, 0x2f,
1038 0x00, 0x00,
1039 0x03,
1040 0x66, 0x6f, 0x6f,
1041 }),
1042 ),
1043 },
1044 wantRes: []Transaction{
1045 {
1046 clientID: &[]byte{0, 1},
1047 Flags: 0x00,
1048 IsReply: 0x01,
1049 Type: []byte{0, 0},
1050 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
1051 ErrorCode: []byte{0, 0, 0, 0},
1052 },
1053 }, wantErr: false,
1054 },
1055 }
1056 for _, tt := range tests {
1057 t.Run(tt.name, func(t *testing.T) {
1058 gotRes, err := HandleNewFolder(tt.args.cc, tt.args.t)
1059 if (err != nil) != tt.wantErr {
1060 t.Errorf("HandleNewFolder() error = %v, wantErr %v", err, tt.wantErr)
1061 return
1062 }
1063
1064 if !tranAssertEqual(t, tt.wantRes, gotRes) {
1065 t.Errorf("HandleNewFolder() gotRes = %v, want %v", gotRes, tt.wantRes)
1066 }
1067 })
1068 }
1069 }
1070
1071 func TestHandleUploadFile(t *testing.T) {
1072 type args struct {
1073 cc *ClientConn
1074 t *Transaction
1075 }
1076 tests := []struct {
1077 name string
1078 args args
1079 wantRes []Transaction
1080 wantErr bool
1081 }{
1082 {
1083 name: "when request is valid and user has Upload Anywhere permission",
1084 args: args{
1085 cc: &ClientConn{
1086 Server: &Server{
1087 FS: &OSFileStore{},
1088 fileTransfers: map[[4]byte]*FileTransfer{},
1089 Config: &Config{
1090 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1091 }},
1092 transfers: map[int]map[[4]byte]*FileTransfer{
1093 FileUpload: {},
1094 },
1095 Account: &Account{
1096 Access: func() accessBitmap {
1097 var bits accessBitmap
1098 bits.Set(accessUploadFile)
1099 bits.Set(accessUploadAnywhere)
1100 return bits
1101 }(),
1102 },
1103 },
1104 t: NewTransaction(
1105 TranUploadFile, &[]byte{0, 1},
1106 NewField(FieldFileName, []byte("testFile")),
1107 NewField(FieldFilePath, []byte{
1108 0x00, 0x01,
1109 0x00, 0x00,
1110 0x03,
1111 0x2e, 0x2e, 0x2f,
1112 }),
1113 ),
1114 },
1115 wantRes: []Transaction{
1116 {
1117 Flags: 0x00,
1118 IsReply: 0x01,
1119 Type: []byte{0, 0},
1120 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1121 ErrorCode: []byte{0, 0, 0, 0},
1122 Fields: []Field{
1123 NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}), // rand.Seed(1)
1124 },
1125 },
1126 },
1127 wantErr: false,
1128 },
1129 {
1130 name: "when user does not have required access",
1131 args: args{
1132 cc: &ClientConn{
1133 Account: &Account{
1134 Access: func() accessBitmap {
1135 var bits accessBitmap
1136 return bits
1137 }(),
1138 },
1139 },
1140 t: NewTransaction(
1141 TranUploadFile, &[]byte{0, 1},
1142 NewField(FieldFileName, []byte("testFile")),
1143 NewField(FieldFilePath, []byte{
1144 0x00, 0x01,
1145 0x00, 0x00,
1146 0x03,
1147 0x2e, 0x2e, 0x2f,
1148 }),
1149 ),
1150 },
1151 wantRes: []Transaction{
1152 {
1153 Flags: 0x00,
1154 IsReply: 0x01,
1155 Type: []byte{0, 0},
1156 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1157 ErrorCode: []byte{0, 0, 0, 1},
1158 Fields: []Field{
1159 NewField(FieldError, []byte("You are not allowed to upload files.")), // rand.Seed(1)
1160 },
1161 },
1162 },
1163 wantErr: false,
1164 },
1165 }
1166 for _, tt := range tests {
1167 t.Run(tt.name, func(t *testing.T) {
1168 rand.Seed(1)
1169 gotRes, err := HandleUploadFile(tt.args.cc, tt.args.t)
1170 if (err != nil) != tt.wantErr {
1171 t.Errorf("HandleUploadFile() error = %v, wantErr %v", err, tt.wantErr)
1172 return
1173 }
1174
1175 tranAssertEqual(t, tt.wantRes, gotRes)
1176 })
1177 }
1178 }
1179
1180 func TestHandleMakeAlias(t *testing.T) {
1181 type args struct {
1182 cc *ClientConn
1183 t *Transaction
1184 }
1185 tests := []struct {
1186 name string
1187 args args
1188 wantRes []Transaction
1189 wantErr bool
1190 }{
1191 {
1192 name: "with valid input and required permissions",
1193 args: args{
1194 cc: &ClientConn{
1195 logger: NewTestLogger(),
1196 Account: &Account{
1197 Access: func() accessBitmap {
1198 var bits accessBitmap
1199 bits.Set(accessMakeAlias)
1200 return bits
1201 }(),
1202 },
1203 Server: &Server{
1204 Config: &Config{
1205 FileRoot: func() string {
1206 path, _ := os.Getwd()
1207 return path + "/test/config/Files"
1208 }(),
1209 },
1210 Logger: NewTestLogger(),
1211 FS: func() *MockFileStore {
1212 mfs := &MockFileStore{}
1213 path, _ := os.Getwd()
1214 mfs.On(
1215 "Symlink",
1216 path+"/test/config/Files/foo/testFile",
1217 path+"/test/config/Files/bar/testFile",
1218 ).Return(nil)
1219 return mfs
1220 }(),
1221 },
1222 },
1223 t: NewTransaction(
1224 TranMakeFileAlias, &[]byte{0, 1},
1225 NewField(FieldFileName, []byte("testFile")),
1226 NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1227 NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1228 ),
1229 },
1230 wantRes: []Transaction{
1231 {
1232 Flags: 0x00,
1233 IsReply: 0x01,
1234 Type: []byte{0, 0},
1235 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1236 ErrorCode: []byte{0, 0, 0, 0},
1237 Fields: []Field(nil),
1238 },
1239 },
1240 wantErr: false,
1241 },
1242 {
1243 name: "when symlink returns an error",
1244 args: args{
1245 cc: &ClientConn{
1246 logger: NewTestLogger(),
1247 Account: &Account{
1248 Access: func() accessBitmap {
1249 var bits accessBitmap
1250 bits.Set(accessMakeAlias)
1251 return bits
1252 }(),
1253 },
1254 Server: &Server{
1255 Config: &Config{
1256 FileRoot: func() string {
1257 path, _ := os.Getwd()
1258 return path + "/test/config/Files"
1259 }(),
1260 },
1261 Logger: NewTestLogger(),
1262 FS: func() *MockFileStore {
1263 mfs := &MockFileStore{}
1264 path, _ := os.Getwd()
1265 mfs.On(
1266 "Symlink",
1267 path+"/test/config/Files/foo/testFile",
1268 path+"/test/config/Files/bar/testFile",
1269 ).Return(errors.New("ohno"))
1270 return mfs
1271 }(),
1272 },
1273 },
1274 t: NewTransaction(
1275 TranMakeFileAlias, &[]byte{0, 1},
1276 NewField(FieldFileName, []byte("testFile")),
1277 NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1278 NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1279 ),
1280 },
1281 wantRes: []Transaction{
1282 {
1283 Flags: 0x00,
1284 IsReply: 0x01,
1285 Type: []byte{0, 0},
1286 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1287 ErrorCode: []byte{0, 0, 0, 1},
1288 Fields: []Field{
1289 NewField(FieldError, []byte("Error creating alias")),
1290 },
1291 },
1292 },
1293 wantErr: false,
1294 },
1295 {
1296 name: "when user does not have required permission",
1297 args: args{
1298 cc: &ClientConn{
1299 logger: NewTestLogger(),
1300 Account: &Account{
1301 Access: func() accessBitmap {
1302 var bits accessBitmap
1303 return bits
1304 }(),
1305 },
1306 Server: &Server{
1307 Config: &Config{
1308 FileRoot: func() string {
1309 path, _ := os.Getwd()
1310 return path + "/test/config/Files"
1311 }(),
1312 },
1313 },
1314 },
1315 t: NewTransaction(
1316 TranMakeFileAlias, &[]byte{0, 1},
1317 NewField(FieldFileName, []byte("testFile")),
1318 NewField(FieldFilePath, []byte{
1319 0x00, 0x01,
1320 0x00, 0x00,
1321 0x03,
1322 0x2e, 0x2e, 0x2e,
1323 }),
1324 NewField(FieldFileNewPath, []byte{
1325 0x00, 0x01,
1326 0x00, 0x00,
1327 0x03,
1328 0x2e, 0x2e, 0x2e,
1329 }),
1330 ),
1331 },
1332 wantRes: []Transaction{
1333 {
1334 Flags: 0x00,
1335 IsReply: 0x01,
1336 Type: []byte{0, 0},
1337 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1338 ErrorCode: []byte{0, 0, 0, 1},
1339 Fields: []Field{
1340 NewField(FieldError, []byte("You are not allowed to make aliases.")),
1341 },
1342 },
1343 },
1344 wantErr: false,
1345 },
1346 }
1347 for _, tt := range tests {
1348 t.Run(tt.name, func(t *testing.T) {
1349 gotRes, err := HandleMakeAlias(tt.args.cc, tt.args.t)
1350 if (err != nil) != tt.wantErr {
1351 t.Errorf("HandleMakeAlias(%v, %v)", tt.args.cc, tt.args.t)
1352 return
1353 }
1354
1355 tranAssertEqual(t, tt.wantRes, gotRes)
1356 })
1357 }
1358 }
1359
1360 func TestHandleGetUser(t *testing.T) {
1361 type args struct {
1362 cc *ClientConn
1363 t *Transaction
1364 }
1365 tests := []struct {
1366 name string
1367 args args
1368 wantRes []Transaction
1369 wantErr assert.ErrorAssertionFunc
1370 }{
1371 {
1372 name: "when account is valid",
1373 args: args{
1374 cc: &ClientConn{
1375 Account: &Account{
1376 Access: func() accessBitmap {
1377 var bits accessBitmap
1378 bits.Set(accessOpenUser)
1379 return bits
1380 }(),
1381 },
1382 Server: &Server{
1383 Accounts: map[string]*Account{
1384 "guest": {
1385 Login: "guest",
1386 Name: "Guest",
1387 Password: "password",
1388 Access: accessBitmap{},
1389 },
1390 },
1391 },
1392 },
1393 t: NewTransaction(
1394 TranGetUser, &[]byte{0, 1},
1395 NewField(FieldUserLogin, []byte("guest")),
1396 ),
1397 },
1398 wantRes: []Transaction{
1399 {
1400 Flags: 0x00,
1401 IsReply: 0x01,
1402 Type: []byte{0, 0},
1403 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1404 ErrorCode: []byte{0, 0, 0, 0},
1405 Fields: []Field{
1406 NewField(FieldUserName, []byte("Guest")),
1407 NewField(FieldUserLogin, encodeString([]byte("guest"))),
1408 NewField(FieldUserPassword, []byte("password")),
1409 NewField(FieldUserAccess, []byte{0, 0, 0, 0, 0, 0, 0, 0}),
1410 },
1411 },
1412 },
1413 wantErr: assert.NoError,
1414 },
1415 {
1416 name: "when user does not have required permission",
1417 args: args{
1418 cc: &ClientConn{
1419 Account: &Account{
1420 Access: func() accessBitmap {
1421 var bits accessBitmap
1422 return bits
1423 }(),
1424 },
1425 Server: &Server{
1426 Accounts: map[string]*Account{},
1427 },
1428 },
1429 t: NewTransaction(
1430 TranGetUser, &[]byte{0, 1},
1431 NewField(FieldUserLogin, []byte("nonExistentUser")),
1432 ),
1433 },
1434 wantRes: []Transaction{
1435 {
1436 Flags: 0x00,
1437 IsReply: 0x01,
1438 Type: []byte{0, 0},
1439 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1440 ErrorCode: []byte{0, 0, 0, 1},
1441 Fields: []Field{
1442 NewField(FieldError, []byte("You are not allowed to view accounts.")),
1443 },
1444 },
1445 },
1446 wantErr: assert.NoError,
1447 },
1448 {
1449 name: "when account does not exist",
1450 args: args{
1451 cc: &ClientConn{
1452 Account: &Account{
1453 Access: func() accessBitmap {
1454 var bits accessBitmap
1455 bits.Set(accessOpenUser)
1456 return bits
1457 }(),
1458 },
1459 Server: &Server{
1460 Accounts: map[string]*Account{},
1461 },
1462 },
1463 t: NewTransaction(
1464 TranGetUser, &[]byte{0, 1},
1465 NewField(FieldUserLogin, []byte("nonExistentUser")),
1466 ),
1467 },
1468 wantRes: []Transaction{
1469 {
1470 Flags: 0x00,
1471 IsReply: 0x01,
1472 Type: []byte{0, 0},
1473 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1474 ErrorCode: []byte{0, 0, 0, 1},
1475 Fields: []Field{
1476 NewField(FieldError, []byte("Account does not exist.")),
1477 },
1478 },
1479 },
1480 wantErr: assert.NoError,
1481 },
1482 }
1483 for _, tt := range tests {
1484 t.Run(tt.name, func(t *testing.T) {
1485 gotRes, err := HandleGetUser(tt.args.cc, tt.args.t)
1486 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetUser(%v, %v)", tt.args.cc, tt.args.t)) {
1487 return
1488 }
1489
1490 tranAssertEqual(t, tt.wantRes, gotRes)
1491 })
1492 }
1493 }
1494
1495 func TestHandleDeleteUser(t *testing.T) {
1496 type args struct {
1497 cc *ClientConn
1498 t *Transaction
1499 }
1500 tests := []struct {
1501 name string
1502 args args
1503 wantRes []Transaction
1504 wantErr assert.ErrorAssertionFunc
1505 }{
1506 {
1507 name: "when user dataFile",
1508 args: args{
1509 cc: &ClientConn{
1510 Account: &Account{
1511 Access: func() accessBitmap {
1512 var bits accessBitmap
1513 bits.Set(accessDeleteUser)
1514 return bits
1515 }(),
1516 },
1517 Server: &Server{
1518 Accounts: map[string]*Account{
1519 "testuser": {
1520 Login: "testuser",
1521 Name: "Testy McTest",
1522 Password: "password",
1523 Access: accessBitmap{},
1524 },
1525 },
1526 FS: func() *MockFileStore {
1527 mfs := &MockFileStore{}
1528 mfs.On("Remove", "Users/testuser.yaml").Return(nil)
1529 return mfs
1530 }(),
1531 },
1532 },
1533 t: NewTransaction(
1534 TranDeleteUser, &[]byte{0, 1},
1535 NewField(FieldUserLogin, encodeString([]byte("testuser"))),
1536 ),
1537 },
1538 wantRes: []Transaction{
1539 {
1540 Flags: 0x00,
1541 IsReply: 0x01,
1542 Type: []byte{0, 0},
1543 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1544 ErrorCode: []byte{0, 0, 0, 0},
1545 Fields: []Field(nil),
1546 },
1547 },
1548 wantErr: assert.NoError,
1549 },
1550 {
1551 name: "when user does not have required permission",
1552 args: args{
1553 cc: &ClientConn{
1554 Account: &Account{
1555 Access: func() accessBitmap {
1556 var bits accessBitmap
1557 return bits
1558 }(),
1559 },
1560 Server: &Server{
1561 Accounts: map[string]*Account{},
1562 },
1563 },
1564 t: NewTransaction(
1565 TranDeleteUser, &[]byte{0, 1},
1566 NewField(FieldUserLogin, encodeString([]byte("testuser"))),
1567 ),
1568 },
1569 wantRes: []Transaction{
1570 {
1571 Flags: 0x00,
1572 IsReply: 0x01,
1573 Type: []byte{0, 0},
1574 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1575 ErrorCode: []byte{0, 0, 0, 1},
1576 Fields: []Field{
1577 NewField(FieldError, []byte("You are not allowed to delete accounts.")),
1578 },
1579 },
1580 },
1581 wantErr: assert.NoError,
1582 },
1583 }
1584 for _, tt := range tests {
1585 t.Run(tt.name, func(t *testing.T) {
1586 gotRes, err := HandleDeleteUser(tt.args.cc, tt.args.t)
1587 if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteUser(%v, %v)", tt.args.cc, tt.args.t)) {
1588 return
1589 }
1590
1591 tranAssertEqual(t, tt.wantRes, gotRes)
1592 })
1593 }
1594 }
1595
1596 func TestHandleGetMsgs(t *testing.T) {
1597 type args struct {
1598 cc *ClientConn
1599 t *Transaction
1600 }
1601 tests := []struct {
1602 name string
1603 args args
1604 wantRes []Transaction
1605 wantErr assert.ErrorAssertionFunc
1606 }{
1607 {
1608 name: "returns news data",
1609 args: args{
1610 cc: &ClientConn{
1611 Account: &Account{
1612 Access: func() accessBitmap {
1613 var bits accessBitmap
1614 bits.Set(accessNewsReadArt)
1615 return bits
1616 }(),
1617 },
1618 Server: &Server{
1619 FlatNews: []byte("TEST"),
1620 },
1621 },
1622 t: NewTransaction(
1623 TranGetMsgs, &[]byte{0, 1},
1624 ),
1625 },
1626 wantRes: []Transaction{
1627 {
1628 Flags: 0x00,
1629 IsReply: 0x01,
1630 Type: []byte{0, 0},
1631 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1632 ErrorCode: []byte{0, 0, 0, 0},
1633 Fields: []Field{
1634 NewField(FieldData, []byte("TEST")),
1635 },
1636 },
1637 },
1638 wantErr: assert.NoError,
1639 },
1640 {
1641 name: "when user does not have required permission",
1642 args: args{
1643 cc: &ClientConn{
1644 Account: &Account{
1645 Access: func() accessBitmap {
1646 var bits accessBitmap
1647 return bits
1648 }(),
1649 },
1650 Server: &Server{
1651 Accounts: map[string]*Account{},
1652 },
1653 },
1654 t: NewTransaction(
1655 TranGetMsgs, &[]byte{0, 1},
1656 ),
1657 },
1658 wantRes: []Transaction{
1659 {
1660 Flags: 0x00,
1661 IsReply: 0x01,
1662 Type: []byte{0, 0},
1663 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1664 ErrorCode: []byte{0, 0, 0, 1},
1665 Fields: []Field{
1666 NewField(FieldError, []byte("You are not allowed to read news.")),
1667 },
1668 },
1669 },
1670 wantErr: assert.NoError,
1671 },
1672 }
1673 for _, tt := range tests {
1674 t.Run(tt.name, func(t *testing.T) {
1675 gotRes, err := HandleGetMsgs(tt.args.cc, tt.args.t)
1676 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetMsgs(%v, %v)", tt.args.cc, tt.args.t)) {
1677 return
1678 }
1679
1680 tranAssertEqual(t, tt.wantRes, gotRes)
1681 })
1682 }
1683 }
1684
1685 func TestHandleNewUser(t *testing.T) {
1686 type args struct {
1687 cc *ClientConn
1688 t *Transaction
1689 }
1690 tests := []struct {
1691 name string
1692 args args
1693 wantRes []Transaction
1694 wantErr assert.ErrorAssertionFunc
1695 }{
1696 {
1697 name: "when user does not have required permission",
1698 args: args{
1699 cc: &ClientConn{
1700 Account: &Account{
1701 Access: func() accessBitmap {
1702 var bits accessBitmap
1703 return bits
1704 }(),
1705 },
1706 Server: &Server{
1707 Accounts: map[string]*Account{},
1708 },
1709 },
1710 t: NewTransaction(
1711 TranNewUser, &[]byte{0, 1},
1712 ),
1713 },
1714 wantRes: []Transaction{
1715 {
1716 Flags: 0x00,
1717 IsReply: 0x01,
1718 Type: []byte{0, 0},
1719 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1720 ErrorCode: []byte{0, 0, 0, 1},
1721 Fields: []Field{
1722 NewField(FieldError, []byte("You are not allowed to create new accounts.")),
1723 },
1724 },
1725 },
1726 wantErr: assert.NoError,
1727 },
1728 {
1729 name: "when user attempts to create account with greater access",
1730 args: args{
1731 cc: &ClientConn{
1732 Account: &Account{
1733 Access: func() accessBitmap {
1734 var bits accessBitmap
1735 bits.Set(accessCreateUser)
1736 return bits
1737 }(),
1738 },
1739 Server: &Server{
1740 Accounts: map[string]*Account{},
1741 },
1742 },
1743 t: NewTransaction(
1744 TranNewUser, &[]byte{0, 1},
1745 NewField(FieldUserLogin, []byte("userB")),
1746 NewField(
1747 FieldUserAccess,
1748 func() []byte {
1749 var bits accessBitmap
1750 bits.Set(accessDisconUser)
1751 return bits[:]
1752 }(),
1753 ),
1754 ),
1755 },
1756 wantRes: []Transaction{
1757 {
1758 Flags: 0x00,
1759 IsReply: 0x01,
1760 Type: []byte{0, 0},
1761 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1762 ErrorCode: []byte{0, 0, 0, 1},
1763 Fields: []Field{
1764 NewField(FieldError, []byte("Cannot create account with more access than yourself.")),
1765 },
1766 },
1767 },
1768 wantErr: assert.NoError,
1769 },
1770 }
1771 for _, tt := range tests {
1772 t.Run(tt.name, func(t *testing.T) {
1773 gotRes, err := HandleNewUser(tt.args.cc, tt.args.t)
1774 if !tt.wantErr(t, err, fmt.Sprintf("HandleNewUser(%v, %v)", tt.args.cc, tt.args.t)) {
1775 return
1776 }
1777
1778 tranAssertEqual(t, tt.wantRes, gotRes)
1779 })
1780 }
1781 }
1782
1783 func TestHandleListUsers(t *testing.T) {
1784 type args struct {
1785 cc *ClientConn
1786 t *Transaction
1787 }
1788 tests := []struct {
1789 name string
1790 args args
1791 wantRes []Transaction
1792 wantErr assert.ErrorAssertionFunc
1793 }{
1794 {
1795 name: "when user does not have required permission",
1796 args: args{
1797 cc: &ClientConn{
1798 Account: &Account{
1799 Access: func() accessBitmap {
1800 var bits accessBitmap
1801 return bits
1802 }(),
1803 },
1804 Server: &Server{
1805 Accounts: map[string]*Account{},
1806 },
1807 },
1808 t: NewTransaction(
1809 TranNewUser, &[]byte{0, 1},
1810 ),
1811 },
1812 wantRes: []Transaction{
1813 {
1814 Flags: 0x00,
1815 IsReply: 0x01,
1816 Type: []byte{0, 0},
1817 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1818 ErrorCode: []byte{0, 0, 0, 1},
1819 Fields: []Field{
1820 NewField(FieldError, []byte("You are not allowed to view accounts.")),
1821 },
1822 },
1823 },
1824 wantErr: assert.NoError,
1825 },
1826 {
1827 name: "when user has required permission",
1828 args: args{
1829 cc: &ClientConn{
1830 Account: &Account{
1831 Access: func() accessBitmap {
1832 var bits accessBitmap
1833 bits.Set(accessOpenUser)
1834 return bits
1835 }(),
1836 },
1837 Server: &Server{
1838 Accounts: map[string]*Account{
1839 "guest": {
1840 Name: "guest",
1841 Login: "guest",
1842 Password: "zz",
1843 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
1844 },
1845 },
1846 },
1847 },
1848 t: NewTransaction(
1849 TranGetClientInfoText, &[]byte{0, 1},
1850 NewField(FieldUserID, []byte{0, 1}),
1851 ),
1852 },
1853 wantRes: []Transaction{
1854 {
1855 Flags: 0x00,
1856 IsReply: 0x01,
1857 Type: []byte{0, 0},
1858 ID: []byte{0, 0, 0, 0},
1859 ErrorCode: []byte{0, 0, 0, 0},
1860 Fields: []Field{
1861 NewField(FieldData, []byte{
1862 0x00, 0x04, 0x00, 0x66, 0x00, 0x05, 0x67, 0x75, 0x65, 0x73, 0x74, 0x00, 0x69, 0x00, 0x05, 0x98,
1863 0x8a, 0x9a, 0x8c, 0x8b, 0x00, 0x6e, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1864 0x00, 0x6a, 0x00, 0x01, 0x78,
1865 }),
1866 },
1867 },
1868 },
1869 wantErr: assert.NoError,
1870 },
1871 }
1872 for _, tt := range tests {
1873 t.Run(tt.name, func(t *testing.T) {
1874 gotRes, err := HandleListUsers(tt.args.cc, tt.args.t)
1875 if !tt.wantErr(t, err, fmt.Sprintf("HandleListUsers(%v, %v)", tt.args.cc, tt.args.t)) {
1876 return
1877 }
1878
1879 tranAssertEqual(t, tt.wantRes, gotRes)
1880 })
1881 }
1882 }
1883
1884 func TestHandleDownloadFile(t *testing.T) {
1885 type args struct {
1886 cc *ClientConn
1887 t *Transaction
1888 }
1889 tests := []struct {
1890 name string
1891 args args
1892 wantRes []Transaction
1893 wantErr assert.ErrorAssertionFunc
1894 }{
1895 {
1896 name: "when user does not have required permission",
1897 args: args{
1898 cc: &ClientConn{
1899 Account: &Account{
1900 Access: func() accessBitmap {
1901 var bits accessBitmap
1902 return bits
1903 }(),
1904 },
1905 Server: &Server{},
1906 },
1907 t: NewTransaction(TranDownloadFile, &[]byte{0, 1}),
1908 },
1909 wantRes: []Transaction{
1910 {
1911 Flags: 0x00,
1912 IsReply: 0x01,
1913 Type: []byte{0, 0},
1914 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1915 ErrorCode: []byte{0, 0, 0, 1},
1916 Fields: []Field{
1917 NewField(FieldError, []byte("You are not allowed to download files.")),
1918 },
1919 },
1920 },
1921 wantErr: assert.NoError,
1922 },
1923 {
1924 name: "with a valid file",
1925 args: args{
1926 cc: &ClientConn{
1927 transfers: map[int]map[[4]byte]*FileTransfer{
1928 FileDownload: {},
1929 },
1930 Account: &Account{
1931 Access: func() accessBitmap {
1932 var bits accessBitmap
1933 bits.Set(accessDownloadFile)
1934 return bits
1935 }(),
1936 },
1937 Server: &Server{
1938 FS: &OSFileStore{},
1939 fileTransfers: map[[4]byte]*FileTransfer{},
1940 Config: &Config{
1941 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1942 },
1943 Accounts: map[string]*Account{},
1944 },
1945 },
1946 t: NewTransaction(
1947 accessDownloadFile,
1948 &[]byte{0, 1},
1949 NewField(FieldFileName, []byte("testfile.txt")),
1950 NewField(FieldFilePath, []byte{0x0, 0x00}),
1951 ),
1952 },
1953 wantRes: []Transaction{
1954 {
1955 Flags: 0x00,
1956 IsReply: 0x01,
1957 Type: []byte{0, 0},
1958 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1959 ErrorCode: []byte{0, 0, 0, 0},
1960 Fields: []Field{
1961 NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1962 NewField(FieldWaitingCount, []byte{0x00, 0x00}),
1963 NewField(FieldTransferSize, []byte{0x00, 0x00, 0x00, 0xa5}),
1964 NewField(FieldFileSize, []byte{0x00, 0x00, 0x00, 0x17}),
1965 },
1966 },
1967 },
1968 wantErr: assert.NoError,
1969 },
1970 {
1971 name: "when client requests to resume 1k test file at offset 256",
1972 args: args{
1973 cc: &ClientConn{
1974 transfers: map[int]map[[4]byte]*FileTransfer{
1975 FileDownload: {},
1976 }, Account: &Account{
1977 Access: func() accessBitmap {
1978 var bits accessBitmap
1979 bits.Set(accessDownloadFile)
1980 return bits
1981 }(),
1982 },
1983 Server: &Server{
1984 FS: &OSFileStore{},
1985
1986 // FS: func() *MockFileStore {
1987 // path, _ := os.Getwd()
1988 // testFile, err := os.Open(path + "/test/config/Files/testfile-1k")
1989 // if err != nil {
1990 // panic(err)
1991 // }
1992 //
1993 // mfi := &MockFileInfo{}
1994 // mfi.On("Mode").Return(fs.FileMode(0))
1995 // mfs := &MockFileStore{}
1996 // mfs.On("Stat", "/fakeRoot/Files/testfile.txt").Return(mfi, nil)
1997 // mfs.On("Open", "/fakeRoot/Files/testfile.txt").Return(testFile, nil)
1998 // mfs.On("Stat", "/fakeRoot/Files/.info_testfile.txt").Return(nil, errors.New("no"))
1999 // mfs.On("Stat", "/fakeRoot/Files/.rsrc_testfile.txt").Return(nil, errors.New("no"))
2000 //
2001 // return mfs
2002 // }(),
2003 fileTransfers: map[[4]byte]*FileTransfer{},
2004 Config: &Config{
2005 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
2006 },
2007 Accounts: map[string]*Account{},
2008 },
2009 },
2010 t: NewTransaction(
2011 accessDownloadFile,
2012 &[]byte{0, 1},
2013 NewField(FieldFileName, []byte("testfile-1k")),
2014 NewField(FieldFilePath, []byte{0x00, 0x00}),
2015 NewField(
2016 FieldFileResumeData,
2017 func() []byte {
2018 frd := FileResumeData{
2019 Format: [4]byte{},
2020 Version: [2]byte{},
2021 RSVD: [34]byte{},
2022 ForkCount: [2]byte{0, 2},
2023 ForkInfoList: []ForkInfoList{
2024 {
2025 Fork: [4]byte{0x44, 0x41, 0x54, 0x41}, // "DATA"
2026 DataSize: [4]byte{0, 0, 0x01, 0x00}, // request offset 256
2027 RSVDA: [4]byte{},
2028 RSVDB: [4]byte{},
2029 },
2030 {
2031 Fork: [4]byte{0x4d, 0x41, 0x43, 0x52}, // "MACR"
2032 DataSize: [4]byte{0, 0, 0, 0},
2033 RSVDA: [4]byte{},
2034 RSVDB: [4]byte{},
2035 },
2036 },
2037 }
2038 b, _ := frd.BinaryMarshal()
2039 return b
2040 }(),
2041 ),
2042 ),
2043 },
2044 wantRes: []Transaction{
2045 {
2046 Flags: 0x00,
2047 IsReply: 0x01,
2048 Type: []byte{0, 0},
2049 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2050 ErrorCode: []byte{0, 0, 0, 0},
2051 Fields: []Field{
2052 NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
2053 NewField(FieldWaitingCount, []byte{0x00, 0x00}),
2054 NewField(FieldTransferSize, []byte{0x00, 0x00, 0x03, 0x8d}),
2055 NewField(FieldFileSize, []byte{0x00, 0x00, 0x03, 0x00}),
2056 },
2057 },
2058 },
2059 wantErr: assert.NoError,
2060 },
2061 }
2062 for _, tt := range tests {
2063 t.Run(tt.name, func(t *testing.T) {
2064 gotRes, err := HandleDownloadFile(tt.args.cc, tt.args.t)
2065 if !tt.wantErr(t, err, fmt.Sprintf("HandleDownloadFile(%v, %v)", tt.args.cc, tt.args.t)) {
2066 return
2067 }
2068
2069 tranAssertEqual(t, tt.wantRes, gotRes)
2070 })
2071 }
2072 }
2073
2074 func TestHandleUpdateUser(t *testing.T) {
2075 type args struct {
2076 cc *ClientConn
2077 t *Transaction
2078 }
2079 tests := []struct {
2080 name string
2081 args args
2082 wantRes []Transaction
2083 wantErr assert.ErrorAssertionFunc
2084 }{
2085 {
2086 name: "when action is create user without required permission",
2087 args: args{
2088 cc: &ClientConn{
2089 logger: NewTestLogger(),
2090 Server: &Server{
2091 Logger: NewTestLogger(),
2092 },
2093 Account: &Account{
2094 Access: func() accessBitmap {
2095 var bits accessBitmap
2096 return bits
2097 }(),
2098 },
2099 },
2100 t: NewTransaction(
2101 TranUpdateUser,
2102 &[]byte{0, 0},
2103 NewField(FieldData, []byte{
2104 0x00, 0x04, // field count
2105
2106 0x00, 0x69, // FieldUserLogin = 105
2107 0x00, 0x03,
2108 0x9d, 0x9d, 0x9d,
2109
2110 0x00, 0x6a, // FieldUserPassword = 106
2111 0x00, 0x03,
2112 0x9c, 0x9c, 0x9c,
2113
2114 0x00, 0x66, // FieldUserName = 102
2115 0x00, 0x03,
2116 0x61, 0x61, 0x61,
2117
2118 0x00, 0x6e, // FieldUserAccess = 110
2119 0x00, 0x08,
2120 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
2121 }),
2122 ),
2123 },
2124 wantRes: []Transaction{
2125 {
2126 Flags: 0x00,
2127 IsReply: 0x01,
2128 Type: []byte{0, 0},
2129 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2130 ErrorCode: []byte{0, 0, 0, 1},
2131 Fields: []Field{
2132 NewField(FieldError, []byte("You are not allowed to create new accounts.")),
2133 },
2134 },
2135 },
2136 wantErr: assert.NoError,
2137 },
2138 {
2139 name: "when action is modify user without required permission",
2140 args: args{
2141 cc: &ClientConn{
2142 logger: NewTestLogger(),
2143 Server: &Server{
2144 Logger: NewTestLogger(),
2145 Accounts: map[string]*Account{
2146 "bbb": {},
2147 },
2148 },
2149 Account: &Account{
2150 Access: func() accessBitmap {
2151 var bits accessBitmap
2152 return bits
2153 }(),
2154 },
2155 },
2156 t: NewTransaction(
2157 TranUpdateUser,
2158 &[]byte{0, 0},
2159 NewField(FieldData, []byte{
2160 0x00, 0x04, // field count
2161
2162 0x00, 0x69, // FieldUserLogin = 105
2163 0x00, 0x03,
2164 0x9d, 0x9d, 0x9d,
2165
2166 0x00, 0x6a, // FieldUserPassword = 106
2167 0x00, 0x03,
2168 0x9c, 0x9c, 0x9c,
2169
2170 0x00, 0x66, // FieldUserName = 102
2171 0x00, 0x03,
2172 0x61, 0x61, 0x61,
2173
2174 0x00, 0x6e, // FieldUserAccess = 110
2175 0x00, 0x08,
2176 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
2177 }),
2178 ),
2179 },
2180 wantRes: []Transaction{
2181 {
2182 Flags: 0x00,
2183 IsReply: 0x01,
2184 Type: []byte{0, 0},
2185 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2186 ErrorCode: []byte{0, 0, 0, 1},
2187 Fields: []Field{
2188 NewField(FieldError, []byte("You are not allowed to modify accounts.")),
2189 },
2190 },
2191 },
2192 wantErr: assert.NoError,
2193 },
2194 {
2195 name: "when action is delete user without required permission",
2196 args: args{
2197 cc: &ClientConn{
2198 logger: NewTestLogger(),
2199 Server: &Server{
2200 Accounts: map[string]*Account{
2201 "bbb": {},
2202 },
2203 },
2204 Account: &Account{
2205 Access: func() accessBitmap {
2206 var bits accessBitmap
2207 return bits
2208 }(),
2209 },
2210 },
2211 t: NewTransaction(
2212 TranUpdateUser,
2213 &[]byte{0, 0},
2214 NewField(FieldData, []byte{
2215 0x00, 0x01,
2216 0x00, 0x65,
2217 0x00, 0x03,
2218 0x88, 0x9e, 0x8b,
2219 }),
2220 ),
2221 },
2222 wantRes: []Transaction{
2223 {
2224 Flags: 0x00,
2225 IsReply: 0x01,
2226 Type: []byte{0, 0},
2227 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2228 ErrorCode: []byte{0, 0, 0, 1},
2229 Fields: []Field{
2230 NewField(FieldError, []byte("You are not allowed to delete accounts.")),
2231 },
2232 },
2233 },
2234 wantErr: assert.NoError,
2235 },
2236 }
2237 for _, tt := range tests {
2238 t.Run(tt.name, func(t *testing.T) {
2239 gotRes, err := HandleUpdateUser(tt.args.cc, tt.args.t)
2240 if !tt.wantErr(t, err, fmt.Sprintf("HandleUpdateUser(%v, %v)", tt.args.cc, tt.args.t)) {
2241 return
2242 }
2243
2244 tranAssertEqual(t, tt.wantRes, gotRes)
2245 })
2246 }
2247 }
2248
2249 func TestHandleDelNewsArt(t *testing.T) {
2250 type args struct {
2251 cc *ClientConn
2252 t *Transaction
2253 }
2254 tests := []struct {
2255 name string
2256 args args
2257 wantRes []Transaction
2258 wantErr assert.ErrorAssertionFunc
2259 }{
2260 {
2261 name: "without required permission",
2262 args: args{
2263 cc: &ClientConn{
2264 Account: &Account{
2265 Access: func() accessBitmap {
2266 var bits accessBitmap
2267 return bits
2268 }(),
2269 },
2270 },
2271 t: NewTransaction(
2272 TranDelNewsArt,
2273 &[]byte{0, 0},
2274 ),
2275 },
2276 wantRes: []Transaction{
2277 {
2278 Flags: 0x00,
2279 IsReply: 0x01,
2280 Type: []byte{0, 0},
2281 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2282 ErrorCode: []byte{0, 0, 0, 1},
2283 Fields: []Field{
2284 NewField(FieldError, []byte("You are not allowed to delete news articles.")),
2285 },
2286 },
2287 },
2288 wantErr: assert.NoError,
2289 },
2290 }
2291 for _, tt := range tests {
2292 t.Run(tt.name, func(t *testing.T) {
2293 gotRes, err := HandleDelNewsArt(tt.args.cc, tt.args.t)
2294 if !tt.wantErr(t, err, fmt.Sprintf("HandleDelNewsArt(%v, %v)", tt.args.cc, tt.args.t)) {
2295 return
2296 }
2297 tranAssertEqual(t, tt.wantRes, gotRes)
2298 })
2299 }
2300 }
2301
2302 func TestHandleDisconnectUser(t *testing.T) {
2303 type args struct {
2304 cc *ClientConn
2305 t *Transaction
2306 }
2307 tests := []struct {
2308 name string
2309 args args
2310 wantRes []Transaction
2311 wantErr assert.ErrorAssertionFunc
2312 }{
2313 {
2314 name: "without required permission",
2315 args: args{
2316 cc: &ClientConn{
2317 Account: &Account{
2318 Access: func() accessBitmap {
2319 var bits accessBitmap
2320 return bits
2321 }(),
2322 },
2323 },
2324 t: NewTransaction(
2325 TranDelNewsArt,
2326 &[]byte{0, 0},
2327 ),
2328 },
2329 wantRes: []Transaction{
2330 {
2331 Flags: 0x00,
2332 IsReply: 0x01,
2333 Type: []byte{0, 0},
2334 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2335 ErrorCode: []byte{0, 0, 0, 1},
2336 Fields: []Field{
2337 NewField(FieldError, []byte("You are not allowed to disconnect users.")),
2338 },
2339 },
2340 },
2341 wantErr: assert.NoError,
2342 },
2343 {
2344 name: "when target user has 'cannot be disconnected' priv",
2345 args: args{
2346 cc: &ClientConn{
2347 Server: &Server{
2348 Clients: map[uint16]*ClientConn{
2349 uint16(1): {
2350 Account: &Account{
2351 Login: "unnamed",
2352 Access: func() accessBitmap {
2353 var bits accessBitmap
2354 bits.Set(accessCannotBeDiscon)
2355 return bits
2356 }(),
2357 },
2358 },
2359 },
2360 },
2361 Account: &Account{
2362 Access: func() accessBitmap {
2363 var bits accessBitmap
2364 bits.Set(accessDisconUser)
2365 return bits
2366 }(),
2367 },
2368 },
2369 t: NewTransaction(
2370 TranDelNewsArt,
2371 &[]byte{0, 0},
2372 NewField(FieldUserID, []byte{0, 1}),
2373 ),
2374 },
2375 wantRes: []Transaction{
2376 {
2377 Flags: 0x00,
2378 IsReply: 0x01,
2379 Type: []byte{0, 0},
2380 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2381 ErrorCode: []byte{0, 0, 0, 1},
2382 Fields: []Field{
2383 NewField(FieldError, []byte("unnamed is not allowed to be disconnected.")),
2384 },
2385 },
2386 },
2387 wantErr: assert.NoError,
2388 },
2389 }
2390 for _, tt := range tests {
2391 t.Run(tt.name, func(t *testing.T) {
2392 gotRes, err := HandleDisconnectUser(tt.args.cc, tt.args.t)
2393 if !tt.wantErr(t, err, fmt.Sprintf("HandleDisconnectUser(%v, %v)", tt.args.cc, tt.args.t)) {
2394 return
2395 }
2396 tranAssertEqual(t, tt.wantRes, gotRes)
2397 })
2398 }
2399 }
2400
2401 func TestHandleSendInstantMsg(t *testing.T) {
2402 type args struct {
2403 cc *ClientConn
2404 t *Transaction
2405 }
2406 tests := []struct {
2407 name string
2408 args args
2409 wantRes []Transaction
2410 wantErr assert.ErrorAssertionFunc
2411 }{
2412 {
2413 name: "without required permission",
2414 args: args{
2415 cc: &ClientConn{
2416 Account: &Account{
2417 Access: func() accessBitmap {
2418 var bits accessBitmap
2419 return bits
2420 }(),
2421 },
2422 },
2423 t: NewTransaction(
2424 TranDelNewsArt,
2425 &[]byte{0, 0},
2426 ),
2427 },
2428 wantRes: []Transaction{
2429 {
2430 Flags: 0x00,
2431 IsReply: 0x01,
2432 Type: []byte{0, 0},
2433 ID: []byte{0, 0, 0, 0},
2434 ErrorCode: []byte{0, 0, 0, 1},
2435 Fields: []Field{
2436 NewField(FieldError, []byte("You are not allowed to send private messages.")),
2437 },
2438 },
2439 },
2440 wantErr: assert.Error,
2441 },
2442 {
2443 name: "when client 1 sends a message to client 2",
2444 args: args{
2445 cc: &ClientConn{
2446 Account: &Account{
2447 Access: func() accessBitmap {
2448 var bits accessBitmap
2449 bits.Set(accessSendPrivMsg)
2450 return bits
2451 }(),
2452 },
2453 ID: &[]byte{0, 1},
2454 UserName: []byte("User1"),
2455 Server: &Server{
2456 Clients: map[uint16]*ClientConn{
2457 uint16(2): {
2458 AutoReply: []byte(nil),
2459 Flags: []byte{0, 0},
2460 },
2461 },
2462 },
2463 },
2464 t: NewTransaction(
2465 TranSendInstantMsg,
2466 &[]byte{0, 1},
2467 NewField(FieldData, []byte("hai")),
2468 NewField(FieldUserID, []byte{0, 2}),
2469 ),
2470 },
2471 wantRes: []Transaction{
2472 *NewTransaction(
2473 TranServerMsg,
2474 &[]byte{0, 2},
2475 NewField(FieldData, []byte("hai")),
2476 NewField(FieldUserName, []byte("User1")),
2477 NewField(FieldUserID, []byte{0, 1}),
2478 NewField(FieldOptions, []byte{0, 1}),
2479 ),
2480 {
2481 clientID: &[]byte{0, 1},
2482 Flags: 0x00,
2483 IsReply: 0x01,
2484 Type: []byte{0, 0},
2485 ID: []byte{0, 0, 0, 0},
2486 ErrorCode: []byte{0, 0, 0, 0},
2487 Fields: []Field(nil),
2488 },
2489 },
2490 wantErr: assert.NoError,
2491 },
2492 {
2493 name: "when client 2 has autoreply enabled",
2494 args: args{
2495 cc: &ClientConn{
2496 Account: &Account{
2497 Access: func() accessBitmap {
2498 var bits accessBitmap
2499 bits.Set(accessSendPrivMsg)
2500 return bits
2501 }(),
2502 },
2503 ID: &[]byte{0, 1},
2504 UserName: []byte("User1"),
2505 Server: &Server{
2506 Clients: map[uint16]*ClientConn{
2507 uint16(2): {
2508 Flags: []byte{0, 0},
2509 ID: &[]byte{0, 2},
2510 UserName: []byte("User2"),
2511 AutoReply: []byte("autohai"),
2512 },
2513 },
2514 },
2515 },
2516 t: NewTransaction(
2517 TranSendInstantMsg,
2518 &[]byte{0, 1},
2519 NewField(FieldData, []byte("hai")),
2520 NewField(FieldUserID, []byte{0, 2}),
2521 ),
2522 },
2523 wantRes: []Transaction{
2524 *NewTransaction(
2525 TranServerMsg,
2526 &[]byte{0, 2},
2527 NewField(FieldData, []byte("hai")),
2528 NewField(FieldUserName, []byte("User1")),
2529 NewField(FieldUserID, []byte{0, 1}),
2530 NewField(FieldOptions, []byte{0, 1}),
2531 ),
2532 *NewTransaction(
2533 TranServerMsg,
2534 &[]byte{0, 1},
2535 NewField(FieldData, []byte("autohai")),
2536 NewField(FieldUserName, []byte("User2")),
2537 NewField(FieldUserID, []byte{0, 2}),
2538 NewField(FieldOptions, []byte{0, 1}),
2539 ),
2540 {
2541 clientID: &[]byte{0, 1},
2542 Flags: 0x00,
2543 IsReply: 0x01,
2544 Type: []byte{0, 0},
2545 ID: []byte{0, 0, 0, 0},
2546 ErrorCode: []byte{0, 0, 0, 0},
2547 Fields: []Field(nil),
2548 },
2549 },
2550 wantErr: assert.NoError,
2551 },
2552 {
2553 name: "when client 2 has refuse private messages enabled",
2554 args: args{
2555 cc: &ClientConn{
2556 Account: &Account{
2557 Access: func() accessBitmap {
2558 var bits accessBitmap
2559 bits.Set(accessSendPrivMsg)
2560 return bits
2561 }(),
2562 },
2563 ID: &[]byte{0, 1},
2564 UserName: []byte("User1"),
2565 Server: &Server{
2566 Clients: map[uint16]*ClientConn{
2567 uint16(2): {
2568 Flags: []byte{255, 255},
2569 ID: &[]byte{0, 2},
2570 UserName: []byte("User2"),
2571 },
2572 },
2573 },
2574 },
2575 t: NewTransaction(
2576 TranSendInstantMsg,
2577 &[]byte{0, 1},
2578 NewField(FieldData, []byte("hai")),
2579 NewField(FieldUserID, []byte{0, 2}),
2580 ),
2581 },
2582 wantRes: []Transaction{
2583 *NewTransaction(
2584 TranServerMsg,
2585 &[]byte{0, 1},
2586 NewField(FieldData, []byte("User2 does not accept private messages.")),
2587 NewField(FieldUserName, []byte("User2")),
2588 NewField(FieldUserID, []byte{0, 2}),
2589 NewField(FieldOptions, []byte{0, 2}),
2590 ),
2591 {
2592 clientID: &[]byte{0, 1},
2593 Flags: 0x00,
2594 IsReply: 0x01,
2595 Type: []byte{0, 0},
2596 ID: []byte{0, 0, 0, 0},
2597 ErrorCode: []byte{0, 0, 0, 0},
2598 Fields: []Field(nil),
2599 },
2600 },
2601 wantErr: assert.NoError,
2602 },
2603 }
2604 for _, tt := range tests {
2605 t.Run(tt.name, func(t *testing.T) {
2606 gotRes, err := HandleSendInstantMsg(tt.args.cc, tt.args.t)
2607 if !tt.wantErr(t, err, fmt.Sprintf("HandleSendInstantMsg(%v, %v)", tt.args.cc, tt.args.t)) {
2608 return
2609 }
2610
2611 tranAssertEqual(t, tt.wantRes, gotRes)
2612 })
2613 }
2614 }
2615
2616 func TestHandleDeleteFile(t *testing.T) {
2617 type args struct {
2618 cc *ClientConn
2619 t *Transaction
2620 }
2621 tests := []struct {
2622 name string
2623 args args
2624 wantRes []Transaction
2625 wantErr assert.ErrorAssertionFunc
2626 }{
2627 {
2628 name: "when user does not have required permission to delete a folder",
2629 args: args{
2630 cc: &ClientConn{
2631 Account: &Account{
2632 Access: func() accessBitmap {
2633 var bits accessBitmap
2634 return bits
2635 }(),
2636 },
2637 Server: &Server{
2638 Config: &Config{
2639 FileRoot: func() string {
2640 return "/fakeRoot/Files"
2641 }(),
2642 },
2643 FS: func() *MockFileStore {
2644 mfi := &MockFileInfo{}
2645 mfi.On("Mode").Return(fs.FileMode(0))
2646 mfi.On("Size").Return(int64(100))
2647 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2648 mfi.On("IsDir").Return(false)
2649 mfi.On("Name").Return("testfile")
2650
2651 mfs := &MockFileStore{}
2652 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2653 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2654 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2655
2656 return mfs
2657 }(),
2658 Accounts: map[string]*Account{},
2659 },
2660 },
2661 t: NewTransaction(
2662 TranDeleteFile, &[]byte{0, 1},
2663 NewField(FieldFileName, []byte("testfile")),
2664 NewField(FieldFilePath, []byte{
2665 0x00, 0x01,
2666 0x00, 0x00,
2667 0x03,
2668 0x61, 0x61, 0x61,
2669 }),
2670 ),
2671 },
2672 wantRes: []Transaction{
2673 {
2674 Flags: 0x00,
2675 IsReply: 0x01,
2676 Type: []byte{0, 0},
2677 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2678 ErrorCode: []byte{0, 0, 0, 1},
2679 Fields: []Field{
2680 NewField(FieldError, []byte("You are not allowed to delete files.")),
2681 },
2682 },
2683 },
2684 wantErr: assert.NoError,
2685 },
2686 {
2687 name: "deletes all associated metadata files",
2688 args: args{
2689 cc: &ClientConn{
2690 Account: &Account{
2691 Access: func() accessBitmap {
2692 var bits accessBitmap
2693 bits.Set(accessDeleteFile)
2694 return bits
2695 }(),
2696 },
2697 Server: &Server{
2698 Config: &Config{
2699 FileRoot: func() string {
2700 return "/fakeRoot/Files"
2701 }(),
2702 },
2703 FS: func() *MockFileStore {
2704 mfi := &MockFileInfo{}
2705 mfi.On("Mode").Return(fs.FileMode(0))
2706 mfi.On("Size").Return(int64(100))
2707 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2708 mfi.On("IsDir").Return(false)
2709 mfi.On("Name").Return("testfile")
2710
2711 mfs := &MockFileStore{}
2712 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2713 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2714 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2715
2716 mfs.On("RemoveAll", "/fakeRoot/Files/aaa/testfile").Return(nil)
2717 mfs.On("Remove", "/fakeRoot/Files/aaa/testfile.incomplete").Return(nil)
2718 mfs.On("Remove", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil)
2719 mfs.On("Remove", "/fakeRoot/Files/aaa/.info_testfile").Return(nil)
2720
2721 return mfs
2722 }(),
2723 Accounts: map[string]*Account{},
2724 },
2725 },
2726 t: NewTransaction(
2727 TranDeleteFile, &[]byte{0, 1},
2728 NewField(FieldFileName, []byte("testfile")),
2729 NewField(FieldFilePath, []byte{
2730 0x00, 0x01,
2731 0x00, 0x00,
2732 0x03,
2733 0x61, 0x61, 0x61,
2734 }),
2735 ),
2736 },
2737 wantRes: []Transaction{
2738 {
2739 Flags: 0x00,
2740 IsReply: 0x01,
2741 Type: []byte{0, 0},
2742 ID: []byte{0x0, 0x0, 0x0, 0x0},
2743 ErrorCode: []byte{0, 0, 0, 0},
2744 Fields: []Field(nil),
2745 },
2746 },
2747 wantErr: assert.NoError,
2748 },
2749 }
2750 for _, tt := range tests {
2751 t.Run(tt.name, func(t *testing.T) {
2752 gotRes, err := HandleDeleteFile(tt.args.cc, tt.args.t)
2753 if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteFile(%v, %v)", tt.args.cc, tt.args.t)) {
2754 return
2755 }
2756
2757 tranAssertEqual(t, tt.wantRes, gotRes)
2758
2759 tt.args.cc.Server.FS.(*MockFileStore).AssertExpectations(t)
2760 })
2761 }
2762 }
2763
2764 func TestHandleGetFileNameList(t *testing.T) {
2765 type args struct {
2766 cc *ClientConn
2767 t *Transaction
2768 }
2769 tests := []struct {
2770 name string
2771 args args
2772 wantRes []Transaction
2773 wantErr assert.ErrorAssertionFunc
2774 }{
2775 {
2776 name: "when FieldFilePath is a drop box, but user does not have accessViewDropBoxes ",
2777 args: args{
2778 cc: &ClientConn{
2779 Account: &Account{
2780 Access: func() accessBitmap {
2781 var bits accessBitmap
2782 return bits
2783 }(),
2784 },
2785 Server: &Server{
2786
2787 Config: &Config{
2788 FileRoot: func() string {
2789 path, _ := os.Getwd()
2790 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2791 }(),
2792 },
2793 },
2794 },
2795 t: NewTransaction(
2796 TranGetFileNameList, &[]byte{0, 1},
2797 NewField(FieldFilePath, []byte{
2798 0x00, 0x01,
2799 0x00, 0x00,
2800 0x08,
2801 0x64, 0x72, 0x6f, 0x70, 0x20, 0x62, 0x6f, 0x78, // "drop box"
2802 }),
2803 ),
2804 },
2805 wantRes: []Transaction{
2806 {
2807 Flags: 0x00,
2808 IsReply: 0x01,
2809 Type: []byte{0, 0},
2810 ID: []byte{0, 0, 0, 0},
2811 ErrorCode: []byte{0, 0, 0, 1},
2812 Fields: []Field{
2813 NewField(FieldError, []byte("You are not allowed to view drop boxes.")),
2814 },
2815 },
2816 },
2817 wantErr: assert.NoError,
2818 },
2819 {
2820 name: "with file root",
2821 args: args{
2822 cc: &ClientConn{
2823 Server: &Server{
2824 Config: &Config{
2825 FileRoot: func() string {
2826 path, _ := os.Getwd()
2827 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2828 }(),
2829 },
2830 },
2831 },
2832 t: NewTransaction(
2833 TranGetFileNameList, &[]byte{0, 1},
2834 NewField(FieldFilePath, []byte{
2835 0x00, 0x00,
2836 0x00, 0x00,
2837 }),
2838 ),
2839 },
2840 wantRes: []Transaction{
2841 {
2842 Flags: 0x00,
2843 IsReply: 0x01,
2844 Type: []byte{0, 0},
2845 ID: []byte{0, 0, 0, 0},
2846 ErrorCode: []byte{0, 0, 0, 0},
2847 Fields: []Field{
2848 NewField(
2849 FieldFileNameWithInfo,
2850 func() []byte {
2851 fnwi := FileNameWithInfo{
2852 fileNameWithInfoHeader: fileNameWithInfoHeader{
2853 Type: [4]byte{0x54, 0x45, 0x58, 0x54},
2854 Creator: [4]byte{0x54, 0x54, 0x58, 0x54},
2855 FileSize: [4]byte{0, 0, 0x04, 0},
2856 RSVD: [4]byte{},
2857 NameScript: [2]byte{},
2858 NameSize: [2]byte{0, 0x0b},
2859 },
2860 name: []byte("testfile-1k"),
2861 }
2862 b, _ := fnwi.MarshalBinary()
2863 return b
2864 }(),
2865 ),
2866 },
2867 },
2868 },
2869 wantErr: assert.NoError,
2870 },
2871 }
2872 for _, tt := range tests {
2873 t.Run(tt.name, func(t *testing.T) {
2874 gotRes, err := HandleGetFileNameList(tt.args.cc, tt.args.t)
2875 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetFileNameList(%v, %v)", tt.args.cc, tt.args.t)) {
2876 return
2877 }
2878
2879 tranAssertEqual(t, tt.wantRes, gotRes)
2880 })
2881 }
2882 }
2883
2884 func TestHandleGetClientInfoText(t *testing.T) {
2885 type args struct {
2886 cc *ClientConn
2887 t *Transaction
2888 }
2889 tests := []struct {
2890 name string
2891 args args
2892 wantRes []Transaction
2893 wantErr assert.ErrorAssertionFunc
2894 }{
2895 {
2896 name: "when user does not have required permission",
2897 args: args{
2898 cc: &ClientConn{
2899 Account: &Account{
2900 Access: func() accessBitmap {
2901 var bits accessBitmap
2902 return bits
2903 }(),
2904 },
2905 Server: &Server{
2906 Accounts: map[string]*Account{},
2907 },
2908 },
2909 t: NewTransaction(
2910 TranGetClientInfoText, &[]byte{0, 1},
2911 NewField(FieldUserID, []byte{0, 1}),
2912 ),
2913 },
2914 wantRes: []Transaction{
2915 {
2916 Flags: 0x00,
2917 IsReply: 0x01,
2918 Type: []byte{0, 0},
2919 ID: []byte{0, 0, 0, 0},
2920 ErrorCode: []byte{0, 0, 0, 1},
2921 Fields: []Field{
2922 NewField(FieldError, []byte("You are not allowed to get client info.")),
2923 },
2924 },
2925 },
2926 wantErr: assert.NoError,
2927 },
2928 {
2929 name: "with a valid user",
2930 args: args{
2931 cc: &ClientConn{
2932 UserName: []byte("Testy McTest"),
2933 RemoteAddr: "1.2.3.4:12345",
2934 Account: &Account{
2935 Access: func() accessBitmap {
2936 var bits accessBitmap
2937 bits.Set(accessGetClientInfo)
2938 return bits
2939 }(),
2940 Name: "test",
2941 Login: "test",
2942 },
2943 Server: &Server{
2944 Accounts: map[string]*Account{},
2945 Clients: map[uint16]*ClientConn{
2946 uint16(1): {
2947 UserName: []byte("Testy McTest"),
2948 RemoteAddr: "1.2.3.4:12345",
2949 Account: &Account{
2950 Access: func() accessBitmap {
2951 var bits accessBitmap
2952 bits.Set(accessGetClientInfo)
2953 return bits
2954 }(),
2955 Name: "test",
2956 Login: "test",
2957 },
2958 },
2959 },
2960 },
2961 transfers: map[int]map[[4]byte]*FileTransfer{
2962 FileDownload: {},
2963 FileUpload: {},
2964 FolderDownload: {},
2965 FolderUpload: {},
2966 },
2967 },
2968 t: NewTransaction(
2969 TranGetClientInfoText, &[]byte{0, 1},
2970 NewField(FieldUserID, []byte{0, 1}),
2971 ),
2972 },
2973 wantRes: []Transaction{
2974 {
2975 Flags: 0x00,
2976 IsReply: 0x01,
2977 Type: []byte{0, 0},
2978 ID: []byte{0, 0, 0, 0},
2979 ErrorCode: []byte{0, 0, 0, 0},
2980 Fields: []Field{
2981 NewField(FieldData, []byte(
2982 strings.ReplaceAll(`Nickname: Testy McTest
2983 Name: test
2984 Account: test
2985 Address: 1.2.3.4:12345
2986
2987 -------- File Downloads ---------
2988
2989 None.
2990
2991 ------- Folder Downloads --------
2992
2993 None.
2994
2995 --------- File Uploads ----------
2996
2997 None.
2998
2999 -------- Folder Uploads ---------
3000
3001 None.
3002
3003 ------- Waiting Downloads -------
3004
3005 None.
3006
3007 `, "\n", "\r")),
3008 ),
3009 NewField(FieldUserName, []byte("Testy McTest")),
3010 },
3011 },
3012 },
3013 wantErr: assert.NoError,
3014 },
3015 }
3016 for _, tt := range tests {
3017 t.Run(tt.name, func(t *testing.T) {
3018 gotRes, err := HandleGetClientInfoText(tt.args.cc, tt.args.t)
3019 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetClientInfoText(%v, %v)", tt.args.cc, tt.args.t)) {
3020 return
3021 }
3022 tranAssertEqual(t, tt.wantRes, gotRes)
3023 })
3024 }
3025 }
3026
3027 func TestHandleTranAgreed(t *testing.T) {
3028 type args struct {
3029 cc *ClientConn
3030 t *Transaction
3031 }
3032 tests := []struct {
3033 name string
3034 args args
3035 wantRes []Transaction
3036 wantErr assert.ErrorAssertionFunc
3037 }{
3038 {
3039 name: "normal request flow",
3040 args: args{
3041 cc: &ClientConn{
3042 Account: &Account{
3043 Access: func() accessBitmap {
3044 var bits accessBitmap
3045 bits.Set(accessDisconUser)
3046 bits.Set(accessAnyName)
3047 return bits
3048 }()},
3049 Icon: []byte{0, 1},
3050 Flags: []byte{0, 1},
3051 Version: []byte{0, 1},
3052 ID: &[]byte{0, 1},
3053 logger: NewTestLogger(),
3054 Server: &Server{
3055 Config: &Config{
3056 BannerFile: "banner.jpg",
3057 },
3058 },
3059 },
3060 t: NewTransaction(
3061 TranAgreed, nil,
3062 NewField(FieldUserName, []byte("username")),
3063 NewField(FieldUserIconID, []byte{0, 1}),
3064 NewField(FieldOptions, []byte{0, 0}),
3065 ),
3066 },
3067 wantRes: []Transaction{
3068 {
3069 clientID: &[]byte{0, 1},
3070 Flags: 0x00,
3071 IsReply: 0x00,
3072 Type: []byte{0, 0x7a},
3073 ID: []byte{0, 0, 0, 0},
3074 ErrorCode: []byte{0, 0, 0, 0},
3075 Fields: []Field{
3076 NewField(FieldBannerType, []byte("JPEG")),
3077 },
3078 },
3079 {
3080 clientID: &[]byte{0, 1},
3081 Flags: 0x00,
3082 IsReply: 0x01,
3083 Type: []byte{0, 0},
3084 ID: []byte{0, 0, 0, 0},
3085 ErrorCode: []byte{0, 0, 0, 0},
3086 Fields: []Field{},
3087 },
3088 },
3089 wantErr: assert.NoError,
3090 },
3091 }
3092 for _, tt := range tests {
3093 t.Run(tt.name, func(t *testing.T) {
3094 gotRes, err := HandleTranAgreed(tt.args.cc, tt.args.t)
3095 if !tt.wantErr(t, err, fmt.Sprintf("HandleTranAgreed(%v, %v)", tt.args.cc, tt.args.t)) {
3096 return
3097 }
3098 tranAssertEqual(t, tt.wantRes, gotRes)
3099 })
3100 }
3101 }
3102
3103 func TestHandleSetClientUserInfo(t *testing.T) {
3104 type args struct {
3105 cc *ClientConn
3106 t *Transaction
3107 }
3108 tests := []struct {
3109 name string
3110 args args
3111 wantRes []Transaction
3112 wantErr assert.ErrorAssertionFunc
3113 }{
3114 {
3115 name: "when client does not have accessAnyName",
3116 args: args{
3117 cc: &ClientConn{
3118 Account: &Account{
3119 Access: func() accessBitmap {
3120 var bits accessBitmap
3121 return bits
3122 }(),
3123 },
3124 ID: &[]byte{0, 1},
3125 UserName: []byte("Guest"),
3126 Flags: []byte{0, 1},
3127 Server: &Server{
3128 Clients: map[uint16]*ClientConn{
3129 uint16(1): {
3130 ID: &[]byte{0, 1},
3131 },
3132 },
3133 },
3134 },
3135 t: NewTransaction(
3136 TranSetClientUserInfo, nil,
3137 NewField(FieldUserIconID, []byte{0, 1}),
3138 NewField(FieldUserName, []byte("NOPE")),
3139 ),
3140 },
3141 wantRes: []Transaction{
3142 {
3143 clientID: &[]byte{0, 1},
3144 Flags: 0x00,
3145 IsReply: 0x00,
3146 Type: []byte{0x01, 0x2d},
3147 ID: []byte{0, 0, 0, 0},
3148 ErrorCode: []byte{0, 0, 0, 0},
3149 Fields: []Field{
3150 NewField(FieldUserID, []byte{0, 1}),
3151 NewField(FieldUserIconID, []byte{0, 1}),
3152 NewField(FieldUserFlags, []byte{0, 1}),
3153 NewField(FieldUserName, []byte("Guest"))},
3154 },
3155 },
3156 wantErr: assert.NoError,
3157 },
3158 }
3159 for _, tt := range tests {
3160 t.Run(tt.name, func(t *testing.T) {
3161 gotRes, err := HandleSetClientUserInfo(tt.args.cc, tt.args.t)
3162 if !tt.wantErr(t, err, fmt.Sprintf("HandleSetClientUserInfo(%v, %v)", tt.args.cc, tt.args.t)) {
3163 return
3164 }
3165
3166 tranAssertEqual(t, tt.wantRes, gotRes)
3167 })
3168 }
3169 }
3170
3171 func TestHandleDelNewsItem(t *testing.T) {
3172 type args struct {
3173 cc *ClientConn
3174 t *Transaction
3175 }
3176 tests := []struct {
3177 name string
3178 args args
3179 wantRes []Transaction
3180 wantErr assert.ErrorAssertionFunc
3181 }{
3182 {
3183 name: "when user does not have permission to delete a news category",
3184 args: args{
3185 cc: &ClientConn{
3186 Account: &Account{
3187 Access: accessBitmap{},
3188 },
3189 ID: &[]byte{0, 1},
3190 Server: &Server{
3191 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3192 "test": {
3193 Type: []byte{0, 3},
3194 Count: nil,
3195 NameSize: 0,
3196 Name: "zz",
3197 },
3198 }},
3199 },
3200 },
3201 t: NewTransaction(
3202 TranDelNewsItem, nil,
3203 NewField(FieldNewsPath,
3204 []byte{
3205 0, 1,
3206 0, 0,
3207 4,
3208 0x74, 0x65, 0x73, 0x74,
3209 },
3210 ),
3211 ),
3212 },
3213 wantRes: []Transaction{
3214 {
3215 clientID: &[]byte{0, 1},
3216 Flags: 0x00,
3217 IsReply: 0x01,
3218 Type: []byte{0, 0},
3219 ID: []byte{0, 0, 0, 0},
3220 ErrorCode: []byte{0, 0, 0, 1},
3221 Fields: []Field{
3222 NewField(FieldError, []byte("You are not allowed to delete news categories.")),
3223 },
3224 },
3225 },
3226 wantErr: assert.NoError,
3227 },
3228 {
3229 name: "when user does not have permission to delete a news folder",
3230 args: args{
3231 cc: &ClientConn{
3232 Account: &Account{
3233 Access: accessBitmap{},
3234 },
3235 ID: &[]byte{0, 1},
3236 Server: &Server{
3237 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3238 "testcat": {
3239 Type: []byte{0, 2},
3240 Count: nil,
3241 NameSize: 0,
3242 Name: "test",
3243 },
3244 }},
3245 },
3246 },
3247 t: NewTransaction(
3248 TranDelNewsItem, nil,
3249 NewField(FieldNewsPath,
3250 []byte{
3251 0, 1,
3252 0, 0,
3253 4,
3254 0x74, 0x65, 0x73, 0x74,
3255 },
3256 ),
3257 ),
3258 },
3259 wantRes: []Transaction{
3260 {
3261 clientID: &[]byte{0, 1},
3262 Flags: 0x00,
3263 IsReply: 0x01,
3264 Type: []byte{0, 0},
3265 ID: []byte{0, 0, 0, 0},
3266 ErrorCode: []byte{0, 0, 0, 1},
3267 Fields: []Field{
3268 NewField(FieldError, []byte("You are not allowed to delete news folders.")),
3269 },
3270 },
3271 },
3272 wantErr: assert.NoError,
3273 },
3274 {
3275 name: "when user deletes a news folder",
3276 args: args{
3277 cc: &ClientConn{
3278 Account: &Account{
3279 Access: func() accessBitmap {
3280 var bits accessBitmap
3281 bits.Set(accessNewsDeleteFldr)
3282 return bits
3283 }(),
3284 },
3285 ID: &[]byte{0, 1},
3286 Server: &Server{
3287 ConfigDir: "/fakeConfigRoot",
3288 FS: func() *MockFileStore {
3289 mfs := &MockFileStore{}
3290 mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
3291 return mfs
3292 }(),
3293 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3294 "testcat": {
3295 Type: []byte{0, 2},
3296 Count: nil,
3297 NameSize: 0,
3298 Name: "test",
3299 },
3300 }},
3301 },
3302 },
3303 t: NewTransaction(
3304 TranDelNewsItem, nil,
3305 NewField(FieldNewsPath,
3306 []byte{
3307 0, 1,
3308 0, 0,
3309 4,
3310 0x74, 0x65, 0x73, 0x74,
3311 },
3312 ),
3313 ),
3314 },
3315 wantRes: []Transaction{
3316 {
3317 clientID: &[]byte{0, 1},
3318 Flags: 0x00,
3319 IsReply: 0x01,
3320 Type: []byte{0, 0},
3321 ID: []byte{0, 0, 0, 0},
3322 ErrorCode: []byte{0, 0, 0, 0},
3323 Fields: []Field{},
3324 },
3325 },
3326 wantErr: assert.NoError,
3327 },
3328 }
3329 for _, tt := range tests {
3330 t.Run(tt.name, func(t *testing.T) {
3331 gotRes, err := HandleDelNewsItem(tt.args.cc, tt.args.t)
3332 if !tt.wantErr(t, err, fmt.Sprintf("HandleDelNewsItem(%v, %v)", tt.args.cc, tt.args.t)) {
3333 return
3334 }
3335 tranAssertEqual(t, tt.wantRes, gotRes)
3336 })
3337 }
3338 }
3339
3340 func TestHandleDownloadBanner(t *testing.T) {
3341 type args struct {
3342 cc *ClientConn
3343 t *Transaction
3344 }
3345 tests := []struct {
3346 name string
3347 args args
3348 wantRes []Transaction
3349 wantErr assert.ErrorAssertionFunc
3350 }{
3351 {
3352 name: "returns expected response",
3353 args: args{
3354 cc: &ClientConn{
3355 ID: &[]byte{0, 1},
3356 transfers: map[int]map[[4]byte]*FileTransfer{
3357 bannerDownload: {},
3358 },
3359 Server: &Server{
3360 ConfigDir: "/config",
3361 Config: &Config{
3362 BannerFile: "banner.jpg",
3363 },
3364 fileTransfers: map[[4]byte]*FileTransfer{},
3365 FS: func() *MockFileStore {
3366 mfi := &MockFileInfo{}
3367 mfi.On("Size").Return(int64(100))
3368
3369 mfs := &MockFileStore{}
3370 mfs.On("Stat", "/config/banner.jpg").Return(mfi, nil)
3371 return mfs
3372 }(),
3373 },
3374 },
3375 t: NewTransaction(TranDownloadBanner, nil),
3376 },
3377 wantRes: []Transaction{
3378 {
3379 clientID: &[]byte{0, 1},
3380 Flags: 0x00,
3381 IsReply: 0x01,
3382 Type: []byte{0, 0},
3383 ID: []byte{0, 0, 0, 0},
3384 ErrorCode: []byte{0, 0, 0, 0},
3385 Fields: []Field{
3386 NewField(FieldRefNum, []byte{1, 2, 3, 4}),
3387 NewField(FieldTransferSize, []byte{0, 0, 0, 0x64}),
3388 },
3389 },
3390 },
3391 wantErr: assert.NoError,
3392 },
3393 }
3394 for _, tt := range tests {
3395 t.Run(tt.name, func(t *testing.T) {
3396 gotRes, err := HandleDownloadBanner(tt.args.cc, tt.args.t)
3397 if !tt.wantErr(t, err, fmt.Sprintf("HandleDownloadBanner(%v, %v)", tt.args.cc, tt.args.t)) {
3398 return
3399 }
3400
3401 tranAssertEqual(t, tt.wantRes, gotRes)
3402 })
3403 }
3404 }
3405
3406 func TestHandleTranOldPostNews(t *testing.T) {
3407 type args struct {
3408 cc *ClientConn
3409 t *Transaction
3410 }
3411 tests := []struct {
3412 name string
3413 args args
3414 wantRes []Transaction
3415 wantErr assert.ErrorAssertionFunc
3416 }{
3417 {
3418 name: "when user does not have required permission",
3419 args: args{
3420 cc: &ClientConn{
3421 Account: &Account{
3422 Access: func() accessBitmap {
3423 var bits accessBitmap
3424 return bits
3425 }(),
3426 },
3427 },
3428 t: NewTransaction(
3429 TranOldPostNews, &[]byte{0, 1},
3430 NewField(FieldData, []byte("hai")),
3431 ),
3432 },
3433 wantRes: []Transaction{
3434 {
3435 Flags: 0x00,
3436 IsReply: 0x01,
3437 Type: []byte{0, 0},
3438 ID: []byte{0, 0, 0, 0},
3439 ErrorCode: []byte{0, 0, 0, 1},
3440 Fields: []Field{
3441 NewField(FieldError, []byte("You are not allowed to post news.")),
3442 },
3443 },
3444 },
3445 wantErr: assert.NoError,
3446 },
3447 {
3448 name: "when user posts news update",
3449 args: args{
3450 cc: &ClientConn{
3451 Account: &Account{
3452 Access: func() accessBitmap {
3453 var bits accessBitmap
3454 bits.Set(accessNewsPostArt)
3455 return bits
3456 }(),
3457 },
3458 Server: &Server{
3459 FS: func() *MockFileStore {
3460 mfs := &MockFileStore{}
3461 mfs.On("WriteFile", "/fakeConfigRoot/MessageBoard.txt", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
3462 return mfs
3463 }(),
3464 ConfigDir: "/fakeConfigRoot",
3465 Config: &Config{},
3466 },
3467 },
3468 t: NewTransaction(
3469 TranOldPostNews, &[]byte{0, 1},
3470 NewField(FieldData, []byte("hai")),
3471 ),
3472 },
3473 wantRes: []Transaction{
3474 {
3475 Flags: 0x00,
3476 IsReply: 0x01,
3477 Type: []byte{0, 0},
3478 ID: []byte{0, 0, 0, 0},
3479 ErrorCode: []byte{0, 0, 0, 0},
3480 },
3481 },
3482 wantErr: assert.NoError,
3483 },
3484 }
3485 for _, tt := range tests {
3486 t.Run(tt.name, func(t *testing.T) {
3487 gotRes, err := HandleTranOldPostNews(tt.args.cc, tt.args.t)
3488 if !tt.wantErr(t, err, fmt.Sprintf("HandleTranOldPostNews(%v, %v)", tt.args.cc, tt.args.t)) {
3489 return
3490 }
3491
3492 tranAssertEqual(t, tt.wantRes, gotRes)
3493 })
3494 }
3495 }
3496
3497 func TestHandleInviteNewChat(t *testing.T) {
3498 type args struct {
3499 cc *ClientConn
3500 t *Transaction
3501 }
3502 tests := []struct {
3503 name string
3504 args args
3505 wantRes []Transaction
3506 wantErr assert.ErrorAssertionFunc
3507 }{
3508 {
3509 name: "when user does not have required permission",
3510 args: args{
3511 cc: &ClientConn{
3512 Account: &Account{
3513 Access: func() accessBitmap {
3514 var bits accessBitmap
3515 return bits
3516 }(),
3517 },
3518 },
3519 t: NewTransaction(TranInviteNewChat, &[]byte{0, 1}),
3520 },
3521 wantRes: []Transaction{
3522 {
3523 Flags: 0x00,
3524 IsReply: 0x01,
3525 Type: []byte{0, 0},
3526 ID: []byte{0, 0, 0, 0},
3527 ErrorCode: []byte{0, 0, 0, 1},
3528 Fields: []Field{
3529 NewField(FieldError, []byte("You are not allowed to request private chat.")),
3530 },
3531 },
3532 },
3533 wantErr: assert.NoError,
3534 },
3535 {
3536 name: "when userA invites userB to new private chat",
3537 args: args{
3538 cc: &ClientConn{
3539 ID: &[]byte{0, 1},
3540 Account: &Account{
3541 Access: func() accessBitmap {
3542 var bits accessBitmap
3543 bits.Set(accessOpenChat)
3544 return bits
3545 }(),
3546 },
3547 UserName: []byte("UserA"),
3548 Icon: []byte{0, 1},
3549 Flags: []byte{0, 0},
3550 Server: &Server{
3551 Clients: map[uint16]*ClientConn{
3552 uint16(2): {
3553 ID: &[]byte{0, 2},
3554 UserName: []byte("UserB"),
3555 Flags: []byte{0, 0},
3556 },
3557 },
3558 PrivateChats: make(map[uint32]*PrivateChat),
3559 },
3560 },
3561 t: NewTransaction(
3562 TranInviteNewChat, &[]byte{0, 1},
3563 NewField(FieldUserID, []byte{0, 2}),
3564 ),
3565 },
3566 wantRes: []Transaction{
3567 {
3568 clientID: &[]byte{0, 2},
3569 Flags: 0x00,
3570 IsReply: 0x00,
3571 Type: []byte{0, 0x71},
3572 ID: []byte{0, 0, 0, 0},
3573 ErrorCode: []byte{0, 0, 0, 0},
3574 Fields: []Field{
3575 NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3576 NewField(FieldUserName, []byte("UserA")),
3577 NewField(FieldUserID, []byte{0, 1}),
3578 },
3579 },
3580
3581 {
3582 clientID: &[]byte{0, 1},
3583 Flags: 0x00,
3584 IsReply: 0x01,
3585 Type: []byte{0, 0},
3586 ID: []byte{0, 0, 0, 0},
3587 ErrorCode: []byte{0, 0, 0, 0},
3588 Fields: []Field{
3589 NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3590 NewField(FieldUserName, []byte("UserA")),
3591 NewField(FieldUserID, []byte{0, 1}),
3592 NewField(FieldUserIconID, []byte{0, 1}),
3593 NewField(FieldUserFlags, []byte{0, 0}),
3594 },
3595 },
3596 },
3597 wantErr: assert.NoError,
3598 },
3599 {
3600 name: "when userA invites userB to new private chat, but UserB has refuse private chat enabled",
3601 args: args{
3602 cc: &ClientConn{
3603 ID: &[]byte{0, 1},
3604 Account: &Account{
3605 Access: func() accessBitmap {
3606 var bits accessBitmap
3607 bits.Set(accessOpenChat)
3608 return bits
3609 }(),
3610 },
3611 UserName: []byte("UserA"),
3612 Icon: []byte{0, 1},
3613 Flags: []byte{0, 0},
3614 Server: &Server{
3615 Clients: map[uint16]*ClientConn{
3616 uint16(2): {
3617 ID: &[]byte{0, 2},
3618 UserName: []byte("UserB"),
3619 Flags: []byte{255, 255},
3620 },
3621 },
3622 PrivateChats: make(map[uint32]*PrivateChat),
3623 },
3624 },
3625 t: NewTransaction(
3626 TranInviteNewChat, &[]byte{0, 1},
3627 NewField(FieldUserID, []byte{0, 2}),
3628 ),
3629 },
3630 wantRes: []Transaction{
3631 {
3632 clientID: &[]byte{0, 1},
3633 Flags: 0x00,
3634 IsReply: 0x00,
3635 Type: []byte{0, 0x68},
3636 ID: []byte{0, 0, 0, 0},
3637 ErrorCode: []byte{0, 0, 0, 0},
3638 Fields: []Field{
3639 NewField(FieldData, []byte("UserB does not accept private chats.")),
3640 NewField(FieldUserName, []byte("UserB")),
3641 NewField(FieldUserID, []byte{0, 2}),
3642 NewField(FieldOptions, []byte{0, 2}),
3643 },
3644 },
3645 {
3646 clientID: &[]byte{0, 1},
3647 Flags: 0x00,
3648 IsReply: 0x01,
3649 Type: []byte{0, 0},
3650 ID: []byte{0, 0, 0, 0},
3651 ErrorCode: []byte{0, 0, 0, 0},
3652 Fields: []Field{
3653 NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3654 NewField(FieldUserName, []byte("UserA")),
3655 NewField(FieldUserID, []byte{0, 1}),
3656 NewField(FieldUserIconID, []byte{0, 1}),
3657 NewField(FieldUserFlags, []byte{0, 0}),
3658 },
3659 },
3660 },
3661 wantErr: assert.NoError,
3662 },
3663 }
3664 for _, tt := range tests {
3665 t.Run(tt.name, func(t *testing.T) {
3666 rand.Seed(1)
3667 gotRes, err := HandleInviteNewChat(tt.args.cc, tt.args.t)
3668 if !tt.wantErr(t, err, fmt.Sprintf("HandleInviteNewChat(%v, %v)", tt.args.cc, tt.args.t)) {
3669 return
3670 }
3671 tranAssertEqual(t, tt.wantRes, gotRes)
3672 })
3673 }
3674 }
3675
3676 func TestHandleGetNewsArtData(t *testing.T) {
3677 type args struct {
3678 cc *ClientConn
3679 t *Transaction
3680 }
3681 tests := []struct {
3682 name string
3683 args args
3684 wantRes []Transaction
3685 wantErr assert.ErrorAssertionFunc
3686 }{
3687 {
3688 name: "when user does not have required permission",
3689 args: args{
3690 cc: &ClientConn{
3691 Account: &Account{
3692 Access: func() accessBitmap {
3693 var bits accessBitmap
3694 return bits
3695 }(),
3696 },
3697 Server: &Server{
3698 Accounts: map[string]*Account{},
3699 },
3700 },
3701 t: NewTransaction(
3702 TranGetNewsArtData, &[]byte{0, 1},
3703 ),
3704 },
3705 wantRes: []Transaction{
3706 {
3707 Flags: 0x00,
3708 IsReply: 0x01,
3709 Type: []byte{0, 0},
3710 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
3711 ErrorCode: []byte{0, 0, 0, 1},
3712 Fields: []Field{
3713 NewField(FieldError, []byte("You are not allowed to read news.")),
3714 },
3715 },
3716 },
3717 wantErr: assert.NoError,
3718 },
3719 }
3720 for _, tt := range tests {
3721 t.Run(tt.name, func(t *testing.T) {
3722 gotRes, err := HandleGetNewsArtData(tt.args.cc, tt.args.t)
3723 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetNewsArtData(%v, %v)", tt.args.cc, tt.args.t)) {
3724 return
3725 }
3726 tranAssertEqual(t, tt.wantRes, gotRes)
3727 })
3728 }
3729 }
3730
3731 func TestHandleGetNewsArtNameList(t *testing.T) {
3732 type args struct {
3733 cc *ClientConn
3734 t *Transaction
3735 }
3736 tests := []struct {
3737 name string
3738 args args
3739 wantRes []Transaction
3740 wantErr assert.ErrorAssertionFunc
3741 }{
3742 {
3743 name: "when user does not have required permission",
3744 args: args{
3745 cc: &ClientConn{
3746 Account: &Account{
3747 Access: func() accessBitmap {
3748 var bits accessBitmap
3749 return bits
3750 }(),
3751 },
3752 Server: &Server{
3753 Accounts: map[string]*Account{},
3754 },
3755 },
3756 t: NewTransaction(
3757 TranGetNewsArtNameList, &[]byte{0, 1},
3758 ),
3759 },
3760 wantRes: []Transaction{
3761 {
3762 Flags: 0x00,
3763 IsReply: 0x01,
3764 Type: []byte{0, 0},
3765 ErrorCode: []byte{0, 0, 0, 1},
3766 Fields: []Field{
3767 NewField(FieldError, []byte("You are not allowed to read news.")),
3768 },
3769 },
3770 },
3771 wantErr: assert.NoError,
3772 },
3773 }
3774 for _, tt := range tests {
3775 t.Run(tt.name, func(t *testing.T) {
3776 gotRes, err := HandleGetNewsArtNameList(tt.args.cc, tt.args.t)
3777 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetNewsArtNameList(%v, %v)", tt.args.cc, tt.args.t)) {
3778 return
3779 }
3780 tranAssertEqual(t, tt.wantRes, gotRes)
3781 })
3782 }
3783 }
3784
3785 func TestHandleNewNewsFldr(t *testing.T) {
3786 type args struct {
3787 cc *ClientConn
3788 t *Transaction
3789 }
3790 tests := []struct {
3791 name string
3792 args args
3793 wantRes []Transaction
3794 wantErr assert.ErrorAssertionFunc
3795 }{
3796 {
3797 name: "when user does not have required permission",
3798 args: args{
3799 cc: &ClientConn{
3800 Account: &Account{
3801 Access: func() accessBitmap {
3802 var bits accessBitmap
3803 return bits
3804 }(),
3805 },
3806 Server: &Server{
3807 Accounts: map[string]*Account{},
3808 },
3809 },
3810 t: NewTransaction(
3811 TranGetNewsArtNameList, &[]byte{0, 1},
3812 ),
3813 },
3814 wantRes: []Transaction{
3815 {
3816 Flags: 0x00,
3817 IsReply: 0x01,
3818 Type: []byte{0, 0},
3819 ErrorCode: []byte{0, 0, 0, 1},
3820 Fields: []Field{
3821 NewField(FieldError, []byte("You are not allowed to create news folders.")),
3822 },
3823 },
3824 },
3825 wantErr: assert.NoError,
3826 },
3827 {
3828 name: "with a valid request",
3829 args: args{
3830 cc: &ClientConn{
3831 Account: &Account{
3832 Access: func() accessBitmap {
3833 var bits accessBitmap
3834 bits.Set(accessNewsCreateFldr)
3835 return bits
3836 }(),
3837 },
3838 logger: NewTestLogger(),
3839 ID: &[]byte{0, 1},
3840 Server: &Server{
3841 ConfigDir: "/fakeConfigRoot",
3842 FS: func() *MockFileStore {
3843 mfs := &MockFileStore{}
3844 mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil)
3845 return mfs
3846 }(),
3847 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3848 "test": {
3849 Type: []byte{0, 2},
3850 Count: nil,
3851 NameSize: 0,
3852 Name: "test",
3853 SubCats: make(map[string]NewsCategoryListData15),
3854 },
3855 }},
3856 },
3857 },
3858 t: NewTransaction(
3859 TranGetNewsArtNameList, &[]byte{0, 1},
3860 NewField(FieldFileName, []byte("testFolder")),
3861 NewField(FieldNewsPath,
3862 []byte{
3863 0, 1,
3864 0, 0,
3865 4,
3866 0x74, 0x65, 0x73, 0x74,
3867 },
3868 ),
3869 ),
3870 },
3871 wantRes: []Transaction{
3872 {
3873 clientID: &[]byte{0, 1},
3874 Flags: 0x00,
3875 IsReply: 0x01,
3876 Type: []byte{0, 0},
3877 ID: []byte{0, 0, 0, 0},
3878 ErrorCode: []byte{0, 0, 0, 0},
3879 Fields: []Field{},
3880 },
3881 },
3882 wantErr: assert.NoError,
3883 },
3884 //{
3885 // name: "when there is an error writing the threaded news file",
3886 // args: args{
3887 // cc: &ClientConn{
3888 // Account: &Account{
3889 // Access: func() accessBitmap {
3890 // var bits accessBitmap
3891 // bits.Set(accessNewsCreateFldr)
3892 // return bits
3893 // }(),
3894 // },
3895 // logger: NewTestLogger(),
3896 // ID: &[]byte{0, 1},
3897 // Server: &Server{
3898 // ConfigDir: "/fakeConfigRoot",
3899 // FS: func() *MockFileStore {
3900 // mfs := &MockFileStore{}
3901 // mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(os.ErrNotExist)
3902 // return mfs
3903 // }(),
3904 // ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3905 // "test": {
3906 // Type: []byte{0, 2},
3907 // Count: nil,
3908 // NameSize: 0,
3909 // Name: "test",
3910 // SubCats: make(map[string]NewsCategoryListData15),
3911 // },
3912 // }},
3913 // },
3914 // },
3915 // t: NewTransaction(
3916 // TranGetNewsArtNameList, &[]byte{0, 1},
3917 // NewField(FieldFileName, []byte("testFolder")),
3918 // NewField(FieldNewsPath,
3919 // []byte{
3920 // 0, 1,
3921 // 0, 0,
3922 // 4,
3923 // 0x74, 0x65, 0x73, 0x74,
3924 // },
3925 // ),
3926 // ),
3927 // },
3928 // wantRes: []Transaction{
3929 // {
3930 // clientID: &[]byte{0, 1},
3931 // Flags: 0x00,
3932 // IsReply: 0x01,
3933 // Type: []byte{0, 0},
3934 // ErrorCode: []byte{0, 0, 0, 1},
3935 // Fields: []Field{
3936 // NewField(FieldError, []byte("Error creating news folder.")),
3937 // },
3938 // },
3939 // },
3940 // wantErr: assert.Error,
3941 // },
3942 }
3943 for _, tt := range tests {
3944 t.Run(tt.name, func(t *testing.T) {
3945 gotRes, err := HandleNewNewsFldr(tt.args.cc, tt.args.t)
3946 if !tt.wantErr(t, err, fmt.Sprintf("HandleNewNewsFldr(%v, %v)", tt.args.cc, tt.args.t)) {
3947 return
3948 }
3949 tranAssertEqual(t, tt.wantRes, gotRes)
3950 })
3951 }
3952 }