6 "github.com/stretchr/testify/assert"
7 "github.com/stretchr/testify/mock"
17 func TestHandleSetChatSubject(t *testing.T) {
29 name: "sends chat subject to private chat members",
32 UserName: []byte{0x00, 0x01},
34 PrivateChats: map[uint32]*PrivateChat{
37 ClientConn: map[uint16]*ClientConn{
40 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
46 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
53 Clients: map[uint16]*ClientConn{
56 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
62 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
72 Type: []byte{0, 0x6a},
73 ID: []byte{0, 0, 0, 1},
74 ErrorCode: []byte{0, 0, 0, 0},
76 NewField(fieldChatID, []byte{0, 0, 0, 1}),
77 NewField(fieldChatSubject, []byte("Test Subject")),
83 clientID: &[]byte{0, 1},
86 Type: []byte{0, 0x77},
87 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
88 ErrorCode: []byte{0, 0, 0, 0},
90 NewField(fieldChatID, []byte{0, 0, 0, 1}),
91 NewField(fieldChatSubject, []byte("Test Subject")),
95 clientID: &[]byte{0, 2},
98 Type: []byte{0, 0x77},
99 ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
100 ErrorCode: []byte{0, 0, 0, 0},
102 NewField(fieldChatID, []byte{0, 0, 0, 1}),
103 NewField(fieldChatSubject, []byte("Test Subject")),
110 for _, tt := range tests {
111 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
113 t.Run(tt.name, func(t *testing.T) {
114 got, err := HandleSetChatSubject(tt.args.cc, tt.args.t)
115 if (err != nil) != tt.wantErr {
116 t.Errorf("HandleSetChatSubject() error = %v, wantErr %v", err, tt.wantErr)
119 if !assert.Equal(t, tt.want, got) {
120 t.Errorf("HandleSetChatSubject() got = %v, want %v", got, tt.want)
126 func TestHandleLeaveChat(t *testing.T) {
138 name: "returns expected transactions",
143 PrivateChats: map[uint32]*PrivateChat{
145 ClientConn: map[uint16]*ClientConn{
148 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
154 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
161 Clients: map[uint16]*ClientConn{
164 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
170 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
177 t: NewTransaction(tranDeleteUser, nil, NewField(fieldChatID, []byte{0, 0, 0, 1})),
181 clientID: &[]byte{0, 1},
184 Type: []byte{0, 0x76},
185 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
186 ErrorCode: []byte{0, 0, 0, 0},
188 NewField(fieldChatID, []byte{0, 0, 0, 1}),
189 NewField(fieldUserID, []byte{0, 2}),
196 for _, tt := range tests {
198 t.Run(tt.name, func(t *testing.T) {
199 got, err := HandleLeaveChat(tt.args.cc, tt.args.t)
200 if (err != nil) != tt.wantErr {
201 t.Errorf("HandleLeaveChat() error = %v, wantErr %v", err, tt.wantErr)
204 if !assert.Equal(t, tt.want, got) {
205 t.Errorf("HandleLeaveChat() got = %v, want %v", got, tt.want)
211 func TestHandleGetUserNameList(t *testing.T) {
223 name: "replies with userlist transaction",
229 Clients: map[uint16]*ClientConn{
234 UserName: []byte{0, 4},
241 UserName: []byte{0, 4},
248 UserName: []byte{0, 4},
255 ID: []byte{0, 0, 0, 1},
261 clientID: &[]byte{1, 1},
265 ID: []byte{0, 0, 0, 1},
266 ErrorCode: []byte{0, 0, 0, 0},
269 fieldUsernameWithInfo,
270 []byte{00, 01, 00, 02, 00, 03, 00, 02, 00, 04},
273 fieldUsernameWithInfo,
274 []byte{00, 02, 00, 02, 00, 03, 00, 02, 00, 04},
282 for _, tt := range tests {
283 t.Run(tt.name, func(t *testing.T) {
284 got, err := HandleGetUserNameList(tt.args.cc, tt.args.t)
285 if (err != nil) != tt.wantErr {
286 t.Errorf("HandleGetUserNameList() error = %v, wantErr %v", err, tt.wantErr)
289 assert.Equal(t, tt.want, got)
294 func TestHandleChatSend(t *testing.T) {
306 name: "sends chat msg transaction to all clients",
310 Access: func() accessBitmap {
311 var bits accessBitmap
312 bits.Set(accessSendChat)
316 UserName: []byte{0x00, 0x01},
318 Clients: map[uint16]*ClientConn{
321 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
327 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
336 NewField(fieldData, []byte("hai")),
342 clientID: &[]byte{0, 1},
345 Type: []byte{0, 0x6a},
346 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
347 ErrorCode: []byte{0, 0, 0, 0},
349 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
353 clientID: &[]byte{0, 2},
356 Type: []byte{0, 0x6a},
357 ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
358 ErrorCode: []byte{0, 0, 0, 0},
360 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
367 name: "when user does not have required permission",
371 Access: func() accessBitmap {
372 var bits accessBitmap
377 Accounts: map[string]*Account{},
381 tranChatSend, &[]byte{0, 1},
382 NewField(fieldData, []byte("hai")),
389 Type: []byte{0, 0x00},
390 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
391 ErrorCode: []byte{0, 0, 0, 1},
393 NewField(fieldError, []byte("You are not allowed to participate in chat.")),
400 name: "sends chat msg as emote if fieldChatOptions is set",
404 Access: func() accessBitmap {
405 var bits accessBitmap
406 bits.Set(accessSendChat)
410 UserName: []byte("Testy McTest"),
412 Clients: map[uint16]*ClientConn{
415 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
421 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
430 NewField(fieldData, []byte("performed action")),
431 NewField(fieldChatOptions, []byte{0x00, 0x01}),
437 clientID: &[]byte{0, 1},
440 Type: []byte{0, 0x6a},
441 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
442 ErrorCode: []byte{0, 0, 0, 0},
444 NewField(fieldData, []byte("\r*** Testy McTest performed action")),
448 clientID: &[]byte{0, 2},
451 Type: []byte{0, 0x6a},
452 ID: []byte{0xf0, 0xc5, 0x34, 0x1e},
453 ErrorCode: []byte{0, 0, 0, 0},
455 NewField(fieldData, []byte("\r*** Testy McTest performed action")),
462 name: "only sends chat msg to clients with accessReadChat permission",
466 Access: func() accessBitmap {
467 var bits accessBitmap
468 bits.Set(accessSendChat)
472 UserName: []byte{0x00, 0x01},
474 Clients: map[uint16]*ClientConn{
477 Access: func() accessBitmap {
478 var bits accessBitmap
479 bits.Set(accessReadChat)
486 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
495 NewField(fieldData, []byte("hai")),
501 clientID: &[]byte{0, 1},
504 Type: []byte{0, 0x6a},
505 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
506 ErrorCode: []byte{0, 0, 0, 0},
508 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
515 name: "only sends private chat msg to members of private chat",
519 Access: func() accessBitmap {
520 var bits accessBitmap
521 bits.Set(accessSendChat)
525 UserName: []byte{0x00, 0x01},
527 PrivateChats: map[uint32]*PrivateChat{
529 ClientConn: map[uint16]*ClientConn{
539 Clients: map[uint16]*ClientConn{
542 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
548 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
554 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
563 NewField(fieldData, []byte("hai")),
564 NewField(fieldChatID, []byte{0, 0, 0, 1}),
570 clientID: &[]byte{0, 1},
573 Type: []byte{0, 0x6a},
574 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
575 ErrorCode: []byte{0, 0, 0, 0},
577 NewField(fieldChatID, []byte{0, 0, 0, 1}),
578 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
582 clientID: &[]byte{0, 2},
585 Type: []byte{0, 0x6a},
586 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
587 ErrorCode: []byte{0, 0, 0, 0},
589 NewField(fieldChatID, []byte{0, 0, 0, 1}),
590 NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
597 for _, tt := range tests {
598 t.Run(tt.name, func(t *testing.T) {
599 got, err := HandleChatSend(tt.args.cc, tt.args.t)
601 if (err != nil) != tt.wantErr {
602 t.Errorf("HandleChatSend() error = %v, wantErr %v", err, tt.wantErr)
605 tranAssertEqual(t, tt.want, got)
610 func TestHandleGetFileInfo(t *testing.T) {
611 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
620 wantRes []Transaction
624 name: "returns expected fields when a valid file is requested",
627 ID: &[]byte{0x00, 0x01},
631 FileRoot: func() string {
632 path, _ := os.Getwd()
633 return filepath.Join(path, "/test/config/Files")
639 tranGetFileInfo, nil,
640 NewField(fieldFileName, []byte("testfile.txt")),
641 NewField(fieldFilePath, []byte{0x00, 0x00}),
644 wantRes: []Transaction{
646 clientID: &[]byte{0, 1},
649 Type: []byte{0, 0xce},
650 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
651 ErrorCode: []byte{0, 0, 0, 0},
653 NewField(fieldFileName, []byte("testfile.txt")),
654 NewField(fieldFileTypeString, []byte("Text File")),
655 NewField(fieldFileCreatorString, []byte("ttxt")),
656 NewField(fieldFileComment, []byte{}),
657 NewField(fieldFileType, []byte("TEXT")),
658 NewField(fieldFileCreateDate, make([]byte, 8)),
659 NewField(fieldFileModifyDate, make([]byte, 8)),
660 NewField(fieldFileSize, []byte{0x0, 0x0, 0x0, 0x17}),
667 for _, tt := range tests {
668 t.Run(tt.name, func(t *testing.T) {
669 rand.Seed(1) // reset seed between tests to make transaction IDs predictable
671 gotRes, err := HandleGetFileInfo(tt.args.cc, tt.args.t)
672 if (err != nil) != tt.wantErr {
673 t.Errorf("HandleGetFileInfo() error = %v, wantErr %v", err, tt.wantErr)
677 // Clear the fileWrapper timestamp fields to work around problems running the tests in multiple timezones
678 // TODO: revisit how to test this by mocking the stat calls
679 gotRes[0].Fields[5].Data = make([]byte, 8)
680 gotRes[0].Fields[6].Data = make([]byte, 8)
681 if !assert.Equal(t, tt.wantRes, gotRes) {
682 t.Errorf("HandleGetFileInfo() gotRes = %v, want %v", gotRes, tt.wantRes)
688 func TestHandleNewFolder(t *testing.T) {
696 wantRes []Transaction
700 name: "without required permission",
704 Access: func() accessBitmap {
705 var bits accessBitmap
715 wantRes: []Transaction{
719 Type: []byte{0, 0x00},
720 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
721 ErrorCode: []byte{0, 0, 0, 1},
723 NewField(fieldError, []byte("You are not allowed to create folders.")),
730 name: "when path is nested",
734 Access: func() accessBitmap {
735 var bits accessBitmap
736 bits.Set(accessCreateFolder)
745 FS: func() *MockFileStore {
746 mfs := &MockFileStore{}
747 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
748 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
754 tranNewFolder, &[]byte{0, 1},
755 NewField(fieldFileName, []byte("testFolder")),
756 NewField(fieldFilePath, []byte{
764 wantRes: []Transaction{
766 clientID: &[]byte{0, 1},
769 Type: []byte{0, 0xcd},
770 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
771 ErrorCode: []byte{0, 0, 0, 0},
777 name: "when path is not nested",
781 Access: func() accessBitmap {
782 var bits accessBitmap
783 bits.Set(accessCreateFolder)
792 FS: func() *MockFileStore {
793 mfs := &MockFileStore{}
794 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
795 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
801 tranNewFolder, &[]byte{0, 1},
802 NewField(fieldFileName, []byte("testFolder")),
805 wantRes: []Transaction{
807 clientID: &[]byte{0, 1},
810 Type: []byte{0, 0xcd},
811 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
812 ErrorCode: []byte{0, 0, 0, 0},
818 name: "when Write returns an err",
822 Access: func() accessBitmap {
823 var bits accessBitmap
824 bits.Set(accessCreateFolder)
833 FS: func() *MockFileStore {
834 mfs := &MockFileStore{}
835 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
836 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
842 tranNewFolder, &[]byte{0, 1},
843 NewField(fieldFileName, []byte("testFolder")),
844 NewField(fieldFilePath, []byte{
849 wantRes: []Transaction{},
853 name: "fieldFileName does not allow directory traversal",
857 Access: func() accessBitmap {
858 var bits accessBitmap
859 bits.Set(accessCreateFolder)
868 FS: func() *MockFileStore {
869 mfs := &MockFileStore{}
870 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
871 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
877 tranNewFolder, &[]byte{0, 1},
878 NewField(fieldFileName, []byte("../../testFolder")),
881 wantRes: []Transaction{
883 clientID: &[]byte{0, 1},
886 Type: []byte{0, 0xcd},
887 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
888 ErrorCode: []byte{0, 0, 0, 0},
893 name: "fieldFilePath does not allow directory traversal",
897 Access: func() accessBitmap {
898 var bits accessBitmap
899 bits.Set(accessCreateFolder)
908 FS: func() *MockFileStore {
909 mfs := &MockFileStore{}
910 mfs.On("Mkdir", "/Files/foo/testFolder", fs.FileMode(0777)).Return(nil)
911 mfs.On("Stat", "/Files/foo/testFolder").Return(nil, os.ErrNotExist)
917 tranNewFolder, &[]byte{0, 1},
918 NewField(fieldFileName, []byte("testFolder")),
919 NewField(fieldFilePath, []byte{
930 wantRes: []Transaction{
932 clientID: &[]byte{0, 1},
935 Type: []byte{0, 0xcd},
936 ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
937 ErrorCode: []byte{0, 0, 0, 0},
942 for _, tt := range tests {
943 t.Run(tt.name, func(t *testing.T) {
945 gotRes, err := HandleNewFolder(tt.args.cc, tt.args.t)
946 if (err != nil) != tt.wantErr {
947 t.Errorf("HandleNewFolder() error = %v, wantErr %v", err, tt.wantErr)
951 if !tranAssertEqual(t, tt.wantRes, gotRes) {
952 t.Errorf("HandleNewFolder() gotRes = %v, want %v", gotRes, tt.wantRes)
958 func TestHandleUploadFile(t *testing.T) {
966 wantRes []Transaction
970 name: "when request is valid and user has Upload Anywhere permission",
975 fileTransfers: map[[4]byte]*FileTransfer{},
977 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
979 transfers: map[int]map[[4]byte]*FileTransfer{
983 Access: func() accessBitmap {
984 var bits accessBitmap
985 bits.Set(accessUploadFile)
986 bits.Set(accessUploadAnywhere)
992 tranUploadFile, &[]byte{0, 1},
993 NewField(fieldFileName, []byte("testFile")),
994 NewField(fieldFilePath, []byte{
1002 wantRes: []Transaction{
1006 Type: []byte{0, 0xcb},
1007 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1008 ErrorCode: []byte{0, 0, 0, 0},
1010 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}), // rand.Seed(1)
1017 name: "when user does not have required access",
1021 Access: func() accessBitmap {
1022 var bits accessBitmap
1028 tranUploadFile, &[]byte{0, 1},
1029 NewField(fieldFileName, []byte("testFile")),
1030 NewField(fieldFilePath, []byte{
1038 wantRes: []Transaction{
1042 Type: []byte{0, 0x00},
1043 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1044 ErrorCode: []byte{0, 0, 0, 1},
1046 NewField(fieldError, []byte("You are not allowed to upload files.")), // rand.Seed(1)
1053 for _, tt := range tests {
1054 t.Run(tt.name, func(t *testing.T) {
1056 gotRes, err := HandleUploadFile(tt.args.cc, tt.args.t)
1057 if (err != nil) != tt.wantErr {
1058 t.Errorf("HandleUploadFile() error = %v, wantErr %v", err, tt.wantErr)
1062 tranAssertEqual(t, tt.wantRes, gotRes)
1068 func TestHandleMakeAlias(t *testing.T) {
1076 wantRes []Transaction
1080 name: "with valid input and required permissions",
1083 logger: NewTestLogger(),
1085 Access: func() accessBitmap {
1086 var bits accessBitmap
1087 bits.Set(accessMakeAlias)
1093 FileRoot: func() string {
1094 path, _ := os.Getwd()
1095 return path + "/test/config/Files"
1098 Logger: NewTestLogger(),
1099 FS: func() *MockFileStore {
1100 mfs := &MockFileStore{}
1101 path, _ := os.Getwd()
1104 path+"/test/config/Files/foo/testFile",
1105 path+"/test/config/Files/bar/testFile",
1112 tranMakeFileAlias, &[]byte{0, 1},
1113 NewField(fieldFileName, []byte("testFile")),
1114 NewField(fieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1115 NewField(fieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1118 wantRes: []Transaction{
1122 Type: []byte{0, 0xd1},
1123 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1124 ErrorCode: []byte{0, 0, 0, 0},
1125 Fields: []Field(nil),
1131 name: "when symlink returns an error",
1134 logger: NewTestLogger(),
1136 Access: func() accessBitmap {
1137 var bits accessBitmap
1138 bits.Set(accessMakeAlias)
1144 FileRoot: func() string {
1145 path, _ := os.Getwd()
1146 return path + "/test/config/Files"
1149 Logger: NewTestLogger(),
1150 FS: func() *MockFileStore {
1151 mfs := &MockFileStore{}
1152 path, _ := os.Getwd()
1155 path+"/test/config/Files/foo/testFile",
1156 path+"/test/config/Files/bar/testFile",
1157 ).Return(errors.New("ohno"))
1163 tranMakeFileAlias, &[]byte{0, 1},
1164 NewField(fieldFileName, []byte("testFile")),
1165 NewField(fieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1166 NewField(fieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1169 wantRes: []Transaction{
1173 Type: []byte{0, 0x00},
1174 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1175 ErrorCode: []byte{0, 0, 0, 1},
1177 NewField(fieldError, []byte("Error creating alias")),
1184 name: "when user does not have required permission",
1187 logger: NewTestLogger(),
1189 Access: func() accessBitmap {
1190 var bits accessBitmap
1196 FileRoot: func() string {
1197 path, _ := os.Getwd()
1198 return path + "/test/config/Files"
1204 tranMakeFileAlias, &[]byte{0, 1},
1205 NewField(fieldFileName, []byte("testFile")),
1206 NewField(fieldFilePath, []byte{
1212 NewField(fieldFileNewPath, []byte{
1220 wantRes: []Transaction{
1224 Type: []byte{0, 0x00},
1225 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1226 ErrorCode: []byte{0, 0, 0, 1},
1228 NewField(fieldError, []byte("You are not allowed to make aliases.")),
1235 for _, tt := range tests {
1236 t.Run(tt.name, func(t *testing.T) {
1237 gotRes, err := HandleMakeAlias(tt.args.cc, tt.args.t)
1238 if (err != nil) != tt.wantErr {
1239 t.Errorf("HandleMakeAlias(%v, %v)", tt.args.cc, tt.args.t)
1243 tranAssertEqual(t, tt.wantRes, gotRes)
1248 func TestHandleGetUser(t *testing.T) {
1256 wantRes []Transaction
1257 wantErr assert.ErrorAssertionFunc
1260 name: "when account is valid",
1264 Access: func() accessBitmap {
1265 var bits accessBitmap
1266 bits.Set(accessOpenUser)
1271 Accounts: map[string]*Account{
1275 Password: "password",
1276 Access: accessBitmap{},
1282 tranGetUser, &[]byte{0, 1},
1283 NewField(fieldUserLogin, []byte("guest")),
1286 wantRes: []Transaction{
1290 Type: []byte{0x01, 0x60},
1291 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1292 ErrorCode: []byte{0, 0, 0, 0},
1294 NewField(fieldUserName, []byte("Guest")),
1295 NewField(fieldUserLogin, negateString([]byte("guest"))),
1296 NewField(fieldUserPassword, []byte("password")),
1297 NewField(fieldUserAccess, []byte{0, 0, 0, 0, 0, 0, 0, 0}),
1301 wantErr: assert.NoError,
1304 name: "when user does not have required permission",
1308 Access: func() accessBitmap {
1309 var bits accessBitmap
1314 Accounts: map[string]*Account{},
1318 tranGetUser, &[]byte{0, 1},
1319 NewField(fieldUserLogin, []byte("nonExistentUser")),
1322 wantRes: []Transaction{
1326 Type: []byte{0, 0x00},
1327 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1328 ErrorCode: []byte{0, 0, 0, 1},
1330 NewField(fieldError, []byte("You are not allowed to view accounts.")),
1334 wantErr: assert.NoError,
1337 name: "when account does not exist",
1341 Access: func() accessBitmap {
1342 var bits accessBitmap
1343 bits.Set(accessOpenUser)
1348 Accounts: map[string]*Account{},
1352 tranGetUser, &[]byte{0, 1},
1353 NewField(fieldUserLogin, []byte("nonExistentUser")),
1356 wantRes: []Transaction{
1360 Type: []byte{0, 0x00},
1361 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1362 ErrorCode: []byte{0, 0, 0, 1},
1364 NewField(fieldError, []byte("Account does not exist.")),
1368 wantErr: assert.NoError,
1371 for _, tt := range tests {
1372 t.Run(tt.name, func(t *testing.T) {
1373 gotRes, err := HandleGetUser(tt.args.cc, tt.args.t)
1374 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetUser(%v, %v)", tt.args.cc, tt.args.t)) {
1378 tranAssertEqual(t, tt.wantRes, gotRes)
1383 func TestHandleDeleteUser(t *testing.T) {
1391 wantRes []Transaction
1392 wantErr assert.ErrorAssertionFunc
1395 name: "when user dataFile",
1399 Access: func() accessBitmap {
1400 var bits accessBitmap
1401 bits.Set(accessDeleteUser)
1406 Accounts: map[string]*Account{
1409 Name: "Testy McTest",
1410 Password: "password",
1411 Access: accessBitmap{},
1414 FS: func() *MockFileStore {
1415 mfs := &MockFileStore{}
1416 mfs.On("Remove", "Users/testuser.yaml").Return(nil)
1422 tranDeleteUser, &[]byte{0, 1},
1423 NewField(fieldUserLogin, negateString([]byte("testuser"))),
1426 wantRes: []Transaction{
1430 Type: []byte{0x1, 0x5f},
1431 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1432 ErrorCode: []byte{0, 0, 0, 0},
1433 Fields: []Field(nil),
1436 wantErr: assert.NoError,
1439 name: "when user does not have required permission",
1443 Access: func() accessBitmap {
1444 var bits accessBitmap
1449 Accounts: map[string]*Account{},
1453 tranDeleteUser, &[]byte{0, 1},
1454 NewField(fieldUserLogin, negateString([]byte("testuser"))),
1457 wantRes: []Transaction{
1461 Type: []byte{0, 0x00},
1462 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1463 ErrorCode: []byte{0, 0, 0, 1},
1465 NewField(fieldError, []byte("You are not allowed to delete accounts.")),
1469 wantErr: assert.NoError,
1472 for _, tt := range tests {
1473 t.Run(tt.name, func(t *testing.T) {
1474 gotRes, err := HandleDeleteUser(tt.args.cc, tt.args.t)
1475 if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteUser(%v, %v)", tt.args.cc, tt.args.t)) {
1479 tranAssertEqual(t, tt.wantRes, gotRes)
1484 func TestHandleGetMsgs(t *testing.T) {
1492 wantRes []Transaction
1493 wantErr assert.ErrorAssertionFunc
1496 name: "returns news data",
1500 Access: func() accessBitmap {
1501 var bits accessBitmap
1502 bits.Set(accessNewsReadArt)
1507 FlatNews: []byte("TEST"),
1511 tranGetMsgs, &[]byte{0, 1},
1514 wantRes: []Transaction{
1518 Type: []byte{0, 0x65},
1519 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1520 ErrorCode: []byte{0, 0, 0, 0},
1522 NewField(fieldData, []byte("TEST")),
1526 wantErr: assert.NoError,
1529 name: "when user does not have required permission",
1533 Access: func() accessBitmap {
1534 var bits accessBitmap
1539 Accounts: map[string]*Account{},
1543 tranGetMsgs, &[]byte{0, 1},
1546 wantRes: []Transaction{
1550 Type: []byte{0, 0x00},
1551 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1552 ErrorCode: []byte{0, 0, 0, 1},
1554 NewField(fieldError, []byte("You are not allowed to read news.")),
1558 wantErr: assert.NoError,
1561 for _, tt := range tests {
1562 t.Run(tt.name, func(t *testing.T) {
1563 gotRes, err := HandleGetMsgs(tt.args.cc, tt.args.t)
1564 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetMsgs(%v, %v)", tt.args.cc, tt.args.t)) {
1568 tranAssertEqual(t, tt.wantRes, gotRes)
1573 func TestHandleNewUser(t *testing.T) {
1581 wantRes []Transaction
1582 wantErr assert.ErrorAssertionFunc
1585 name: "when user does not have required permission",
1589 Access: func() accessBitmap {
1590 var bits accessBitmap
1595 Accounts: map[string]*Account{},
1599 tranNewUser, &[]byte{0, 1},
1602 wantRes: []Transaction{
1606 Type: []byte{0, 0x00},
1607 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1608 ErrorCode: []byte{0, 0, 0, 1},
1610 NewField(fieldError, []byte("You are not allowed to create new accounts.")),
1614 wantErr: assert.NoError,
1617 for _, tt := range tests {
1618 t.Run(tt.name, func(t *testing.T) {
1619 gotRes, err := HandleNewUser(tt.args.cc, tt.args.t)
1620 if !tt.wantErr(t, err, fmt.Sprintf("HandleNewUser(%v, %v)", tt.args.cc, tt.args.t)) {
1624 tranAssertEqual(t, tt.wantRes, gotRes)
1629 func TestHandleListUsers(t *testing.T) {
1637 wantRes []Transaction
1638 wantErr assert.ErrorAssertionFunc
1641 name: "when user does not have required permission",
1645 Access: func() accessBitmap {
1646 var bits accessBitmap
1651 Accounts: map[string]*Account{},
1655 tranNewUser, &[]byte{0, 1},
1658 wantRes: []Transaction{
1662 Type: []byte{0, 0x00},
1663 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1664 ErrorCode: []byte{0, 0, 0, 1},
1666 NewField(fieldError, []byte("You are not allowed to view accounts.")),
1670 wantErr: assert.NoError,
1673 name: "when user has required permission",
1677 Access: func() accessBitmap {
1678 var bits accessBitmap
1679 bits.Set(accessOpenUser)
1684 Accounts: map[string]*Account{
1689 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
1695 tranGetClientInfoText, &[]byte{0, 1},
1696 NewField(fieldUserID, []byte{0, 1}),
1699 wantRes: []Transaction{
1703 Type: []byte{0x01, 0x2f},
1704 ID: []byte{0, 0, 0, 0},
1705 ErrorCode: []byte{0, 0, 0, 0},
1707 NewField(fieldData, []byte{
1708 0x00, 0x04, 0x00, 0x66, 0x00, 0x05, 0x67, 0x75, 0x65, 0x73, 0x74, 0x00, 0x69, 0x00, 0x05, 0x98,
1709 0x8a, 0x9a, 0x8c, 0x8b, 0x00, 0x6e, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1710 0x00, 0x6a, 0x00, 0x01, 0x78,
1715 wantErr: assert.NoError,
1718 for _, tt := range tests {
1719 t.Run(tt.name, func(t *testing.T) {
1720 gotRes, err := HandleListUsers(tt.args.cc, tt.args.t)
1721 if !tt.wantErr(t, err, fmt.Sprintf("HandleListUsers(%v, %v)", tt.args.cc, tt.args.t)) {
1725 tranAssertEqual(t, tt.wantRes, gotRes)
1730 func TestHandleDownloadFile(t *testing.T) {
1738 wantRes []Transaction
1739 wantErr assert.ErrorAssertionFunc
1742 name: "when user does not have required permission",
1746 Access: func() accessBitmap {
1747 var bits accessBitmap
1753 t: NewTransaction(tranDownloadFile, &[]byte{0, 1}),
1755 wantRes: []Transaction{
1759 Type: []byte{0, 0x00},
1760 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1761 ErrorCode: []byte{0, 0, 0, 1},
1763 NewField(fieldError, []byte("You are not allowed to download files.")),
1767 wantErr: assert.NoError,
1770 name: "with a valid file",
1773 transfers: map[int]map[[4]byte]*FileTransfer{
1777 Access: func() accessBitmap {
1778 var bits accessBitmap
1779 bits.Set(accessDownloadFile)
1785 fileTransfers: map[[4]byte]*FileTransfer{},
1787 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1789 Accounts: map[string]*Account{},
1795 NewField(fieldFileName, []byte("testfile.txt")),
1796 NewField(fieldFilePath, []byte{0x0, 0x00}),
1799 wantRes: []Transaction{
1803 Type: []byte{0, 0x2},
1804 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1805 ErrorCode: []byte{0, 0, 0, 0},
1807 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1808 NewField(fieldWaitingCount, []byte{0x00, 0x00}),
1809 NewField(fieldTransferSize, []byte{0x00, 0x00, 0x00, 0xa5}),
1810 NewField(fieldFileSize, []byte{0x00, 0x00, 0x00, 0x17}),
1814 wantErr: assert.NoError,
1817 name: "when client requests to resume 1k test file at offset 256",
1820 transfers: map[int]map[[4]byte]*FileTransfer{
1822 }, Account: &Account{
1823 Access: func() accessBitmap {
1824 var bits accessBitmap
1825 bits.Set(accessDownloadFile)
1832 // FS: func() *MockFileStore {
1833 // path, _ := os.Getwd()
1834 // testFile, err := os.Open(path + "/test/config/Files/testfile-1k")
1839 // mfi := &MockFileInfo{}
1840 // mfi.On("Mode").Return(fs.FileMode(0))
1841 // mfs := &MockFileStore{}
1842 // mfs.On("Stat", "/fakeRoot/Files/testfile.txt").Return(mfi, nil)
1843 // mfs.On("Open", "/fakeRoot/Files/testfile.txt").Return(testFile, nil)
1844 // mfs.On("Stat", "/fakeRoot/Files/.info_testfile.txt").Return(nil, errors.New("no"))
1845 // mfs.On("Stat", "/fakeRoot/Files/.rsrc_testfile.txt").Return(nil, errors.New("no"))
1849 fileTransfers: map[[4]byte]*FileTransfer{},
1851 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1853 Accounts: map[string]*Account{},
1859 NewField(fieldFileName, []byte("testfile-1k")),
1860 NewField(fieldFilePath, []byte{0x00, 0x00}),
1862 fieldFileResumeData,
1864 frd := FileResumeData{
1868 ForkCount: [2]byte{0, 2},
1869 ForkInfoList: []ForkInfoList{
1871 Fork: [4]byte{0x44, 0x41, 0x54, 0x41}, // "DATA"
1872 DataSize: [4]byte{0, 0, 0x01, 0x00}, // request offset 256
1877 Fork: [4]byte{0x4d, 0x41, 0x43, 0x52}, // "MACR"
1878 DataSize: [4]byte{0, 0, 0, 0},
1884 b, _ := frd.BinaryMarshal()
1890 wantRes: []Transaction{
1894 Type: []byte{0, 0x2},
1895 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1896 ErrorCode: []byte{0, 0, 0, 0},
1898 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1899 NewField(fieldWaitingCount, []byte{0x00, 0x00}),
1900 NewField(fieldTransferSize, []byte{0x00, 0x00, 0x03, 0x8d}),
1901 NewField(fieldFileSize, []byte{0x00, 0x00, 0x03, 0x00}),
1905 wantErr: assert.NoError,
1908 for _, tt := range tests {
1909 t.Run(tt.name, func(t *testing.T) {
1910 gotRes, err := HandleDownloadFile(tt.args.cc, tt.args.t)
1911 if !tt.wantErr(t, err, fmt.Sprintf("HandleDownloadFile(%v, %v)", tt.args.cc, tt.args.t)) {
1915 tranAssertEqual(t, tt.wantRes, gotRes)
1920 func TestHandleUpdateUser(t *testing.T) {
1928 wantRes []Transaction
1929 wantErr assert.ErrorAssertionFunc
1932 name: "when action is create user without required permission",
1935 logger: NewTestLogger(),
1937 Logger: NewTestLogger(),
1940 Access: func() accessBitmap {
1941 var bits accessBitmap
1949 NewField(fieldData, []byte{
1950 0x00, 0x04, // field count
1952 0x00, 0x69, // fieldUserLogin = 105
1956 0x00, 0x6a, // fieldUserPassword = 106
1960 0x00, 0x66, // fieldUserName = 102
1964 0x00, 0x6e, // fieldUserAccess = 110
1966 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
1970 wantRes: []Transaction{
1974 Type: []byte{0, 0x00},
1975 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1976 ErrorCode: []byte{0, 0, 0, 1},
1978 NewField(fieldError, []byte("You are not allowed to create new accounts.")),
1982 wantErr: assert.NoError,
1985 name: "when action is modify user without required permission",
1988 logger: NewTestLogger(),
1990 Logger: NewTestLogger(),
1991 Accounts: map[string]*Account{
1996 Access: func() accessBitmap {
1997 var bits accessBitmap
2005 NewField(fieldData, []byte{
2006 0x00, 0x04, // field count
2008 0x00, 0x69, // fieldUserLogin = 105
2012 0x00, 0x6a, // fieldUserPassword = 106
2016 0x00, 0x66, // fieldUserName = 102
2020 0x00, 0x6e, // fieldUserAccess = 110
2022 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
2026 wantRes: []Transaction{
2030 Type: []byte{0, 0x00},
2031 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2032 ErrorCode: []byte{0, 0, 0, 1},
2034 NewField(fieldError, []byte("You are not allowed to modify accounts.")),
2038 wantErr: assert.NoError,
2041 name: "when action is delete user without required permission",
2044 logger: NewTestLogger(),
2046 Accounts: map[string]*Account{
2051 Access: func() accessBitmap {
2052 var bits accessBitmap
2060 NewField(fieldData, []byte{
2068 wantRes: []Transaction{
2072 Type: []byte{0, 0x00},
2073 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2074 ErrorCode: []byte{0, 0, 0, 1},
2076 NewField(fieldError, []byte("You are not allowed to delete accounts.")),
2080 wantErr: assert.NoError,
2083 for _, tt := range tests {
2084 t.Run(tt.name, func(t *testing.T) {
2085 gotRes, err := HandleUpdateUser(tt.args.cc, tt.args.t)
2086 if !tt.wantErr(t, err, fmt.Sprintf("HandleUpdateUser(%v, %v)", tt.args.cc, tt.args.t)) {
2090 tranAssertEqual(t, tt.wantRes, gotRes)
2095 func TestHandleDelNewsArt(t *testing.T) {
2103 wantRes []Transaction
2104 wantErr assert.ErrorAssertionFunc
2107 name: "without required permission",
2111 Access: func() accessBitmap {
2112 var bits accessBitmap
2122 wantRes: []Transaction{
2126 Type: []byte{0, 0x00},
2127 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2128 ErrorCode: []byte{0, 0, 0, 1},
2130 NewField(fieldError, []byte("You are not allowed to delete news articles.")),
2134 wantErr: assert.NoError,
2137 for _, tt := range tests {
2138 t.Run(tt.name, func(t *testing.T) {
2139 gotRes, err := HandleDelNewsArt(tt.args.cc, tt.args.t)
2140 if !tt.wantErr(t, err, fmt.Sprintf("HandleDelNewsArt(%v, %v)", tt.args.cc, tt.args.t)) {
2143 tranAssertEqual(t, tt.wantRes, gotRes)
2148 func TestHandleDisconnectUser(t *testing.T) {
2156 wantRes []Transaction
2157 wantErr assert.ErrorAssertionFunc
2160 name: "without required permission",
2164 Access: func() accessBitmap {
2165 var bits accessBitmap
2175 wantRes: []Transaction{
2179 Type: []byte{0, 0x00},
2180 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2181 ErrorCode: []byte{0, 0, 0, 1},
2183 NewField(fieldError, []byte("You are not allowed to disconnect users.")),
2187 wantErr: assert.NoError,
2190 name: "when target user has 'cannot be disconnected' priv",
2194 Clients: map[uint16]*ClientConn{
2198 Access: func() accessBitmap {
2199 var bits accessBitmap
2200 bits.Set(accessCannotBeDiscon)
2208 Access: func() accessBitmap {
2209 var bits accessBitmap
2210 bits.Set(accessDisconUser)
2218 NewField(fieldUserID, []byte{0, 1}),
2221 wantRes: []Transaction{
2225 Type: []byte{0, 0x00},
2226 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2227 ErrorCode: []byte{0, 0, 0, 1},
2229 NewField(fieldError, []byte("unnamed is not allowed to be disconnected.")),
2233 wantErr: assert.NoError,
2236 for _, tt := range tests {
2237 t.Run(tt.name, func(t *testing.T) {
2238 gotRes, err := HandleDisconnectUser(tt.args.cc, tt.args.t)
2239 if !tt.wantErr(t, err, fmt.Sprintf("HandleDisconnectUser(%v, %v)", tt.args.cc, tt.args.t)) {
2242 tranAssertEqual(t, tt.wantRes, gotRes)
2247 func TestHandleSendInstantMsg(t *testing.T) {
2255 wantRes []Transaction
2256 wantErr assert.ErrorAssertionFunc
2259 name: "without required permission",
2263 Access: func() accessBitmap {
2264 var bits accessBitmap
2274 wantRes: []Transaction{
2278 Type: []byte{0, 0x00},
2279 ID: []byte{0, 0, 0, 0},
2280 ErrorCode: []byte{0, 0, 0, 1},
2282 NewField(fieldError, []byte("You are not allowed to send private messages.")),
2286 wantErr: assert.NoError,
2289 name: "when client 1 sends a message to client 2",
2293 Access: func() accessBitmap {
2294 var bits accessBitmap
2295 bits.Set(accessSendPrivMsg)
2300 UserName: []byte("User1"),
2302 Clients: map[uint16]*ClientConn{
2304 AutoReply: []byte(nil),
2312 NewField(fieldData, []byte("hai")),
2313 NewField(fieldUserID, []byte{0, 2}),
2316 wantRes: []Transaction{
2320 NewField(fieldData, []byte("hai")),
2321 NewField(fieldUserName, []byte("User1")),
2322 NewField(fieldUserID, []byte{0, 1}),
2323 NewField(fieldOptions, []byte{0, 1}),
2326 clientID: &[]byte{0, 1},
2329 Type: []byte{0x0, 0x6c},
2330 ID: []byte{0, 0, 0, 0},
2331 ErrorCode: []byte{0, 0, 0, 0},
2332 Fields: []Field(nil),
2335 wantErr: assert.NoError,
2338 name: "when client 2 has autoreply enabled",
2342 Access: func() accessBitmap {
2343 var bits accessBitmap
2344 bits.Set(accessSendPrivMsg)
2349 UserName: []byte("User1"),
2351 Clients: map[uint16]*ClientConn{
2354 UserName: []byte("User2"),
2355 AutoReply: []byte("autohai"),
2363 NewField(fieldData, []byte("hai")),
2364 NewField(fieldUserID, []byte{0, 2}),
2367 wantRes: []Transaction{
2371 NewField(fieldData, []byte("hai")),
2372 NewField(fieldUserName, []byte("User1")),
2373 NewField(fieldUserID, []byte{0, 1}),
2374 NewField(fieldOptions, []byte{0, 1}),
2379 NewField(fieldData, []byte("autohai")),
2380 NewField(fieldUserName, []byte("User2")),
2381 NewField(fieldUserID, []byte{0, 2}),
2382 NewField(fieldOptions, []byte{0, 1}),
2385 clientID: &[]byte{0, 1},
2388 Type: []byte{0x0, 0x6c},
2389 ID: []byte{0, 0, 0, 0},
2390 ErrorCode: []byte{0, 0, 0, 0},
2391 Fields: []Field(nil),
2394 wantErr: assert.NoError,
2397 for _, tt := range tests {
2398 t.Run(tt.name, func(t *testing.T) {
2399 gotRes, err := HandleSendInstantMsg(tt.args.cc, tt.args.t)
2400 if !tt.wantErr(t, err, fmt.Sprintf("HandleSendInstantMsg(%v, %v)", tt.args.cc, tt.args.t)) {
2404 tranAssertEqual(t, tt.wantRes, gotRes)
2409 func TestHandleDeleteFile(t *testing.T) {
2417 wantRes []Transaction
2418 wantErr assert.ErrorAssertionFunc
2421 name: "when user does not have required permission to delete a folder",
2425 Access: func() accessBitmap {
2426 var bits accessBitmap
2432 FileRoot: func() string {
2433 return "/fakeRoot/Files"
2436 FS: func() *MockFileStore {
2437 mfi := &MockFileInfo{}
2438 mfi.On("Mode").Return(fs.FileMode(0))
2439 mfi.On("Size").Return(int64(100))
2440 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2441 mfi.On("IsDir").Return(false)
2442 mfi.On("Name").Return("testfile")
2444 mfs := &MockFileStore{}
2445 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2446 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2447 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2451 Accounts: map[string]*Account{},
2455 tranDeleteFile, &[]byte{0, 1},
2456 NewField(fieldFileName, []byte("testfile")),
2457 NewField(fieldFilePath, []byte{
2465 wantRes: []Transaction{
2469 Type: []byte{0, 0x00},
2470 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2471 ErrorCode: []byte{0, 0, 0, 1},
2473 NewField(fieldError, []byte("You are not allowed to delete files.")),
2477 wantErr: assert.NoError,
2480 name: "deletes all associated metadata files",
2484 Access: func() accessBitmap {
2485 var bits accessBitmap
2486 bits.Set(accessDeleteFile)
2492 FileRoot: func() string {
2493 return "/fakeRoot/Files"
2496 FS: func() *MockFileStore {
2497 mfi := &MockFileInfo{}
2498 mfi.On("Mode").Return(fs.FileMode(0))
2499 mfi.On("Size").Return(int64(100))
2500 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2501 mfi.On("IsDir").Return(false)
2502 mfi.On("Name").Return("testfile")
2504 mfs := &MockFileStore{}
2505 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2506 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2507 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2509 mfs.On("RemoveAll", "/fakeRoot/Files/aaa/testfile").Return(nil)
2510 mfs.On("Remove", "/fakeRoot/Files/aaa/testfile.incomplete").Return(nil)
2511 mfs.On("Remove", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil)
2512 mfs.On("Remove", "/fakeRoot/Files/aaa/.info_testfile").Return(nil)
2516 Accounts: map[string]*Account{},
2520 tranDeleteFile, &[]byte{0, 1},
2521 NewField(fieldFileName, []byte("testfile")),
2522 NewField(fieldFilePath, []byte{
2530 wantRes: []Transaction{
2534 Type: []byte{0x0, 0xcc},
2535 ID: []byte{0x0, 0x0, 0x0, 0x0},
2536 ErrorCode: []byte{0, 0, 0, 0},
2537 Fields: []Field(nil),
2540 wantErr: assert.NoError,
2543 for _, tt := range tests {
2544 t.Run(tt.name, func(t *testing.T) {
2545 gotRes, err := HandleDeleteFile(tt.args.cc, tt.args.t)
2546 if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteFile(%v, %v)", tt.args.cc, tt.args.t)) {
2550 tranAssertEqual(t, tt.wantRes, gotRes)
2552 tt.args.cc.Server.FS.(*MockFileStore).AssertExpectations(t)
2557 func TestHandleGetFileNameList(t *testing.T) {
2565 wantRes []Transaction
2566 wantErr assert.ErrorAssertionFunc
2569 name: "when fieldFilePath is a drop box, but user does not have accessViewDropBoxes ",
2573 Access: func() accessBitmap {
2574 var bits accessBitmap
2581 FileRoot: func() string {
2582 path, _ := os.Getwd()
2583 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2589 tranGetFileNameList, &[]byte{0, 1},
2590 NewField(fieldFilePath, []byte{
2594 0x64, 0x72, 0x6f, 0x70, 0x20, 0x62, 0x6f, 0x78, // "drop box"
2598 wantRes: []Transaction{
2602 Type: []byte{0, 0x00},
2603 ID: []byte{0, 0, 0, 0},
2604 ErrorCode: []byte{0, 0, 0, 1},
2606 NewField(fieldError, []byte("You are not allowed to view drop boxes.")),
2610 wantErr: assert.NoError,
2613 name: "with file root",
2618 FileRoot: func() string {
2619 path, _ := os.Getwd()
2620 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2626 tranGetFileNameList, &[]byte{0, 1},
2627 NewField(fieldFilePath, []byte{
2633 wantRes: []Transaction{
2637 Type: []byte{0, 0xc8},
2638 ID: []byte{0, 0, 0, 0},
2639 ErrorCode: []byte{0, 0, 0, 0},
2642 fieldFileNameWithInfo,
2644 fnwi := FileNameWithInfo{
2645 fileNameWithInfoHeader: fileNameWithInfoHeader{
2646 Type: [4]byte{0x54, 0x45, 0x58, 0x54},
2647 Creator: [4]byte{0x54, 0x54, 0x58, 0x54},
2648 FileSize: [4]byte{0, 0, 0x04, 0},
2650 NameScript: [2]byte{},
2651 NameSize: [2]byte{0, 0x0b},
2653 name: []byte("testfile-1k"),
2655 b, _ := fnwi.MarshalBinary()
2662 wantErr: assert.NoError,
2665 for _, tt := range tests {
2666 t.Run(tt.name, func(t *testing.T) {
2667 gotRes, err := HandleGetFileNameList(tt.args.cc, tt.args.t)
2668 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetFileNameList(%v, %v)", tt.args.cc, tt.args.t)) {
2672 tranAssertEqual(t, tt.wantRes, gotRes)
2677 func TestHandleGetClientInfoText(t *testing.T) {
2685 wantRes []Transaction
2686 wantErr assert.ErrorAssertionFunc
2689 name: "when user does not have required permission",
2693 Access: func() accessBitmap {
2694 var bits accessBitmap
2699 Accounts: map[string]*Account{},
2703 tranGetClientInfoText, &[]byte{0, 1},
2704 NewField(fieldUserID, []byte{0, 1}),
2707 wantRes: []Transaction{
2711 Type: []byte{0, 0x00},
2712 ID: []byte{0, 0, 0, 0},
2713 ErrorCode: []byte{0, 0, 0, 1},
2715 NewField(fieldError, []byte("You are not allowed to get client info.")),
2719 wantErr: assert.NoError,
2722 name: "with a valid user",
2725 UserName: []byte("Testy McTest"),
2726 RemoteAddr: "1.2.3.4:12345",
2728 Access: func() accessBitmap {
2729 var bits accessBitmap
2730 bits.Set(accessGetClientInfo)
2737 Accounts: map[string]*Account{},
2738 Clients: map[uint16]*ClientConn{
2740 UserName: []byte("Testy McTest"),
2741 RemoteAddr: "1.2.3.4:12345",
2743 Access: func() accessBitmap {
2744 var bits accessBitmap
2745 bits.Set(accessGetClientInfo)
2754 transfers: map[int]map[[4]byte]*FileTransfer{
2762 tranGetClientInfoText, &[]byte{0, 1},
2763 NewField(fieldUserID, []byte{0, 1}),
2766 wantRes: []Transaction{
2770 Type: []byte{0x1, 0x2f},
2771 ID: []byte{0, 0, 0, 0},
2772 ErrorCode: []byte{0, 0, 0, 0},
2774 NewField(fieldData, []byte(
2775 strings.Replace(`Nickname: Testy McTest
2778 Address: 1.2.3.4:12345
2780 -------- File Downloads ---------
2784 ------- Folder Downloads --------
2788 --------- File Uploads ----------
2792 -------- Folder Uploads ---------
2796 ------- Waiting Downloads -------
2800 `, "\n", "\r", -1)),
2802 NewField(fieldUserName, []byte("Testy McTest")),
2806 wantErr: assert.NoError,
2809 for _, tt := range tests {
2810 t.Run(tt.name, func(t *testing.T) {
2811 gotRes, err := HandleGetClientInfoText(tt.args.cc, tt.args.t)
2812 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetClientInfoText(%v, %v)", tt.args.cc, tt.args.t)) {
2815 tranAssertEqual(t, tt.wantRes, gotRes)
2820 func TestHandleTranAgreed(t *testing.T) {
2828 wantRes []Transaction
2829 wantErr assert.ErrorAssertionFunc
2832 name: "normal request flow",
2836 Access: func() accessBitmap {
2837 var bits accessBitmap
2838 bits.Set(accessDisconUser)
2839 bits.Set(accessAnyName)
2843 Flags: []byte{0, 1},
2844 Version: []byte{0, 1},
2846 logger: NewTestLogger(),
2849 BannerFile: "banner.jpg",
2855 NewField(fieldUserName, []byte("username")),
2856 NewField(fieldUserIconID, []byte{0, 1}),
2857 NewField(fieldOptions, []byte{0, 0}),
2860 wantRes: []Transaction{
2862 clientID: &[]byte{0, 1},
2865 Type: []byte{0, 0x7a},
2866 ID: []byte{0, 0, 0, 0},
2867 ErrorCode: []byte{0, 0, 0, 0},
2869 NewField(fieldBannerType, []byte("JPEG")),
2873 clientID: &[]byte{0, 1},
2876 Type: []byte{0, 0x79},
2877 ID: []byte{0, 0, 0, 0},
2878 ErrorCode: []byte{0, 0, 0, 0},
2882 wantErr: assert.NoError,
2885 for _, tt := range tests {
2886 t.Run(tt.name, func(t *testing.T) {
2887 gotRes, err := HandleTranAgreed(tt.args.cc, tt.args.t)
2888 if !tt.wantErr(t, err, fmt.Sprintf("HandleTranAgreed(%v, %v)", tt.args.cc, tt.args.t)) {
2891 tranAssertEqual(t, tt.wantRes, gotRes)
2896 func TestHandleSetClientUserInfo(t *testing.T) {
2904 wantRes []Transaction
2905 wantErr assert.ErrorAssertionFunc
2908 name: "when client does not have accessAnyName",
2912 Access: func() accessBitmap {
2913 var bits accessBitmap
2918 UserName: []byte("Guest"),
2919 Flags: []byte{0, 1},
2921 Clients: map[uint16]*ClientConn{
2929 tranSetClientUserInfo, nil,
2930 NewField(fieldUserIconID, []byte{0, 1}),
2931 NewField(fieldUserName, []byte("NOPE")),
2934 wantRes: []Transaction{
2936 clientID: &[]byte{0, 1},
2939 Type: []byte{0x01, 0x2d},
2940 ID: []byte{0, 0, 0, 0},
2941 ErrorCode: []byte{0, 0, 0, 0},
2943 NewField(fieldUserID, []byte{0, 1}),
2944 NewField(fieldUserIconID, []byte{0, 1}),
2945 NewField(fieldUserFlags, []byte{0, 1}),
2946 NewField(fieldUserName, []byte("Guest"))},
2949 wantErr: assert.NoError,
2952 for _, tt := range tests {
2953 t.Run(tt.name, func(t *testing.T) {
2954 gotRes, err := HandleSetClientUserInfo(tt.args.cc, tt.args.t)
2955 if !tt.wantErr(t, err, fmt.Sprintf("HandleSetClientUserInfo(%v, %v)", tt.args.cc, tt.args.t)) {
2959 tranAssertEqual(t, tt.wantRes, gotRes)
2964 func TestHandleDelNewsItem(t *testing.T) {
2972 wantRes []Transaction
2973 wantErr assert.ErrorAssertionFunc
2976 name: "when user does not have permission to delete a news category",
2980 Access: accessBitmap{},
2984 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
2995 tranDelNewsItem, nil,
2996 NewField(fieldNewsPath,
3001 0x74, 0x65, 0x73, 0x74,
3006 wantRes: []Transaction{
3008 clientID: &[]byte{0, 1},
3011 Type: []byte{0, 0x00},
3012 ID: []byte{0, 0, 0, 0},
3013 ErrorCode: []byte{0, 0, 0, 1},
3015 NewField(fieldError, []byte("You are not allowed to delete news categories.")),
3019 wantErr: assert.NoError,
3022 name: "when user does not have permission to delete a news folder",
3026 Access: accessBitmap{},
3030 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3041 tranDelNewsItem, nil,
3042 NewField(fieldNewsPath,
3047 0x74, 0x65, 0x73, 0x74,
3052 wantRes: []Transaction{
3054 clientID: &[]byte{0, 1},
3057 Type: []byte{0, 0x00},
3058 ID: []byte{0, 0, 0, 0},
3059 ErrorCode: []byte{0, 0, 0, 1},
3061 NewField(fieldError, []byte("You are not allowed to delete news folders.")),
3065 wantErr: assert.NoError,
3068 name: "when user deletes a news folder",
3072 Access: func() accessBitmap {
3073 var bits accessBitmap
3074 bits.Set(accessNewsDeleteFldr)
3080 ConfigDir: "/fakeConfigRoot",
3081 FS: func() *MockFileStore {
3082 mfs := &MockFileStore{}
3083 mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
3086 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3097 tranDelNewsItem, nil,
3098 NewField(fieldNewsPath,
3103 0x74, 0x65, 0x73, 0x74,
3108 wantRes: []Transaction{
3110 clientID: &[]byte{0, 1},
3113 Type: []byte{0x01, 0x7c},
3114 ID: []byte{0, 0, 0, 0},
3115 ErrorCode: []byte{0, 0, 0, 0},
3119 wantErr: assert.NoError,
3122 for _, tt := range tests {
3123 t.Run(tt.name, func(t *testing.T) {
3124 gotRes, err := HandleDelNewsItem(tt.args.cc, tt.args.t)
3125 if !tt.wantErr(t, err, fmt.Sprintf("HandleDelNewsItem(%v, %v)", tt.args.cc, tt.args.t)) {
3128 tranAssertEqual(t, tt.wantRes, gotRes)