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