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 name: "when user attempts to create account with greater access",
1621 Access: func() accessBitmap {
1622 var bits accessBitmap
1623 bits.Set(accessCreateUser)
1628 Accounts: map[string]*Account{},
1632 tranNewUser, &[]byte{0, 1},
1633 NewField(fieldUserLogin, []byte("userB")),
1637 var bits accessBitmap
1638 bits.Set(accessDisconUser)
1644 wantRes: []Transaction{
1648 Type: []byte{0, 0x00},
1649 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1650 ErrorCode: []byte{0, 0, 0, 1},
1652 NewField(fieldError, []byte("Cannot create account with more access than yourself.")),
1656 wantErr: assert.NoError,
1659 for _, tt := range tests {
1660 t.Run(tt.name, func(t *testing.T) {
1661 gotRes, err := HandleNewUser(tt.args.cc, tt.args.t)
1662 if !tt.wantErr(t, err, fmt.Sprintf("HandleNewUser(%v, %v)", tt.args.cc, tt.args.t)) {
1666 tranAssertEqual(t, tt.wantRes, gotRes)
1671 func TestHandleListUsers(t *testing.T) {
1679 wantRes []Transaction
1680 wantErr assert.ErrorAssertionFunc
1683 name: "when user does not have required permission",
1687 Access: func() accessBitmap {
1688 var bits accessBitmap
1693 Accounts: map[string]*Account{},
1697 tranNewUser, &[]byte{0, 1},
1700 wantRes: []Transaction{
1704 Type: []byte{0, 0x00},
1705 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1706 ErrorCode: []byte{0, 0, 0, 1},
1708 NewField(fieldError, []byte("You are not allowed to view accounts.")),
1712 wantErr: assert.NoError,
1715 name: "when user has required permission",
1719 Access: func() accessBitmap {
1720 var bits accessBitmap
1721 bits.Set(accessOpenUser)
1726 Accounts: map[string]*Account{
1731 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
1737 tranGetClientInfoText, &[]byte{0, 1},
1738 NewField(fieldUserID, []byte{0, 1}),
1741 wantRes: []Transaction{
1745 Type: []byte{0x01, 0x2f},
1746 ID: []byte{0, 0, 0, 0},
1747 ErrorCode: []byte{0, 0, 0, 0},
1749 NewField(fieldData, []byte{
1750 0x00, 0x04, 0x00, 0x66, 0x00, 0x05, 0x67, 0x75, 0x65, 0x73, 0x74, 0x00, 0x69, 0x00, 0x05, 0x98,
1751 0x8a, 0x9a, 0x8c, 0x8b, 0x00, 0x6e, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1752 0x00, 0x6a, 0x00, 0x01, 0x78,
1757 wantErr: assert.NoError,
1760 for _, tt := range tests {
1761 t.Run(tt.name, func(t *testing.T) {
1762 gotRes, err := HandleListUsers(tt.args.cc, tt.args.t)
1763 if !tt.wantErr(t, err, fmt.Sprintf("HandleListUsers(%v, %v)", tt.args.cc, tt.args.t)) {
1767 tranAssertEqual(t, tt.wantRes, gotRes)
1772 func TestHandleDownloadFile(t *testing.T) {
1780 wantRes []Transaction
1781 wantErr assert.ErrorAssertionFunc
1784 name: "when user does not have required permission",
1788 Access: func() accessBitmap {
1789 var bits accessBitmap
1795 t: NewTransaction(tranDownloadFile, &[]byte{0, 1}),
1797 wantRes: []Transaction{
1801 Type: []byte{0, 0x00},
1802 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1803 ErrorCode: []byte{0, 0, 0, 1},
1805 NewField(fieldError, []byte("You are not allowed to download files.")),
1809 wantErr: assert.NoError,
1812 name: "with a valid file",
1815 transfers: map[int]map[[4]byte]*FileTransfer{
1819 Access: func() accessBitmap {
1820 var bits accessBitmap
1821 bits.Set(accessDownloadFile)
1827 fileTransfers: map[[4]byte]*FileTransfer{},
1829 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1831 Accounts: map[string]*Account{},
1837 NewField(fieldFileName, []byte("testfile.txt")),
1838 NewField(fieldFilePath, []byte{0x0, 0x00}),
1841 wantRes: []Transaction{
1845 Type: []byte{0, 0x2},
1846 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1847 ErrorCode: []byte{0, 0, 0, 0},
1849 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1850 NewField(fieldWaitingCount, []byte{0x00, 0x00}),
1851 NewField(fieldTransferSize, []byte{0x00, 0x00, 0x00, 0xa5}),
1852 NewField(fieldFileSize, []byte{0x00, 0x00, 0x00, 0x17}),
1856 wantErr: assert.NoError,
1859 name: "when client requests to resume 1k test file at offset 256",
1862 transfers: map[int]map[[4]byte]*FileTransfer{
1864 }, Account: &Account{
1865 Access: func() accessBitmap {
1866 var bits accessBitmap
1867 bits.Set(accessDownloadFile)
1874 // FS: func() *MockFileStore {
1875 // path, _ := os.Getwd()
1876 // testFile, err := os.Open(path + "/test/config/Files/testfile-1k")
1881 // mfi := &MockFileInfo{}
1882 // mfi.On("Mode").Return(fs.FileMode(0))
1883 // mfs := &MockFileStore{}
1884 // mfs.On("Stat", "/fakeRoot/Files/testfile.txt").Return(mfi, nil)
1885 // mfs.On("Open", "/fakeRoot/Files/testfile.txt").Return(testFile, nil)
1886 // mfs.On("Stat", "/fakeRoot/Files/.info_testfile.txt").Return(nil, errors.New("no"))
1887 // mfs.On("Stat", "/fakeRoot/Files/.rsrc_testfile.txt").Return(nil, errors.New("no"))
1891 fileTransfers: map[[4]byte]*FileTransfer{},
1893 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1895 Accounts: map[string]*Account{},
1901 NewField(fieldFileName, []byte("testfile-1k")),
1902 NewField(fieldFilePath, []byte{0x00, 0x00}),
1904 fieldFileResumeData,
1906 frd := FileResumeData{
1910 ForkCount: [2]byte{0, 2},
1911 ForkInfoList: []ForkInfoList{
1913 Fork: [4]byte{0x44, 0x41, 0x54, 0x41}, // "DATA"
1914 DataSize: [4]byte{0, 0, 0x01, 0x00}, // request offset 256
1919 Fork: [4]byte{0x4d, 0x41, 0x43, 0x52}, // "MACR"
1920 DataSize: [4]byte{0, 0, 0, 0},
1926 b, _ := frd.BinaryMarshal()
1932 wantRes: []Transaction{
1936 Type: []byte{0, 0x2},
1937 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
1938 ErrorCode: []byte{0, 0, 0, 0},
1940 NewField(fieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1941 NewField(fieldWaitingCount, []byte{0x00, 0x00}),
1942 NewField(fieldTransferSize, []byte{0x00, 0x00, 0x03, 0x8d}),
1943 NewField(fieldFileSize, []byte{0x00, 0x00, 0x03, 0x00}),
1947 wantErr: assert.NoError,
1950 for _, tt := range tests {
1951 t.Run(tt.name, func(t *testing.T) {
1952 gotRes, err := HandleDownloadFile(tt.args.cc, tt.args.t)
1953 if !tt.wantErr(t, err, fmt.Sprintf("HandleDownloadFile(%v, %v)", tt.args.cc, tt.args.t)) {
1957 tranAssertEqual(t, tt.wantRes, gotRes)
1962 func TestHandleUpdateUser(t *testing.T) {
1970 wantRes []Transaction
1971 wantErr assert.ErrorAssertionFunc
1974 name: "when action is create user without required permission",
1977 logger: NewTestLogger(),
1979 Logger: NewTestLogger(),
1982 Access: func() accessBitmap {
1983 var bits accessBitmap
1991 NewField(fieldData, []byte{
1992 0x00, 0x04, // field count
1994 0x00, 0x69, // fieldUserLogin = 105
1998 0x00, 0x6a, // fieldUserPassword = 106
2002 0x00, 0x66, // fieldUserName = 102
2006 0x00, 0x6e, // fieldUserAccess = 110
2008 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
2012 wantRes: []Transaction{
2016 Type: []byte{0, 0x00},
2017 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2018 ErrorCode: []byte{0, 0, 0, 1},
2020 NewField(fieldError, []byte("You are not allowed to create new accounts.")),
2024 wantErr: assert.NoError,
2027 name: "when action is modify user without required permission",
2030 logger: NewTestLogger(),
2032 Logger: NewTestLogger(),
2033 Accounts: map[string]*Account{
2038 Access: func() accessBitmap {
2039 var bits accessBitmap
2047 NewField(fieldData, []byte{
2048 0x00, 0x04, // field count
2050 0x00, 0x69, // fieldUserLogin = 105
2054 0x00, 0x6a, // fieldUserPassword = 106
2058 0x00, 0x66, // fieldUserName = 102
2062 0x00, 0x6e, // fieldUserAccess = 110
2064 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
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 modify accounts.")),
2080 wantErr: assert.NoError,
2083 name: "when action is delete user without required permission",
2086 logger: NewTestLogger(),
2088 Accounts: map[string]*Account{
2093 Access: func() accessBitmap {
2094 var bits accessBitmap
2102 NewField(fieldData, []byte{
2110 wantRes: []Transaction{
2114 Type: []byte{0, 0x00},
2115 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2116 ErrorCode: []byte{0, 0, 0, 1},
2118 NewField(fieldError, []byte("You are not allowed to delete accounts.")),
2122 wantErr: assert.NoError,
2125 for _, tt := range tests {
2126 t.Run(tt.name, func(t *testing.T) {
2127 gotRes, err := HandleUpdateUser(tt.args.cc, tt.args.t)
2128 if !tt.wantErr(t, err, fmt.Sprintf("HandleUpdateUser(%v, %v)", tt.args.cc, tt.args.t)) {
2132 tranAssertEqual(t, tt.wantRes, gotRes)
2137 func TestHandleDelNewsArt(t *testing.T) {
2145 wantRes []Transaction
2146 wantErr assert.ErrorAssertionFunc
2149 name: "without required permission",
2153 Access: func() accessBitmap {
2154 var bits accessBitmap
2164 wantRes: []Transaction{
2168 Type: []byte{0, 0x00},
2169 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2170 ErrorCode: []byte{0, 0, 0, 1},
2172 NewField(fieldError, []byte("You are not allowed to delete news articles.")),
2176 wantErr: assert.NoError,
2179 for _, tt := range tests {
2180 t.Run(tt.name, func(t *testing.T) {
2181 gotRes, err := HandleDelNewsArt(tt.args.cc, tt.args.t)
2182 if !tt.wantErr(t, err, fmt.Sprintf("HandleDelNewsArt(%v, %v)", tt.args.cc, tt.args.t)) {
2185 tranAssertEqual(t, tt.wantRes, gotRes)
2190 func TestHandleDisconnectUser(t *testing.T) {
2198 wantRes []Transaction
2199 wantErr assert.ErrorAssertionFunc
2202 name: "without required permission",
2206 Access: func() accessBitmap {
2207 var bits accessBitmap
2217 wantRes: []Transaction{
2221 Type: []byte{0, 0x00},
2222 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2223 ErrorCode: []byte{0, 0, 0, 1},
2225 NewField(fieldError, []byte("You are not allowed to disconnect users.")),
2229 wantErr: assert.NoError,
2232 name: "when target user has 'cannot be disconnected' priv",
2236 Clients: map[uint16]*ClientConn{
2240 Access: func() accessBitmap {
2241 var bits accessBitmap
2242 bits.Set(accessCannotBeDiscon)
2250 Access: func() accessBitmap {
2251 var bits accessBitmap
2252 bits.Set(accessDisconUser)
2260 NewField(fieldUserID, []byte{0, 1}),
2263 wantRes: []Transaction{
2267 Type: []byte{0, 0x00},
2268 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2269 ErrorCode: []byte{0, 0, 0, 1},
2271 NewField(fieldError, []byte("unnamed is not allowed to be disconnected.")),
2275 wantErr: assert.NoError,
2278 for _, tt := range tests {
2279 t.Run(tt.name, func(t *testing.T) {
2280 gotRes, err := HandleDisconnectUser(tt.args.cc, tt.args.t)
2281 if !tt.wantErr(t, err, fmt.Sprintf("HandleDisconnectUser(%v, %v)", tt.args.cc, tt.args.t)) {
2284 tranAssertEqual(t, tt.wantRes, gotRes)
2289 func TestHandleSendInstantMsg(t *testing.T) {
2297 wantRes []Transaction
2298 wantErr assert.ErrorAssertionFunc
2301 name: "without required permission",
2305 Access: func() accessBitmap {
2306 var bits accessBitmap
2316 wantRes: []Transaction{
2320 Type: []byte{0, 0x00},
2321 ID: []byte{0, 0, 0, 0},
2322 ErrorCode: []byte{0, 0, 0, 1},
2324 NewField(fieldError, []byte("You are not allowed to send private messages.")),
2328 wantErr: assert.NoError,
2331 name: "when client 1 sends a message to client 2",
2335 Access: func() accessBitmap {
2336 var bits accessBitmap
2337 bits.Set(accessSendPrivMsg)
2342 UserName: []byte("User1"),
2344 Clients: map[uint16]*ClientConn{
2346 AutoReply: []byte(nil),
2347 Flags: []byte{0, 0},
2355 NewField(fieldData, []byte("hai")),
2356 NewField(fieldUserID, []byte{0, 2}),
2359 wantRes: []Transaction{
2363 NewField(fieldData, []byte("hai")),
2364 NewField(fieldUserName, []byte("User1")),
2365 NewField(fieldUserID, []byte{0, 1}),
2366 NewField(fieldOptions, []byte{0, 1}),
2369 clientID: &[]byte{0, 1},
2372 Type: []byte{0x0, 0x6c},
2373 ID: []byte{0, 0, 0, 0},
2374 ErrorCode: []byte{0, 0, 0, 0},
2375 Fields: []Field(nil),
2378 wantErr: assert.NoError,
2381 name: "when client 2 has autoreply enabled",
2385 Access: func() accessBitmap {
2386 var bits accessBitmap
2387 bits.Set(accessSendPrivMsg)
2392 UserName: []byte("User1"),
2394 Clients: map[uint16]*ClientConn{
2396 Flags: []byte{0, 0},
2398 UserName: []byte("User2"),
2399 AutoReply: []byte("autohai"),
2407 NewField(fieldData, []byte("hai")),
2408 NewField(fieldUserID, []byte{0, 2}),
2411 wantRes: []Transaction{
2415 NewField(fieldData, []byte("hai")),
2416 NewField(fieldUserName, []byte("User1")),
2417 NewField(fieldUserID, []byte{0, 1}),
2418 NewField(fieldOptions, []byte{0, 1}),
2423 NewField(fieldData, []byte("autohai")),
2424 NewField(fieldUserName, []byte("User2")),
2425 NewField(fieldUserID, []byte{0, 2}),
2426 NewField(fieldOptions, []byte{0, 1}),
2429 clientID: &[]byte{0, 1},
2432 Type: []byte{0x0, 0x6c},
2433 ID: []byte{0, 0, 0, 0},
2434 ErrorCode: []byte{0, 0, 0, 0},
2435 Fields: []Field(nil),
2438 wantErr: assert.NoError,
2441 name: "when client 2 has refuse private messages enabled",
2445 Access: func() accessBitmap {
2446 var bits accessBitmap
2447 bits.Set(accessSendPrivMsg)
2452 UserName: []byte("User1"),
2454 Clients: map[uint16]*ClientConn{
2456 Flags: []byte{255, 255},
2458 UserName: []byte("User2"),
2466 NewField(fieldData, []byte("hai")),
2467 NewField(fieldUserID, []byte{0, 2}),
2470 wantRes: []Transaction{
2474 NewField(fieldData, []byte("User2 does not accept private messages.")),
2475 NewField(fieldUserName, []byte("User2")),
2476 NewField(fieldUserID, []byte{0, 2}),
2477 NewField(fieldOptions, []byte{0, 2}),
2480 clientID: &[]byte{0, 1},
2483 Type: []byte{0x0, 0x6c},
2484 ID: []byte{0, 0, 0, 0},
2485 ErrorCode: []byte{0, 0, 0, 0},
2486 Fields: []Field(nil),
2489 wantErr: assert.NoError,
2492 for _, tt := range tests {
2493 t.Run(tt.name, func(t *testing.T) {
2494 gotRes, err := HandleSendInstantMsg(tt.args.cc, tt.args.t)
2495 if !tt.wantErr(t, err, fmt.Sprintf("HandleSendInstantMsg(%v, %v)", tt.args.cc, tt.args.t)) {
2499 tranAssertEqual(t, tt.wantRes, gotRes)
2504 func TestHandleDeleteFile(t *testing.T) {
2512 wantRes []Transaction
2513 wantErr assert.ErrorAssertionFunc
2516 name: "when user does not have required permission to delete a folder",
2520 Access: func() accessBitmap {
2521 var bits accessBitmap
2527 FileRoot: func() string {
2528 return "/fakeRoot/Files"
2531 FS: func() *MockFileStore {
2532 mfi := &MockFileInfo{}
2533 mfi.On("Mode").Return(fs.FileMode(0))
2534 mfi.On("Size").Return(int64(100))
2535 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2536 mfi.On("IsDir").Return(false)
2537 mfi.On("Name").Return("testfile")
2539 mfs := &MockFileStore{}
2540 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2541 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2542 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2546 Accounts: map[string]*Account{},
2550 tranDeleteFile, &[]byte{0, 1},
2551 NewField(fieldFileName, []byte("testfile")),
2552 NewField(fieldFilePath, []byte{
2560 wantRes: []Transaction{
2564 Type: []byte{0, 0x00},
2565 ID: []byte{0x9a, 0xcb, 0x04, 0x42},
2566 ErrorCode: []byte{0, 0, 0, 1},
2568 NewField(fieldError, []byte("You are not allowed to delete files.")),
2572 wantErr: assert.NoError,
2575 name: "deletes all associated metadata files",
2579 Access: func() accessBitmap {
2580 var bits accessBitmap
2581 bits.Set(accessDeleteFile)
2587 FileRoot: func() string {
2588 return "/fakeRoot/Files"
2591 FS: func() *MockFileStore {
2592 mfi := &MockFileInfo{}
2593 mfi.On("Mode").Return(fs.FileMode(0))
2594 mfi.On("Size").Return(int64(100))
2595 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2596 mfi.On("IsDir").Return(false)
2597 mfi.On("Name").Return("testfile")
2599 mfs := &MockFileStore{}
2600 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2601 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2602 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2604 mfs.On("RemoveAll", "/fakeRoot/Files/aaa/testfile").Return(nil)
2605 mfs.On("Remove", "/fakeRoot/Files/aaa/testfile.incomplete").Return(nil)
2606 mfs.On("Remove", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil)
2607 mfs.On("Remove", "/fakeRoot/Files/aaa/.info_testfile").Return(nil)
2611 Accounts: map[string]*Account{},
2615 tranDeleteFile, &[]byte{0, 1},
2616 NewField(fieldFileName, []byte("testfile")),
2617 NewField(fieldFilePath, []byte{
2625 wantRes: []Transaction{
2629 Type: []byte{0x0, 0xcc},
2630 ID: []byte{0x0, 0x0, 0x0, 0x0},
2631 ErrorCode: []byte{0, 0, 0, 0},
2632 Fields: []Field(nil),
2635 wantErr: assert.NoError,
2638 for _, tt := range tests {
2639 t.Run(tt.name, func(t *testing.T) {
2640 gotRes, err := HandleDeleteFile(tt.args.cc, tt.args.t)
2641 if !tt.wantErr(t, err, fmt.Sprintf("HandleDeleteFile(%v, %v)", tt.args.cc, tt.args.t)) {
2645 tranAssertEqual(t, tt.wantRes, gotRes)
2647 tt.args.cc.Server.FS.(*MockFileStore).AssertExpectations(t)
2652 func TestHandleGetFileNameList(t *testing.T) {
2660 wantRes []Transaction
2661 wantErr assert.ErrorAssertionFunc
2664 name: "when fieldFilePath is a drop box, but user does not have accessViewDropBoxes ",
2668 Access: func() accessBitmap {
2669 var bits accessBitmap
2676 FileRoot: func() string {
2677 path, _ := os.Getwd()
2678 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2684 tranGetFileNameList, &[]byte{0, 1},
2685 NewField(fieldFilePath, []byte{
2689 0x64, 0x72, 0x6f, 0x70, 0x20, 0x62, 0x6f, 0x78, // "drop box"
2693 wantRes: []Transaction{
2697 Type: []byte{0, 0x00},
2698 ID: []byte{0, 0, 0, 0},
2699 ErrorCode: []byte{0, 0, 0, 1},
2701 NewField(fieldError, []byte("You are not allowed to view drop boxes.")),
2705 wantErr: assert.NoError,
2708 name: "with file root",
2713 FileRoot: func() string {
2714 path, _ := os.Getwd()
2715 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2721 tranGetFileNameList, &[]byte{0, 1},
2722 NewField(fieldFilePath, []byte{
2728 wantRes: []Transaction{
2732 Type: []byte{0, 0xc8},
2733 ID: []byte{0, 0, 0, 0},
2734 ErrorCode: []byte{0, 0, 0, 0},
2737 fieldFileNameWithInfo,
2739 fnwi := FileNameWithInfo{
2740 fileNameWithInfoHeader: fileNameWithInfoHeader{
2741 Type: [4]byte{0x54, 0x45, 0x58, 0x54},
2742 Creator: [4]byte{0x54, 0x54, 0x58, 0x54},
2743 FileSize: [4]byte{0, 0, 0x04, 0},
2745 NameScript: [2]byte{},
2746 NameSize: [2]byte{0, 0x0b},
2748 name: []byte("testfile-1k"),
2750 b, _ := fnwi.MarshalBinary()
2757 wantErr: assert.NoError,
2760 for _, tt := range tests {
2761 t.Run(tt.name, func(t *testing.T) {
2762 gotRes, err := HandleGetFileNameList(tt.args.cc, tt.args.t)
2763 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetFileNameList(%v, %v)", tt.args.cc, tt.args.t)) {
2767 tranAssertEqual(t, tt.wantRes, gotRes)
2772 func TestHandleGetClientInfoText(t *testing.T) {
2780 wantRes []Transaction
2781 wantErr assert.ErrorAssertionFunc
2784 name: "when user does not have required permission",
2788 Access: func() accessBitmap {
2789 var bits accessBitmap
2794 Accounts: map[string]*Account{},
2798 tranGetClientInfoText, &[]byte{0, 1},
2799 NewField(fieldUserID, []byte{0, 1}),
2802 wantRes: []Transaction{
2806 Type: []byte{0, 0x00},
2807 ID: []byte{0, 0, 0, 0},
2808 ErrorCode: []byte{0, 0, 0, 1},
2810 NewField(fieldError, []byte("You are not allowed to get client info.")),
2814 wantErr: assert.NoError,
2817 name: "with a valid user",
2820 UserName: []byte("Testy McTest"),
2821 RemoteAddr: "1.2.3.4:12345",
2823 Access: func() accessBitmap {
2824 var bits accessBitmap
2825 bits.Set(accessGetClientInfo)
2832 Accounts: map[string]*Account{},
2833 Clients: map[uint16]*ClientConn{
2835 UserName: []byte("Testy McTest"),
2836 RemoteAddr: "1.2.3.4:12345",
2838 Access: func() accessBitmap {
2839 var bits accessBitmap
2840 bits.Set(accessGetClientInfo)
2849 transfers: map[int]map[[4]byte]*FileTransfer{
2857 tranGetClientInfoText, &[]byte{0, 1},
2858 NewField(fieldUserID, []byte{0, 1}),
2861 wantRes: []Transaction{
2865 Type: []byte{0x1, 0x2f},
2866 ID: []byte{0, 0, 0, 0},
2867 ErrorCode: []byte{0, 0, 0, 0},
2869 NewField(fieldData, []byte(
2870 strings.Replace(`Nickname: Testy McTest
2873 Address: 1.2.3.4:12345
2875 -------- File Downloads ---------
2879 ------- Folder Downloads --------
2883 --------- File Uploads ----------
2887 -------- Folder Uploads ---------
2891 ------- Waiting Downloads -------
2895 `, "\n", "\r", -1)),
2897 NewField(fieldUserName, []byte("Testy McTest")),
2901 wantErr: assert.NoError,
2904 for _, tt := range tests {
2905 t.Run(tt.name, func(t *testing.T) {
2906 gotRes, err := HandleGetClientInfoText(tt.args.cc, tt.args.t)
2907 if !tt.wantErr(t, err, fmt.Sprintf("HandleGetClientInfoText(%v, %v)", tt.args.cc, tt.args.t)) {
2910 tranAssertEqual(t, tt.wantRes, gotRes)
2915 func TestHandleTranAgreed(t *testing.T) {
2923 wantRes []Transaction
2924 wantErr assert.ErrorAssertionFunc
2927 name: "normal request flow",
2931 Access: func() accessBitmap {
2932 var bits accessBitmap
2933 bits.Set(accessDisconUser)
2934 bits.Set(accessAnyName)
2938 Flags: []byte{0, 1},
2939 Version: []byte{0, 1},
2941 logger: NewTestLogger(),
2944 BannerFile: "banner.jpg",
2950 NewField(fieldUserName, []byte("username")),
2951 NewField(fieldUserIconID, []byte{0, 1}),
2952 NewField(fieldOptions, []byte{0, 0}),
2955 wantRes: []Transaction{
2957 clientID: &[]byte{0, 1},
2960 Type: []byte{0, 0x7a},
2961 ID: []byte{0, 0, 0, 0},
2962 ErrorCode: []byte{0, 0, 0, 0},
2964 NewField(fieldBannerType, []byte("JPEG")),
2968 clientID: &[]byte{0, 1},
2971 Type: []byte{0, 0x79},
2972 ID: []byte{0, 0, 0, 0},
2973 ErrorCode: []byte{0, 0, 0, 0},
2977 wantErr: assert.NoError,
2980 for _, tt := range tests {
2981 t.Run(tt.name, func(t *testing.T) {
2982 gotRes, err := HandleTranAgreed(tt.args.cc, tt.args.t)
2983 if !tt.wantErr(t, err, fmt.Sprintf("HandleTranAgreed(%v, %v)", tt.args.cc, tt.args.t)) {
2986 tranAssertEqual(t, tt.wantRes, gotRes)
2991 func TestHandleSetClientUserInfo(t *testing.T) {
2999 wantRes []Transaction
3000 wantErr assert.ErrorAssertionFunc
3003 name: "when client does not have accessAnyName",
3007 Access: func() accessBitmap {
3008 var bits accessBitmap
3013 UserName: []byte("Guest"),
3014 Flags: []byte{0, 1},
3016 Clients: map[uint16]*ClientConn{
3024 tranSetClientUserInfo, nil,
3025 NewField(fieldUserIconID, []byte{0, 1}),
3026 NewField(fieldUserName, []byte("NOPE")),
3029 wantRes: []Transaction{
3031 clientID: &[]byte{0, 1},
3034 Type: []byte{0x01, 0x2d},
3035 ID: []byte{0, 0, 0, 0},
3036 ErrorCode: []byte{0, 0, 0, 0},
3038 NewField(fieldUserID, []byte{0, 1}),
3039 NewField(fieldUserIconID, []byte{0, 1}),
3040 NewField(fieldUserFlags, []byte{0, 1}),
3041 NewField(fieldUserName, []byte("Guest"))},
3044 wantErr: assert.NoError,
3047 for _, tt := range tests {
3048 t.Run(tt.name, func(t *testing.T) {
3049 gotRes, err := HandleSetClientUserInfo(tt.args.cc, tt.args.t)
3050 if !tt.wantErr(t, err, fmt.Sprintf("HandleSetClientUserInfo(%v, %v)", tt.args.cc, tt.args.t)) {
3054 tranAssertEqual(t, tt.wantRes, gotRes)
3059 func TestHandleDelNewsItem(t *testing.T) {
3067 wantRes []Transaction
3068 wantErr assert.ErrorAssertionFunc
3071 name: "when user does not have permission to delete a news category",
3075 Access: accessBitmap{},
3079 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3090 tranDelNewsItem, nil,
3091 NewField(fieldNewsPath,
3096 0x74, 0x65, 0x73, 0x74,
3101 wantRes: []Transaction{
3103 clientID: &[]byte{0, 1},
3106 Type: []byte{0, 0x00},
3107 ID: []byte{0, 0, 0, 0},
3108 ErrorCode: []byte{0, 0, 0, 1},
3110 NewField(fieldError, []byte("You are not allowed to delete news categories.")),
3114 wantErr: assert.NoError,
3117 name: "when user does not have permission to delete a news folder",
3121 Access: accessBitmap{},
3125 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3136 tranDelNewsItem, nil,
3137 NewField(fieldNewsPath,
3142 0x74, 0x65, 0x73, 0x74,
3147 wantRes: []Transaction{
3149 clientID: &[]byte{0, 1},
3152 Type: []byte{0, 0x00},
3153 ID: []byte{0, 0, 0, 0},
3154 ErrorCode: []byte{0, 0, 0, 1},
3156 NewField(fieldError, []byte("You are not allowed to delete news folders.")),
3160 wantErr: assert.NoError,
3163 name: "when user deletes a news folder",
3167 Access: func() accessBitmap {
3168 var bits accessBitmap
3169 bits.Set(accessNewsDeleteFldr)
3175 ConfigDir: "/fakeConfigRoot",
3176 FS: func() *MockFileStore {
3177 mfs := &MockFileStore{}
3178 mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
3181 ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3192 tranDelNewsItem, nil,
3193 NewField(fieldNewsPath,
3198 0x74, 0x65, 0x73, 0x74,
3203 wantRes: []Transaction{
3205 clientID: &[]byte{0, 1},
3208 Type: []byte{0x01, 0x7c},
3209 ID: []byte{0, 0, 0, 0},
3210 ErrorCode: []byte{0, 0, 0, 0},
3214 wantErr: assert.NoError,
3217 for _, tt := range tests {
3218 t.Run(tt.name, func(t *testing.T) {
3219 gotRes, err := HandleDelNewsItem(tt.args.cc, tt.args.t)
3220 if !tt.wantErr(t, err, fmt.Sprintf("HandleDelNewsItem(%v, %v)", tt.args.cc, tt.args.t)) {
3223 tranAssertEqual(t, tt.wantRes, gotRes)
3228 func TestHandleDownloadBanner(t *testing.T) {
3236 wantRes []Transaction
3237 wantErr assert.ErrorAssertionFunc
3240 name: "returns expected response",
3244 transfers: map[int]map[[4]byte]*FileTransfer{
3248 ConfigDir: "/config",
3250 BannerFile: "banner.jpg",
3252 fileTransfers: map[[4]byte]*FileTransfer{},
3253 FS: func() *MockFileStore {
3254 mfi := &MockFileInfo{}
3255 mfi.On("Size").Return(int64(100))
3257 mfs := &MockFileStore{}
3258 mfs.On("Stat", "/config/banner.jpg").Return(mfi, nil)
3263 t: NewTransaction(tranDownloadBanner, nil),
3265 wantRes: []Transaction{
3267 clientID: &[]byte{0, 1},
3270 Type: []byte{0x00, 0xd4},
3271 ID: []byte{0, 0, 0, 0},
3272 ErrorCode: []byte{0, 0, 0, 0},
3274 NewField(fieldRefNum, []byte{1, 2, 3, 4}),
3275 NewField(fieldTransferSize, []byte{0, 0, 0, 0x64}),
3279 wantErr: assert.NoError,
3282 for _, tt := range tests {
3283 t.Run(tt.name, func(t *testing.T) {
3284 gotRes, err := HandleDownloadBanner(tt.args.cc, tt.args.t)
3285 if !tt.wantErr(t, err, fmt.Sprintf("HandleDownloadBanner(%v, %v)", tt.args.cc, tt.args.t)) {
3289 tranAssertEqual(t, tt.wantRes, gotRes)
3294 func TestHandleTranOldPostNews(t *testing.T) {
3302 wantRes []Transaction
3303 wantErr assert.ErrorAssertionFunc
3306 name: "when user does not have required permission",
3310 Access: func() accessBitmap {
3311 var bits accessBitmap
3317 tranOldPostNews, &[]byte{0, 1},
3318 NewField(fieldData, []byte("hai")),
3321 wantRes: []Transaction{
3325 Type: []byte{0, 0x00},
3326 ID: []byte{0, 0, 0, 0},
3327 ErrorCode: []byte{0, 0, 0, 1},
3329 NewField(fieldError, []byte("You are not allowed to post news.")),
3333 wantErr: assert.NoError,
3336 name: "when user posts news update",
3340 Access: func() accessBitmap {
3341 var bits accessBitmap
3342 bits.Set(accessNewsPostArt)
3347 FS: func() *MockFileStore {
3348 mfs := &MockFileStore{}
3349 mfs.On("WriteFile", "/fakeConfigRoot/MessageBoard.txt", mock.Anything, mock.Anything).Return(nil, os.ErrNotExist)
3352 ConfigDir: "/fakeConfigRoot",
3357 tranOldPostNews, &[]byte{0, 1},
3358 NewField(fieldData, []byte("hai")),
3361 wantRes: []Transaction{
3365 Type: []byte{0, 0x67},
3366 ID: []byte{0, 0, 0, 0},
3367 ErrorCode: []byte{0, 0, 0, 0},
3370 wantErr: assert.NoError,
3373 for _, tt := range tests {
3374 t.Run(tt.name, func(t *testing.T) {
3375 gotRes, err := HandleTranOldPostNews(tt.args.cc, tt.args.t)
3376 if !tt.wantErr(t, err, fmt.Sprintf("HandleTranOldPostNews(%v, %v)", tt.args.cc, tt.args.t)) {
3380 tranAssertEqual(t, tt.wantRes, gotRes)
3385 func TestHandleInviteNewChat(t *testing.T) {
3393 wantRes []Transaction
3394 wantErr assert.ErrorAssertionFunc
3397 name: "when user does not have required permission",
3401 Access: func() accessBitmap {
3402 var bits accessBitmap
3407 t: NewTransaction(tranInviteNewChat, &[]byte{0, 1}),
3409 wantRes: []Transaction{
3413 Type: []byte{0, 0x00},
3414 ID: []byte{0, 0, 0, 0},
3415 ErrorCode: []byte{0, 0, 0, 1},
3417 NewField(fieldError, []byte("You are not allowed to request private chat.")),
3421 wantErr: assert.NoError,
3424 name: "when userA invites userB to new private chat",
3429 Access: func() accessBitmap {
3430 var bits accessBitmap
3431 bits.Set(accessOpenChat)
3435 UserName: []byte("UserA"),
3437 Flags: []byte{0, 0},
3439 Clients: map[uint16]*ClientConn{
3442 UserName: []byte("UserB"),
3443 Flags: []byte{0, 0},
3446 PrivateChats: make(map[uint32]*PrivateChat),
3450 tranInviteNewChat, &[]byte{0, 1},
3451 NewField(fieldUserID, []byte{0, 2}),
3454 wantRes: []Transaction{
3456 clientID: &[]byte{0, 2},
3459 Type: []byte{0, 0x71},
3460 ID: []byte{0, 0, 0, 0},
3461 ErrorCode: []byte{0, 0, 0, 0},
3463 NewField(fieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3464 NewField(fieldUserName, []byte("UserA")),
3465 NewField(fieldUserID, []byte{0, 1}),
3470 clientID: &[]byte{0, 1},
3473 Type: []byte{0, 0x70},
3474 ID: []byte{0, 0, 0, 0},
3475 ErrorCode: []byte{0, 0, 0, 0},
3477 NewField(fieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3478 NewField(fieldUserName, []byte("UserA")),
3479 NewField(fieldUserID, []byte{0, 1}),
3480 NewField(fieldUserIconID, []byte{0, 1}),
3481 NewField(fieldUserFlags, []byte{0, 0}),
3485 wantErr: assert.NoError,
3488 name: "when userA invites userB to new private chat, but UserB has refuse private chat enabled",
3493 Access: func() accessBitmap {
3494 var bits accessBitmap
3495 bits.Set(accessOpenChat)
3499 UserName: []byte("UserA"),
3501 Flags: []byte{0, 0},
3503 Clients: map[uint16]*ClientConn{
3506 UserName: []byte("UserB"),
3507 Flags: []byte{255, 255},
3510 PrivateChats: make(map[uint32]*PrivateChat),
3514 tranInviteNewChat, &[]byte{0, 1},
3515 NewField(fieldUserID, []byte{0, 2}),
3518 wantRes: []Transaction{
3520 clientID: &[]byte{0, 1},
3523 Type: []byte{0, 0x68},
3524 ID: []byte{0, 0, 0, 0},
3525 ErrorCode: []byte{0, 0, 0, 0},
3527 NewField(fieldData, []byte("UserB does not accept private chats.")),
3528 NewField(fieldUserName, []byte("UserB")),
3529 NewField(fieldUserID, []byte{0, 2}),
3530 NewField(fieldOptions, []byte{0, 2}),
3534 clientID: &[]byte{0, 1},
3537 Type: []byte{0, 0x70},
3538 ID: []byte{0, 0, 0, 0},
3539 ErrorCode: []byte{0, 0, 0, 0},
3541 NewField(fieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3542 NewField(fieldUserName, []byte("UserA")),
3543 NewField(fieldUserID, []byte{0, 1}),
3544 NewField(fieldUserIconID, []byte{0, 1}),
3545 NewField(fieldUserFlags, []byte{0, 0}),
3549 wantErr: assert.NoError,
3552 for _, tt := range tests {
3553 t.Run(tt.name, func(t *testing.T) {
3555 gotRes, err := HandleInviteNewChat(tt.args.cc, tt.args.t)
3556 if !tt.wantErr(t, err, fmt.Sprintf("HandleInviteNewChat(%v, %v)", tt.args.cc, tt.args.t)) {
3559 tranAssertEqual(t, tt.wantRes, gotRes)