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