5 "github.com/stretchr/testify/assert"
6 "github.com/stretchr/testify/mock"
16 func TestHandleSetChatSubject(t *testing.T) {
27 name: "sends chat subject to private chat members",
30 UserName: []byte{0x00, 0x01},
32 ChatMgr: func() *MockChatManager {
33 m := MockChatManager{}
34 m.On("Members", ChatID{0x0, 0x0, 0x0, 0x1}).Return([]*ClientConn{
37 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
43 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
48 m.On("SetSubject", ChatID{0x0, 0x0, 0x0, 0x1}, "Test Subject")
51 //PrivateChats: map[[4]byte]*PrivateChat{
52 // [4]byte{0, 0, 0, 1}: {
54 // ClientConn: map[[2]byte]*ClientConn{
57 // Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
63 // Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
70 ClientMgr: func() *MockClientMgr {
72 m.On("List").Return([]*ClientConn{
75 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
81 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
92 Type: [2]byte{0, 0x6a},
93 ID: [4]byte{0, 0, 0, 1},
95 NewField(FieldChatID, []byte{0, 0, 0, 1}),
96 NewField(FieldChatSubject, []byte("Test Subject")),
102 clientID: [2]byte{0, 1},
103 Type: [2]byte{0, 0x77},
105 NewField(FieldChatID, []byte{0, 0, 0, 1}),
106 NewField(FieldChatSubject, []byte("Test Subject")),
110 clientID: [2]byte{0, 2},
111 Type: [2]byte{0, 0x77},
113 NewField(FieldChatID, []byte{0, 0, 0, 1}),
114 NewField(FieldChatSubject, []byte("Test Subject")),
120 for _, tt := range tests {
121 t.Run(tt.name, func(t *testing.T) {
122 got := HandleSetChatSubject(tt.args.cc, &tt.args.t)
123 if !tranAssertEqual(t, tt.want, got) {
124 t.Errorf("HandleSetChatSubject() got = %v, want %v", got, tt.want)
130 func TestHandleLeaveChat(t *testing.T) {
141 name: "when client 2 leaves chat",
146 ChatMgr: func() *MockChatManager {
147 m := MockChatManager{}
148 m.On("Members", ChatID{0x0, 0x0, 0x0, 0x1}).Return([]*ClientConn{
151 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
156 m.On("Leave", ChatID{0x0, 0x0, 0x0, 0x1}, [2]uint8{0x0, 0x2})
157 m.On("GetSubject").Return("unset")
160 ClientMgr: func() *MockClientMgr {
162 m.On("Get").Return([]*ClientConn{
165 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
171 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
181 t: NewTransaction(TranDeleteUser, [2]byte{}, NewField(FieldChatID, []byte{0, 0, 0, 1})),
185 clientID: [2]byte{0, 1},
186 Type: [2]byte{0, 0x76},
188 NewField(FieldChatID, []byte{0, 0, 0, 1}),
189 NewField(FieldUserID, []byte{0, 2}),
195 for _, tt := range tests {
196 t.Run(tt.name, func(t *testing.T) {
197 got := HandleLeaveChat(tt.args.cc, &tt.args.t)
198 if !tranAssertEqual(t, tt.want, got) {
199 t.Errorf("HandleLeaveChat() got = %v, want %v", got, tt.want)
205 func TestHandleGetUserNameList(t *testing.T) {
216 name: "replies with userlist transaction",
221 ClientMgr: func() *MockClientMgr {
223 m.On("List").Return([]*ClientConn{
227 Flags: [2]byte{0, 3},
228 UserName: []byte{0, 4},
233 Flags: [2]byte{0, 3},
234 UserName: []byte{0, 4},
246 clientID: [2]byte{0, 1},
250 FieldUsernameWithInfo,
251 []byte{00, 01, 00, 02, 00, 03, 00, 02, 00, 04},
254 FieldUsernameWithInfo,
255 []byte{00, 02, 00, 02, 00, 03, 00, 02, 00, 04},
262 for _, tt := range tests {
263 t.Run(tt.name, func(t *testing.T) {
264 got := HandleGetUserNameList(tt.args.cc, &tt.args.t)
265 assert.Equal(t, tt.want, got)
270 func TestHandleChatSend(t *testing.T) {
281 name: "sends chat msg transaction to all clients",
285 Access: func() accessBitmap {
286 var bits accessBitmap
287 bits.Set(AccessSendChat)
291 UserName: []byte{0x00, 0x01},
293 ClientMgr: func() *MockClientMgr {
295 m.On("List").Return([]*ClientConn{
298 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
304 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
316 NewField(FieldData, []byte("hai")),
322 clientID: [2]byte{0, 1},
325 Type: [2]byte{0, 0x6a},
327 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
331 clientID: [2]byte{0, 2},
334 Type: [2]byte{0, 0x6a},
336 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
342 name: "treats Chat Type 00 00 00 00 as a public chat message",
346 Access: func() accessBitmap {
347 var bits accessBitmap
348 bits.Set(AccessSendChat)
352 UserName: []byte{0x00, 0x01},
354 ClientMgr: func() *MockClientMgr {
356 m.On("List").Return([]*ClientConn{
359 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
365 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
377 NewField(FieldData, []byte("hai")),
378 NewField(FieldChatID, []byte{0, 0, 0, 0}),
384 clientID: [2]byte{0, 1},
385 Type: [2]byte{0, 0x6a},
387 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
391 clientID: [2]byte{0, 2},
392 Type: [2]byte{0, 0x6a},
394 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
400 name: "when user does not have required permission",
404 Access: func() accessBitmap {
405 var bits accessBitmap
410 //Accounts: map[string]*Account{},
414 TranChatSend, [2]byte{0, 1},
415 NewField(FieldData, []byte("hai")),
421 ErrorCode: [4]byte{0, 0, 0, 1},
423 NewField(FieldError, []byte("You are not allowed to participate in chat.")),
429 name: "sends chat msg as emote if FieldChatOptions is set to 1",
433 Access: func() accessBitmap {
434 var bits accessBitmap
435 bits.Set(AccessSendChat)
439 UserName: []byte("Testy McTest"),
441 ClientMgr: func() *MockClientMgr {
443 m.On("List").Return([]*ClientConn{
446 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
452 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
464 NewField(FieldData, []byte("performed action")),
465 NewField(FieldChatOptions, []byte{0x00, 0x01}),
471 clientID: [2]byte{0, 1},
474 Type: [2]byte{0, 0x6a},
476 NewField(FieldData, []byte("\r*** Testy McTest performed action")),
480 clientID: [2]byte{0, 2},
483 Type: [2]byte{0, 0x6a},
485 NewField(FieldData, []byte("\r*** Testy McTest performed action")),
491 name: "does not send chat msg as emote if FieldChatOptions is set to 0",
495 Access: func() accessBitmap {
496 var bits accessBitmap
497 bits.Set(AccessSendChat)
501 UserName: []byte("Testy McTest"),
503 ClientMgr: func() *MockClientMgr {
505 m.On("List").Return([]*ClientConn{
508 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
514 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
526 NewField(FieldData, []byte("hello")),
527 NewField(FieldChatOptions, []byte{0x00, 0x00}),
533 clientID: [2]byte{0, 1},
534 Type: [2]byte{0, 0x6a},
536 NewField(FieldData, []byte("\r Testy McTest: hello")),
540 clientID: [2]byte{0, 2},
541 Type: [2]byte{0, 0x6a},
543 NewField(FieldData, []byte("\r Testy McTest: hello")),
549 name: "only sends chat msg to clients with AccessReadChat permission",
553 Access: func() accessBitmap {
554 var bits accessBitmap
555 bits.Set(AccessSendChat)
559 UserName: []byte{0x00, 0x01},
561 ClientMgr: func() *MockClientMgr {
563 m.On("List").Return([]*ClientConn{
566 Access: func() accessBitmap {
567 var bits accessBitmap
568 bits.Set(AccessReadChat)
586 NewField(FieldData, []byte("hai")),
592 clientID: [2]byte{0, 1},
593 Type: [2]byte{0, 0x6a},
595 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
601 name: "only sends private chat msg to members of private chat",
605 Access: func() accessBitmap {
606 var bits accessBitmap
607 bits.Set(AccessSendChat)
611 UserName: []byte{0x00, 0x01},
613 ChatMgr: func() *MockChatManager {
614 m := MockChatManager{}
615 m.On("Members", ChatID{0x0, 0x0, 0x0, 0x1}).Return([]*ClientConn{
623 m.On("GetSubject").Return("unset")
626 ClientMgr: func() *MockClientMgr {
628 m.On("List").Return([]*ClientConn{
631 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
637 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
643 Access: accessBitmap{0, 0, 0, 0, 0, 0, 0, 0},
655 NewField(FieldData, []byte("hai")),
656 NewField(FieldChatID, []byte{0, 0, 0, 1}),
662 clientID: [2]byte{0, 1},
663 Type: [2]byte{0, 0x6a},
665 NewField(FieldChatID, []byte{0, 0, 0, 1}),
666 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
670 clientID: [2]byte{0, 2},
671 Type: [2]byte{0, 0x6a},
673 NewField(FieldChatID, []byte{0, 0, 0, 1}),
674 NewField(FieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
680 for _, tt := range tests {
681 t.Run(tt.name, func(t *testing.T) {
682 got := HandleChatSend(tt.args.cc, &tt.args.t)
683 tranAssertEqual(t, tt.want, got)
688 func TestHandleGetFileInfo(t *testing.T) {
696 wantRes []Transaction
699 name: "returns expected fields when a valid file is requested",
702 ID: [2]byte{0x00, 0x01},
706 FileRoot: func() string {
707 path, _ := os.Getwd()
708 return filepath.Join(path, "/test/config/Files")
714 TranGetFileInfo, [2]byte{},
715 NewField(FieldFileName, []byte("testfile.txt")),
716 NewField(FieldFilePath, []byte{0x00, 0x00}),
719 wantRes: []Transaction{
721 clientID: [2]byte{0, 1},
725 NewField(FieldFileName, []byte("testfile.txt")),
726 NewField(FieldFileTypeString, []byte("Text File")),
727 NewField(FieldFileCreatorString, []byte("ttxt")),
728 NewField(FieldFileType, []byte("TEXT")),
729 NewField(FieldFileCreateDate, make([]byte, 8)),
730 NewField(FieldFileModifyDate, make([]byte, 8)),
731 NewField(FieldFileSize, []byte{0x0, 0x0, 0x0, 0x17}),
737 for _, tt := range tests {
738 t.Run(tt.name, func(t *testing.T) {
739 gotRes := HandleGetFileInfo(tt.args.cc, &tt.args.t)
741 // Clear the file timestamp fields to work around problems running the tests in multiple timezones
742 // TODO: revisit how to test this by mocking the stat calls
743 gotRes[0].Fields[4].Data = make([]byte, 8)
744 gotRes[0].Fields[5].Data = make([]byte, 8)
746 if !tranAssertEqual(t, tt.wantRes, gotRes) {
747 t.Errorf("HandleGetFileInfo() gotRes = %v, want %v", gotRes, tt.wantRes)
753 func TestHandleNewFolder(t *testing.T) {
761 wantRes []Transaction
764 name: "without required permission",
768 Access: func() accessBitmap {
769 var bits accessBitmap
779 wantRes: []Transaction{
782 ErrorCode: [4]byte{0, 0, 0, 1},
784 NewField(FieldError, []byte("You are not allowed to create folders.")),
790 name: "when path is nested",
794 Access: func() accessBitmap {
795 var bits accessBitmap
796 bits.Set(AccessCreateFolder)
805 FS: func() *MockFileStore {
806 mfs := &MockFileStore{}
807 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
808 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
814 TranNewFolder, [2]byte{0, 1},
815 NewField(FieldFileName, []byte("testFolder")),
816 NewField(FieldFilePath, []byte{
824 wantRes: []Transaction{
826 clientID: [2]byte{0, 1},
832 name: "when path is not nested",
836 Access: func() accessBitmap {
837 var bits accessBitmap
838 bits.Set(AccessCreateFolder)
847 FS: func() *MockFileStore {
848 mfs := &MockFileStore{}
849 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
850 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
856 TranNewFolder, [2]byte{0, 1},
857 NewField(FieldFileName, []byte("testFolder")),
860 wantRes: []Transaction{
862 clientID: [2]byte{0, 1},
868 name: "when Write returns an err",
872 Access: func() accessBitmap {
873 var bits accessBitmap
874 bits.Set(AccessCreateFolder)
883 FS: func() *MockFileStore {
884 mfs := &MockFileStore{}
885 mfs.On("Mkdir", "/Files/aaa/testFolder", fs.FileMode(0777)).Return(nil)
886 mfs.On("Stat", "/Files/aaa/testFolder").Return(nil, os.ErrNotExist)
892 TranNewFolder, [2]byte{0, 1},
893 NewField(FieldFileName, []byte("testFolder")),
894 NewField(FieldFilePath, []byte{
899 wantRes: []Transaction{},
902 name: "FieldFileName does not allow directory traversal",
906 Access: func() accessBitmap {
907 var bits accessBitmap
908 bits.Set(AccessCreateFolder)
917 FS: func() *MockFileStore {
918 mfs := &MockFileStore{}
919 mfs.On("Mkdir", "/Files/testFolder", fs.FileMode(0777)).Return(nil)
920 mfs.On("Stat", "/Files/testFolder").Return(nil, os.ErrNotExist)
926 TranNewFolder, [2]byte{0, 1},
927 NewField(FieldFileName, []byte("../../testFolder")),
930 wantRes: []Transaction{
932 clientID: [2]byte{0, 1},
938 name: "FieldFilePath does not allow directory traversal",
942 Access: func() accessBitmap {
943 var bits accessBitmap
944 bits.Set(AccessCreateFolder)
953 FS: func() *MockFileStore {
954 mfs := &MockFileStore{}
955 mfs.On("Mkdir", "/Files/foo/testFolder", fs.FileMode(0777)).Return(nil)
956 mfs.On("Stat", "/Files/foo/testFolder").Return(nil, os.ErrNotExist)
962 TranNewFolder, [2]byte{0, 1},
963 NewField(FieldFileName, []byte("testFolder")),
964 NewField(FieldFilePath, []byte{
975 wantRes: []Transaction{
977 clientID: [2]byte{0, 1},
983 for _, tt := range tests {
984 t.Run(tt.name, func(t *testing.T) {
985 gotRes := HandleNewFolder(tt.args.cc, &tt.args.t)
987 if !tranAssertEqual(t, tt.wantRes, gotRes) {
988 t.Errorf("HandleNewFolder() gotRes = %v, want %v", gotRes, tt.wantRes)
994 func TestHandleUploadFile(t *testing.T) {
1002 wantRes []Transaction
1005 name: "when request is valid and user has Upload Anywhere permission",
1010 FileTransferMgr: NewMemFileTransferMgr(),
1012 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1014 ClientFileTransferMgr: NewClientFileTransferMgr(),
1016 Access: func() accessBitmap {
1017 var bits accessBitmap
1018 bits.Set(AccessUploadFile)
1019 bits.Set(AccessUploadAnywhere)
1025 TranUploadFile, [2]byte{0, 1},
1026 NewField(FieldFileName, []byte("testFile")),
1027 NewField(FieldFilePath, []byte{
1035 wantRes: []Transaction{
1039 NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}), // rand.Seed(1)
1045 name: "when user does not have required access",
1049 Access: func() accessBitmap {
1050 var bits accessBitmap
1056 TranUploadFile, [2]byte{0, 1},
1057 NewField(FieldFileName, []byte("testFile")),
1058 NewField(FieldFilePath, []byte{
1066 wantRes: []Transaction{
1069 ErrorCode: [4]byte{0, 0, 0, 1},
1071 NewField(FieldError, []byte("You are not allowed to upload files.")), // rand.Seed(1)
1077 for _, tt := range tests {
1078 t.Run(tt.name, func(t *testing.T) {
1079 gotRes := HandleUploadFile(tt.args.cc, &tt.args.t)
1080 tranAssertEqual(t, tt.wantRes, gotRes)
1085 func TestHandleMakeAlias(t *testing.T) {
1093 wantRes []Transaction
1096 name: "with valid input and required permissions",
1099 logger: NewTestLogger(),
1101 Access: func() accessBitmap {
1102 var bits accessBitmap
1103 bits.Set(AccessMakeAlias)
1109 FileRoot: func() string {
1110 path, _ := os.Getwd()
1111 return path + "/test/config/Files"
1114 Logger: NewTestLogger(),
1115 FS: func() *MockFileStore {
1116 mfs := &MockFileStore{}
1117 path, _ := os.Getwd()
1120 path+"/test/config/Files/foo/testFile",
1121 path+"/test/config/Files/bar/testFile",
1128 TranMakeFileAlias, [2]byte{0, 1},
1129 NewField(FieldFileName, []byte("testFile")),
1130 NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1131 NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1134 wantRes: []Transaction{
1137 Fields: []Field(nil),
1142 name: "when symlink returns an error",
1145 logger: NewTestLogger(),
1147 Access: func() accessBitmap {
1148 var bits accessBitmap
1149 bits.Set(AccessMakeAlias)
1155 FileRoot: func() string {
1156 path, _ := os.Getwd()
1157 return path + "/test/config/Files"
1160 Logger: NewTestLogger(),
1161 FS: func() *MockFileStore {
1162 mfs := &MockFileStore{}
1163 path, _ := os.Getwd()
1166 path+"/test/config/Files/foo/testFile",
1167 path+"/test/config/Files/bar/testFile",
1168 ).Return(errors.New("ohno"))
1174 TranMakeFileAlias, [2]byte{0, 1},
1175 NewField(FieldFileName, []byte("testFile")),
1176 NewField(FieldFilePath, EncodeFilePath(strings.Join([]string{"foo"}, "/"))),
1177 NewField(FieldFileNewPath, EncodeFilePath(strings.Join([]string{"bar"}, "/"))),
1180 wantRes: []Transaction{
1183 ErrorCode: [4]byte{0, 0, 0, 1},
1185 NewField(FieldError, []byte("Error creating alias")),
1191 name: "when user does not have required permission",
1194 logger: NewTestLogger(),
1196 Access: accessBitmap{},
1200 FileRoot: func() string {
1201 path, _ := os.Getwd()
1202 return path + "/test/config/Files"
1208 TranMakeFileAlias, [2]byte{0, 1},
1209 NewField(FieldFileName, []byte("testFile")),
1210 NewField(FieldFilePath, []byte{
1216 NewField(FieldFileNewPath, []byte{
1224 wantRes: []Transaction{
1227 ErrorCode: [4]byte{0, 0, 0, 1},
1229 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 := HandleMakeAlias(tt.args.cc, &tt.args.t)
1238 tranAssertEqual(t, tt.wantRes, gotRes)
1243 func TestHandleGetUser(t *testing.T) {
1251 wantRes []Transaction
1254 name: "when account is valid",
1258 Access: func() accessBitmap {
1259 var bits accessBitmap
1260 bits.Set(AccessOpenUser)
1265 AccountManager: func() *MockAccountManager {
1266 m := MockAccountManager{}
1267 m.On("Get", "guest").Return(&Account{
1270 Password: "password",
1271 Access: accessBitmap{},
1278 TranGetUser, [2]byte{0, 1},
1279 NewField(FieldUserLogin, []byte("guest")),
1282 wantRes: []Transaction{
1286 NewField(FieldUserName, []byte("Guest")),
1287 NewField(FieldUserLogin, encodeString([]byte("guest"))),
1288 NewField(FieldUserPassword, []byte("password")),
1289 NewField(FieldUserAccess, []byte{0, 0, 0, 0, 0, 0, 0, 0}),
1295 name: "when user does not have required permission",
1299 Access: func() accessBitmap {
1300 var bits accessBitmap
1305 //Accounts: map[string]*Account{},
1309 TranGetUser, [2]byte{0, 1},
1310 NewField(FieldUserLogin, []byte("nonExistentUser")),
1313 wantRes: []Transaction{
1316 ErrorCode: [4]byte{0, 0, 0, 1},
1318 NewField(FieldError, []byte("You are not allowed to view accounts.")),
1324 name: "when account does not exist",
1328 Access: func() accessBitmap {
1329 var bits accessBitmap
1330 bits.Set(AccessOpenUser)
1335 AccountManager: func() *MockAccountManager {
1336 m := MockAccountManager{}
1337 m.On("Get", "nonExistentUser").Return((*Account)(nil))
1343 TranGetUser, [2]byte{0, 1},
1344 NewField(FieldUserLogin, []byte("nonExistentUser")),
1347 wantRes: []Transaction{
1351 Type: [2]byte{0, 0},
1352 ErrorCode: [4]byte{0, 0, 0, 1},
1354 NewField(FieldError, []byte("Account does not exist.")),
1360 for _, tt := range tests {
1361 t.Run(tt.name, func(t *testing.T) {
1362 gotRes := HandleGetUser(tt.args.cc, &tt.args.t)
1363 tranAssertEqual(t, tt.wantRes, gotRes)
1368 func TestHandleDeleteUser(t *testing.T) {
1376 wantRes []Transaction
1379 name: "when user exists",
1383 Access: func() accessBitmap {
1384 var bits accessBitmap
1385 bits.Set(AccessDeleteUser)
1390 AccountManager: func() *MockAccountManager {
1391 m := MockAccountManager{}
1392 m.On("Delete", "testuser").Return(nil)
1395 ClientMgr: func() *MockClientMgr {
1396 m := MockClientMgr{}
1397 m.On("List").Return([]*ClientConn{}) // TODO
1403 TranDeleteUser, [2]byte{0, 1},
1404 NewField(FieldUserLogin, encodeString([]byte("testuser"))),
1407 wantRes: []Transaction{
1411 Type: [2]byte{0, 0},
1412 Fields: []Field(nil),
1417 name: "when user does not have required permission",
1421 Access: accessBitmap{},
1424 //Accounts: map[string]*Account{},
1428 TranDeleteUser, [2]byte{0, 1},
1429 NewField(FieldUserLogin, encodeString([]byte("testuser"))),
1432 wantRes: []Transaction{
1435 ErrorCode: [4]byte{0, 0, 0, 1},
1437 NewField(FieldError, []byte("You are not allowed to delete accounts.")),
1443 for _, tt := range tests {
1444 t.Run(tt.name, func(t *testing.T) {
1445 gotRes := HandleDeleteUser(tt.args.cc, &tt.args.t)
1446 tranAssertEqual(t, tt.wantRes, gotRes)
1451 func TestHandleGetMsgs(t *testing.T) {
1459 wantRes []Transaction
1462 name: "returns news data",
1466 Access: func() accessBitmap {
1467 var bits accessBitmap
1468 bits.Set(AccessNewsReadArt)
1473 MessageBoard: func() *mockReadWriteSeeker {
1474 m := mockReadWriteSeeker{}
1475 m.On("Seek", int64(0), 0).Return(int64(0), nil)
1476 m.On("Read", mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
1477 arg := args.Get(0).([]uint8)
1479 }).Return(4, io.EOF)
1485 TranGetMsgs, [2]byte{0, 1},
1488 wantRes: []Transaction{
1492 NewField(FieldData, []byte("TEST")),
1498 name: "when user does not have required permission",
1502 Access: accessBitmap{},
1505 //Accounts: map[string]*Account{},
1509 TranGetMsgs, [2]byte{0, 1},
1512 wantRes: []Transaction{
1515 ErrorCode: [4]byte{0, 0, 0, 1},
1517 NewField(FieldError, []byte("You are not allowed to read news.")),
1523 for _, tt := range tests {
1524 t.Run(tt.name, func(t *testing.T) {
1525 gotRes := HandleGetMsgs(tt.args.cc, &tt.args.t)
1526 tranAssertEqual(t, tt.wantRes, gotRes)
1531 func TestHandleNewUser(t *testing.T) {
1539 wantRes []Transaction
1542 name: "when user does not have required permission",
1546 Access: func() accessBitmap {
1547 var bits accessBitmap
1552 //Accounts: map[string]*Account{},
1556 TranNewUser, [2]byte{0, 1},
1559 wantRes: []Transaction{
1562 ErrorCode: [4]byte{0, 0, 0, 1},
1564 NewField(FieldError, []byte("You are not allowed to create new accounts.")),
1570 name: "when user attempts to create account with greater access",
1574 Access: func() accessBitmap {
1575 var bits accessBitmap
1576 bits.Set(AccessCreateUser)
1581 AccountManager: func() *MockAccountManager {
1582 m := MockAccountManager{}
1583 m.On("Get", "userB").Return((*Account)(nil))
1589 TranNewUser, [2]byte{0, 1},
1590 NewField(FieldUserLogin, encodeString([]byte("userB"))),
1594 var bits accessBitmap
1595 bits.Set(AccessDisconUser)
1601 wantRes: []Transaction{
1604 ErrorCode: [4]byte{0, 0, 0, 1},
1606 NewField(FieldError, []byte("Cannot create account with more access than yourself.")),
1612 for _, tt := range tests {
1613 t.Run(tt.name, func(t *testing.T) {
1614 gotRes := HandleNewUser(tt.args.cc, &tt.args.t)
1615 tranAssertEqual(t, tt.wantRes, gotRes)
1620 func TestHandleListUsers(t *testing.T) {
1628 wantRes []Transaction
1631 name: "when user does not have required permission",
1635 Access: func() accessBitmap {
1636 var bits accessBitmap
1641 //Accounts: map[string]*Account{},
1645 TranNewUser, [2]byte{0, 1},
1648 wantRes: []Transaction{
1651 ErrorCode: [4]byte{0, 0, 0, 1},
1653 NewField(FieldError, []byte("You are not allowed to view accounts.")),
1659 name: "when user has required permission",
1663 Access: func() accessBitmap {
1664 var bits accessBitmap
1665 bits.Set(AccessOpenUser)
1670 AccountManager: func() *MockAccountManager {
1671 m := MockAccountManager{}
1672 m.On("List").Return([]Account{
1677 Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
1685 TranGetClientInfoText, [2]byte{0, 1},
1686 NewField(FieldUserID, []byte{0, 1}),
1689 wantRes: []Transaction{
1693 NewField(FieldData, []byte{
1694 0x00, 0x04, 0x00, 0x66, 0x00, 0x05, 0x67, 0x75, 0x65, 0x73, 0x74, 0x00, 0x69, 0x00, 0x05, 0x98,
1695 0x8a, 0x9a, 0x8c, 0x8b, 0x00, 0x6e, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1696 0x00, 0x6a, 0x00, 0x01, 0x78,
1703 for _, tt := range tests {
1704 t.Run(tt.name, func(t *testing.T) {
1705 gotRes := HandleListUsers(tt.args.cc, &tt.args.t)
1707 tranAssertEqual(t, tt.wantRes, gotRes)
1712 func TestHandleDownloadFile(t *testing.T) {
1720 wantRes []Transaction
1723 name: "when user does not have required permission",
1727 Access: func() accessBitmap {
1728 var bits accessBitmap
1734 t: NewTransaction(TranDownloadFile, [2]byte{0, 1}),
1736 wantRes: []Transaction{
1739 ErrorCode: [4]byte{0, 0, 0, 1},
1741 NewField(FieldError, []byte("You are not allowed to download files.")),
1747 name: "with a valid file",
1750 ClientFileTransferMgr: NewClientFileTransferMgr(),
1752 Access: func() accessBitmap {
1753 var bits accessBitmap
1754 bits.Set(AccessDownloadFile)
1760 FileTransferMgr: NewMemFileTransferMgr(),
1762 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1769 NewField(FieldFileName, []byte("testfile.txt")),
1770 NewField(FieldFilePath, []byte{0x0, 0x00}),
1773 wantRes: []Transaction{
1777 NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1778 NewField(FieldWaitingCount, []byte{0x00, 0x00}),
1779 NewField(FieldTransferSize, []byte{0x00, 0x00, 0x00, 0xa5}),
1780 NewField(FieldFileSize, []byte{0x00, 0x00, 0x00, 0x17}),
1786 name: "when client requests to resume 1k test file at offset 256",
1789 ClientFileTransferMgr: NewClientFileTransferMgr(),
1791 Access: func() accessBitmap {
1792 var bits accessBitmap
1793 bits.Set(AccessDownloadFile)
1800 // FS: func() *MockFileStore {
1801 // path, _ := os.Getwd()
1802 // testFile, err := os.Open(path + "/test/config/Files/testfile-1k")
1807 // mfi := &MockFileInfo{}
1808 // mfi.On("Mode").Return(fs.FileMode(0))
1809 // mfs := &MockFileStore{}
1810 // mfs.On("Stat", "/fakeRoot/Files/testfile.txt").Return(mfi, nil)
1811 // mfs.On("Open", "/fakeRoot/Files/testfile.txt").Return(testFile, nil)
1812 // mfs.On("Stat", "/fakeRoot/Files/.info_testfile.txt").Return(nil, errors.New("no"))
1813 // mfs.On("Stat", "/fakeRoot/Files/.rsrc_testfile.txt").Return(nil, errors.New("no"))
1817 FileTransferMgr: NewMemFileTransferMgr(),
1819 FileRoot: func() string { path, _ := os.Getwd(); return path + "/test/config/Files" }(),
1821 //Accounts: map[string]*Account{},
1827 NewField(FieldFileName, []byte("testfile-1k")),
1828 NewField(FieldFilePath, []byte{0x00, 0x00}),
1830 FieldFileResumeData,
1832 frd := FileResumeData{
1833 ForkCount: [2]byte{0, 2},
1834 ForkInfoList: []ForkInfoList{
1836 Fork: [4]byte{0x44, 0x41, 0x54, 0x41}, // "DATA"
1837 DataSize: [4]byte{0, 0, 0x01, 0x00}, // request offset 256
1840 Fork: [4]byte{0x4d, 0x41, 0x43, 0x52}, // "MACR"
1841 DataSize: [4]byte{0, 0, 0, 0},
1845 b, _ := frd.BinaryMarshal()
1851 wantRes: []Transaction{
1855 NewField(FieldRefNum, []byte{0x52, 0xfd, 0xfc, 0x07}),
1856 NewField(FieldWaitingCount, []byte{0x00, 0x00}),
1857 NewField(FieldTransferSize, []byte{0x00, 0x00, 0x03, 0x8d}),
1858 NewField(FieldFileSize, []byte{0x00, 0x00, 0x03, 0x00}),
1864 for _, tt := range tests {
1865 t.Run(tt.name, func(t *testing.T) {
1866 gotRes := HandleDownloadFile(tt.args.cc, &tt.args.t)
1867 tranAssertEqual(t, tt.wantRes, gotRes)
1872 func TestHandleUpdateUser(t *testing.T) {
1880 wantRes []Transaction
1883 name: "when action is create user without required permission",
1886 logger: NewTestLogger(),
1888 AccountManager: func() *MockAccountManager {
1889 m := MockAccountManager{}
1890 m.On("Get", "bbb").Return((*Account)(nil))
1893 Logger: NewTestLogger(),
1896 Access: accessBitmap{},
1902 NewField(FieldData, []byte{
1903 0x00, 0x04, // field count
1905 0x00, 0x69, // FieldUserLogin = 105
1909 0x00, 0x6a, // FieldUserPassword = 106
1913 0x00, 0x66, // FieldUserName = 102
1917 0x00, 0x6e, // FieldUserAccess = 110
1919 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
1923 wantRes: []Transaction{
1926 ErrorCode: [4]byte{0, 0, 0, 1},
1928 NewField(FieldError, []byte("You are not allowed to create new accounts.")),
1934 name: "when action is modify user without required permission",
1937 logger: NewTestLogger(),
1939 Logger: NewTestLogger(),
1940 AccountManager: func() *MockAccountManager {
1941 m := MockAccountManager{}
1942 m.On("Get", "bbb").Return(&Account{})
1947 Access: func() accessBitmap {
1948 var bits accessBitmap
1956 NewField(FieldData, []byte{
1957 0x00, 0x04, // field count
1959 0x00, 0x69, // FieldUserLogin = 105
1963 0x00, 0x6a, // FieldUserPassword = 106
1967 0x00, 0x66, // FieldUserName = 102
1971 0x00, 0x6e, // FieldUserAccess = 110
1973 0x60, 0x70, 0x0c, 0x20, 0x03, 0x80, 0x00, 0x00,
1977 wantRes: []Transaction{
1980 ErrorCode: [4]byte{0, 0, 0, 1},
1982 NewField(FieldError, []byte("You are not allowed to modify accounts.")),
1988 name: "when action is delete user without required permission",
1991 logger: NewTestLogger(),
1994 Access: accessBitmap{},
2000 NewField(FieldData, []byte{
2008 wantRes: []Transaction{
2011 ErrorCode: [4]byte{0, 0, 0, 1},
2013 NewField(FieldError, []byte("You are not allowed to delete accounts.")),
2019 for _, tt := range tests {
2020 t.Run(tt.name, func(t *testing.T) {
2021 gotRes := HandleUpdateUser(tt.args.cc, &tt.args.t)
2022 tranAssertEqual(t, tt.wantRes, gotRes)
2027 func TestHandleDelNewsArt(t *testing.T) {
2035 wantRes []Transaction
2038 name: "without required permission",
2042 Access: func() accessBitmap {
2043 var bits accessBitmap
2053 wantRes: []Transaction{
2056 ErrorCode: [4]byte{0, 0, 0, 1},
2058 NewField(FieldError, []byte("You are not allowed to delete news articles.")),
2064 for _, tt := range tests {
2065 t.Run(tt.name, func(t *testing.T) {
2066 gotRes := HandleDelNewsArt(tt.args.cc, &tt.args.t)
2067 tranAssertEqual(t, tt.wantRes, gotRes)
2072 func TestHandleDisconnectUser(t *testing.T) {
2080 wantRes []Transaction
2083 name: "without required permission",
2087 Access: func() accessBitmap {
2088 var bits accessBitmap
2098 wantRes: []Transaction{
2101 ErrorCode: [4]byte{0, 0, 0, 1},
2103 NewField(FieldError, []byte("You are not allowed to disconnect users.")),
2109 name: "when target user has 'cannot be disconnected' priv",
2113 ClientMgr: func() *MockClientMgr {
2114 m := MockClientMgr{}
2115 m.On("Get", ClientID{0x0, 0x1}).Return(&ClientConn{
2118 Access: func() accessBitmap {
2119 var bits accessBitmap
2120 bits.Set(AccessCannotBeDiscon)
2130 Access: func() accessBitmap {
2131 var bits accessBitmap
2132 bits.Set(AccessDisconUser)
2140 NewField(FieldUserID, []byte{0, 1}),
2143 wantRes: []Transaction{
2146 ErrorCode: [4]byte{0, 0, 0, 1},
2148 NewField(FieldError, []byte("unnamed is not allowed to be disconnected.")),
2154 for _, tt := range tests {
2155 t.Run(tt.name, func(t *testing.T) {
2156 gotRes := HandleDisconnectUser(tt.args.cc, &tt.args.t)
2157 tranAssertEqual(t, tt.wantRes, gotRes)
2162 func TestHandleSendInstantMsg(t *testing.T) {
2170 wantRes []Transaction
2173 name: "without required permission",
2177 Access: func() accessBitmap {
2178 var bits accessBitmap
2188 wantRes: []Transaction{
2191 ErrorCode: [4]byte{0, 0, 0, 1},
2193 NewField(FieldError, []byte("You are not allowed to send private messages.")),
2199 name: "when client 1 sends a message to client 2",
2203 Access: func() accessBitmap {
2204 var bits accessBitmap
2205 bits.Set(AccessSendPrivMsg)
2210 UserName: []byte("User1"),
2212 ClientMgr: func() *MockClientMgr {
2213 m := MockClientMgr{}
2214 m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
2215 AutoReply: []byte(nil),
2216 Flags: [2]byte{0, 0},
2226 NewField(FieldData, []byte("hai")),
2227 NewField(FieldUserID, []byte{0, 2}),
2230 wantRes: []Transaction{
2234 NewField(FieldData, []byte("hai")),
2235 NewField(FieldUserName, []byte("User1")),
2236 NewField(FieldUserID, []byte{0, 1}),
2237 NewField(FieldOptions, []byte{0, 1}),
2240 clientID: [2]byte{0, 1},
2242 Fields: []Field(nil),
2247 name: "when client 2 has autoreply enabled",
2251 Access: func() accessBitmap {
2252 var bits accessBitmap
2253 bits.Set(AccessSendPrivMsg)
2258 UserName: []byte("User1"),
2260 ClientMgr: func() *MockClientMgr {
2261 m := MockClientMgr{}
2262 m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
2263 Flags: [2]byte{0, 0},
2265 UserName: []byte("User2"),
2266 AutoReply: []byte("autohai"),
2275 NewField(FieldData, []byte("hai")),
2276 NewField(FieldUserID, []byte{0, 2}),
2279 wantRes: []Transaction{
2283 NewField(FieldData, []byte("hai")),
2284 NewField(FieldUserName, []byte("User1")),
2285 NewField(FieldUserID, []byte{0, 1}),
2286 NewField(FieldOptions, []byte{0, 1}),
2291 NewField(FieldData, []byte("autohai")),
2292 NewField(FieldUserName, []byte("User2")),
2293 NewField(FieldUserID, []byte{0, 2}),
2294 NewField(FieldOptions, []byte{0, 1}),
2297 clientID: [2]byte{0, 1},
2299 Fields: []Field(nil),
2304 name: "when client 2 has refuse private messages enabled",
2308 Access: func() accessBitmap {
2309 var bits accessBitmap
2310 bits.Set(AccessSendPrivMsg)
2315 UserName: []byte("User1"),
2317 ClientMgr: func() *MockClientMgr {
2318 m := MockClientMgr{}
2319 m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
2320 Flags: [2]byte{255, 255},
2322 UserName: []byte("User2"),
2332 NewField(FieldData, []byte("hai")),
2333 NewField(FieldUserID, []byte{0, 2}),
2336 wantRes: []Transaction{
2340 NewField(FieldData, []byte("User2 does not accept private messages.")),
2341 NewField(FieldUserName, []byte("User2")),
2342 NewField(FieldUserID, []byte{0, 2}),
2343 NewField(FieldOptions, []byte{0, 2}),
2346 clientID: [2]byte{0, 1},
2348 Fields: []Field(nil),
2353 for _, tt := range tests {
2354 t.Run(tt.name, func(t *testing.T) {
2355 gotRes := HandleSendInstantMsg(tt.args.cc, &tt.args.t)
2356 tranAssertEqual(t, tt.wantRes, gotRes)
2361 func TestHandleDeleteFile(t *testing.T) {
2369 wantRes []Transaction
2372 name: "when user does not have required permission to delete a folder",
2376 Access: func() accessBitmap {
2377 var bits accessBitmap
2383 FileRoot: func() string {
2384 return "/fakeRoot/Files"
2387 FS: func() *MockFileStore {
2388 mfi := &MockFileInfo{}
2389 mfi.On("Mode").Return(fs.FileMode(0))
2390 mfi.On("Size").Return(int64(100))
2391 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2392 mfi.On("IsDir").Return(false)
2393 mfi.On("Name").Return("testfile")
2395 mfs := &MockFileStore{}
2396 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2397 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2398 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2402 //Accounts: map[string]*Account{},
2406 TranDeleteFile, [2]byte{0, 1},
2407 NewField(FieldFileName, []byte("testfile")),
2408 NewField(FieldFilePath, []byte{
2416 wantRes: []Transaction{
2419 ErrorCode: [4]byte{0, 0, 0, 1},
2421 NewField(FieldError, []byte("You are not allowed to delete files.")),
2427 name: "deletes all associated metadata files",
2431 Access: func() accessBitmap {
2432 var bits accessBitmap
2433 bits.Set(AccessDeleteFile)
2439 FileRoot: func() string {
2440 return "/fakeRoot/Files"
2443 FS: func() *MockFileStore {
2444 mfi := &MockFileInfo{}
2445 mfi.On("Mode").Return(fs.FileMode(0))
2446 mfi.On("Size").Return(int64(100))
2447 mfi.On("ModTime").Return(time.Parse(time.Layout, time.Layout))
2448 mfi.On("IsDir").Return(false)
2449 mfi.On("Name").Return("testfile")
2451 mfs := &MockFileStore{}
2452 mfs.On("Stat", "/fakeRoot/Files/aaa/testfile").Return(mfi, nil)
2453 mfs.On("Stat", "/fakeRoot/Files/aaa/.info_testfile").Return(nil, errors.New("err"))
2454 mfs.On("Stat", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil, errors.New("err"))
2456 mfs.On("RemoveAll", "/fakeRoot/Files/aaa/testfile").Return(nil)
2457 mfs.On("Remove", "/fakeRoot/Files/aaa/testfile.incomplete").Return(nil)
2458 mfs.On("Remove", "/fakeRoot/Files/aaa/.rsrc_testfile").Return(nil)
2459 mfs.On("Remove", "/fakeRoot/Files/aaa/.info_testfile").Return(nil)
2463 //Accounts: map[string]*Account{},
2467 TranDeleteFile, [2]byte{0, 1},
2468 NewField(FieldFileName, []byte("testfile")),
2469 NewField(FieldFilePath, []byte{
2477 wantRes: []Transaction{
2480 Fields: []Field(nil),
2485 for _, tt := range tests {
2486 t.Run(tt.name, func(t *testing.T) {
2487 gotRes := HandleDeleteFile(tt.args.cc, &tt.args.t)
2488 tranAssertEqual(t, tt.wantRes, gotRes)
2490 tt.args.cc.Server.FS.(*MockFileStore).AssertExpectations(t)
2495 func TestHandleGetFileNameList(t *testing.T) {
2503 wantRes []Transaction
2506 name: "when FieldFilePath is a drop box, but user does not have AccessViewDropBoxes ",
2510 Access: func() accessBitmap {
2511 var bits accessBitmap
2518 FileRoot: func() string {
2519 path, _ := os.Getwd()
2520 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2526 TranGetFileNameList, [2]byte{0, 1},
2527 NewField(FieldFilePath, []byte{
2531 0x64, 0x72, 0x6f, 0x70, 0x20, 0x62, 0x6f, 0x78, // "drop box"
2535 wantRes: []Transaction{
2538 ErrorCode: [4]byte{0, 0, 0, 1},
2540 NewField(FieldError, []byte("You are not allowed to view drop boxes.")),
2546 name: "with file root",
2551 FileRoot: func() string {
2552 path, _ := os.Getwd()
2553 return filepath.Join(path, "/test/config/Files/getFileNameListTestDir")
2559 TranGetFileNameList, [2]byte{0, 1},
2560 NewField(FieldFilePath, []byte{
2566 wantRes: []Transaction{
2571 FieldFileNameWithInfo,
2573 fnwi := FileNameWithInfo{
2574 fileNameWithInfoHeader: fileNameWithInfoHeader{
2575 Type: [4]byte{0x54, 0x45, 0x58, 0x54},
2576 Creator: [4]byte{0x54, 0x54, 0x58, 0x54},
2577 FileSize: [4]byte{0, 0, 0x04, 0},
2579 NameScript: [2]byte{},
2580 NameSize: [2]byte{0, 0x0b},
2582 Name: []byte("testfile-1k"),
2584 b, _ := io.ReadAll(&fnwi)
2593 for _, tt := range tests {
2594 t.Run(tt.name, func(t *testing.T) {
2595 gotRes := HandleGetFileNameList(tt.args.cc, &tt.args.t)
2596 tranAssertEqual(t, tt.wantRes, gotRes)
2601 func TestHandleGetClientInfoText(t *testing.T) {
2609 wantRes []Transaction
2612 name: "when user does not have required permission",
2616 Access: func() accessBitmap {
2617 var bits accessBitmap
2622 //Accounts: map[string]*Account{},
2626 TranGetClientInfoText, [2]byte{0, 1},
2627 NewField(FieldUserID, []byte{0, 1}),
2630 wantRes: []Transaction{
2633 ErrorCode: [4]byte{0, 0, 0, 1},
2635 NewField(FieldError, []byte("You are not allowed to get client info.")),
2641 name: "with a valid user",
2644 UserName: []byte("Testy McTest"),
2645 RemoteAddr: "1.2.3.4:12345",
2647 Access: func() accessBitmap {
2648 var bits accessBitmap
2649 bits.Set(AccessGetClientInfo)
2656 ClientMgr: func() *MockClientMgr {
2657 m := MockClientMgr{}
2658 m.On("Get", ClientID{0x0, 0x1}).Return(&ClientConn{
2659 UserName: []byte("Testy McTest"),
2660 RemoteAddr: "1.2.3.4:12345",
2662 Access: func() accessBitmap {
2663 var bits accessBitmap
2664 bits.Set(AccessGetClientInfo)
2675 ClientFileTransferMgr: ClientFileTransferMgr{},
2678 TranGetClientInfoText, [2]byte{0, 1},
2679 NewField(FieldUserID, []byte{0, 1}),
2682 wantRes: []Transaction{
2686 NewField(FieldData, []byte(
2687 strings.ReplaceAll(`Nickname: Testy McTest
2690 Address: 1.2.3.4:12345
2692 -------- File Downloads ---------
2696 ------- Folder Downloads --------
2700 --------- File Uploads ----------
2704 -------- Folder Uploads ---------
2708 ------- Waiting Downloads -------
2714 NewField(FieldUserName, []byte("Testy McTest")),
2720 for _, tt := range tests {
2721 t.Run(tt.name, func(t *testing.T) {
2722 gotRes := HandleGetClientInfoText(tt.args.cc, &tt.args.t)
2723 tranAssertEqual(t, tt.wantRes, gotRes)
2728 func TestHandleTranAgreed(t *testing.T) {
2736 wantRes []Transaction
2739 name: "normal request flow",
2743 Access: func() accessBitmap {
2744 var bits accessBitmap
2745 bits.Set(AccessDisconUser)
2746 bits.Set(AccessAnyName)
2750 Flags: [2]byte{0, 1},
2751 Version: []byte{0, 1},
2753 logger: NewTestLogger(),
2756 BannerFile: "banner.jpg",
2758 ClientMgr: func() *MockClientMgr {
2759 m := MockClientMgr{}
2760 m.On("List").Return([]*ClientConn{
2762 // ID: [2]byte{0, 2},
2763 // UserName: []byte("UserB"),
2772 TranAgreed, [2]byte{},
2773 NewField(FieldUserName, []byte("username")),
2774 NewField(FieldUserIconID, []byte{0, 1}),
2775 NewField(FieldOptions, []byte{0, 0}),
2778 wantRes: []Transaction{
2780 clientID: [2]byte{0, 1},
2781 Type: [2]byte{0, 0x7a},
2783 NewField(FieldBannerType, []byte("JPEG")),
2787 clientID: [2]byte{0, 1},
2794 for _, tt := range tests {
2795 t.Run(tt.name, func(t *testing.T) {
2796 gotRes := HandleTranAgreed(tt.args.cc, &tt.args.t)
2797 tranAssertEqual(t, tt.wantRes, gotRes)
2802 func TestHandleSetClientUserInfo(t *testing.T) {
2810 wantRes []Transaction
2813 name: "when client does not have AccessAnyName",
2817 Access: func() accessBitmap {
2818 var bits accessBitmap
2823 UserName: []byte("Guest"),
2824 Flags: [2]byte{0, 1},
2826 ClientMgr: func() *MockClientMgr {
2827 m := MockClientMgr{}
2828 m.On("List").Return([]*ClientConn{
2838 TranSetClientUserInfo, [2]byte{},
2839 NewField(FieldUserIconID, []byte{0, 1}),
2840 NewField(FieldUserName, []byte("NOPE")),
2843 wantRes: []Transaction{
2845 clientID: [2]byte{0, 1},
2846 Type: [2]byte{0x01, 0x2d},
2848 NewField(FieldUserID, []byte{0, 1}),
2849 NewField(FieldUserIconID, []byte{0, 1}),
2850 NewField(FieldUserFlags, []byte{0, 1}),
2851 NewField(FieldUserName, []byte("Guest"))},
2856 for _, tt := range tests {
2857 t.Run(tt.name, func(t *testing.T) {
2858 gotRes := HandleSetClientUserInfo(tt.args.cc, &tt.args.t)
2859 tranAssertEqual(t, tt.wantRes, gotRes)
2864 func TestHandleDelNewsItem(t *testing.T) {
2872 wantRes []Transaction
2875 name: "when user does not have permission to delete a news category",
2879 Access: accessBitmap{},
2883 ThreadedNewsMgr: func() *mockThreadNewsMgr {
2884 m := mockThreadNewsMgr{}
2885 m.On("NewsItem", []string{"test"}).Return(NewsCategoryListData15{
2893 TranDelNewsItem, [2]byte{},
2894 NewField(FieldNewsPath,
2899 0x74, 0x65, 0x73, 0x74,
2904 wantRes: []Transaction{
2906 clientID: [2]byte{0, 1},
2908 ErrorCode: [4]byte{0, 0, 0, 1},
2910 NewField(FieldError, []byte("You are not allowed to delete news categories.")),
2916 name: "when user does not have permission to delete a news folder",
2920 Access: accessBitmap{},
2924 ThreadedNewsMgr: func() *mockThreadNewsMgr {
2925 m := mockThreadNewsMgr{}
2926 m.On("NewsItem", []string{"test"}).Return(NewsCategoryListData15{
2934 TranDelNewsItem, [2]byte{},
2935 NewField(FieldNewsPath,
2940 0x74, 0x65, 0x73, 0x74,
2945 wantRes: []Transaction{
2947 clientID: [2]byte{0, 1},
2949 ErrorCode: [4]byte{0, 0, 0, 1},
2951 NewField(FieldError, []byte("You are not allowed to delete news folders.")),
2957 name: "when user deletes a news folder",
2961 Access: func() accessBitmap {
2962 var bits accessBitmap
2963 bits.Set(AccessNewsDeleteFldr)
2969 ThreadedNewsMgr: func() *mockThreadNewsMgr {
2970 m := mockThreadNewsMgr{}
2971 m.On("NewsItem", []string{"test"}).Return(NewsCategoryListData15{Type: NewsBundle})
2972 m.On("DeleteNewsItem", []string{"test"}).Return(nil)
2978 TranDelNewsItem, [2]byte{},
2979 NewField(FieldNewsPath,
2984 0x74, 0x65, 0x73, 0x74,
2989 wantRes: []Transaction{
2991 clientID: [2]byte{0, 1},
2998 for _, tt := range tests {
2999 t.Run(tt.name, func(t *testing.T) {
3000 gotRes := HandleDelNewsItem(tt.args.cc, &tt.args.t)
3002 tranAssertEqual(t, tt.wantRes, gotRes)
3007 func TestHandleTranOldPostNews(t *testing.T) {
3015 wantRes []Transaction
3018 name: "when user does not have required permission",
3022 Access: accessBitmap{},
3026 TranOldPostNews, [2]byte{0, 1},
3027 NewField(FieldData, []byte("hai")),
3030 wantRes: []Transaction{
3033 ErrorCode: [4]byte{0, 0, 0, 1},
3035 NewField(FieldError, []byte("You are not allowed to post news.")),
3041 name: "when user posts news update",
3045 Access: func() accessBitmap {
3046 var bits accessBitmap
3047 bits.Set(AccessNewsPostArt)
3055 ClientMgr: func() *MockClientMgr {
3056 m := MockClientMgr{}
3057 m.On("List").Return([]*ClientConn{})
3060 MessageBoard: func() *mockReadWriteSeeker {
3061 m := mockReadWriteSeeker{}
3062 m.On("Seek", int64(0), 0).Return(int64(0), nil)
3063 m.On("Read", mock.AnythingOfType("[]uint8")).Run(func(args mock.Arguments) {
3064 arg := args.Get(0).([]uint8)
3066 }).Return(4, io.EOF)
3067 m.On("Write", mock.AnythingOfType("[]uint8")).Return(3, nil)
3073 TranOldPostNews, [2]byte{0, 1},
3074 NewField(FieldData, []byte("hai")),
3077 wantRes: []Transaction{
3084 for _, tt := range tests {
3085 t.Run(tt.name, func(t *testing.T) {
3086 gotRes := HandleTranOldPostNews(tt.args.cc, &tt.args.t)
3088 tranAssertEqual(t, tt.wantRes, gotRes)
3093 func TestHandleInviteNewChat(t *testing.T) {
3101 wantRes []Transaction
3104 name: "when user does not have required permission",
3108 Access: func() accessBitmap {
3109 var bits accessBitmap
3114 t: NewTransaction(TranInviteNewChat, [2]byte{0, 1}),
3116 wantRes: []Transaction{
3119 ErrorCode: [4]byte{0, 0, 0, 1},
3121 NewField(FieldError, []byte("You are not allowed to request private chat.")),
3127 name: "when userA invites userB to new private chat",
3132 Access: func() accessBitmap {
3133 var bits accessBitmap
3134 bits.Set(AccessOpenChat)
3138 UserName: []byte("UserA"),
3140 Flags: [2]byte{0, 0},
3142 ClientMgr: func() *MockClientMgr {
3143 m := MockClientMgr{}
3144 m.On("Get", ClientID{0x0, 0x2}).Return(&ClientConn{
3146 UserName: []byte("UserB"),
3150 ChatMgr: func() *MockChatManager {
3151 m := MockChatManager{}
3152 m.On("New", mock.AnythingOfType("*hotline.ClientConn")).Return(ChatID{0x52, 0xfd, 0xfc, 0x07})
3158 TranInviteNewChat, [2]byte{0, 1},
3159 NewField(FieldUserID, []byte{0, 2}),
3162 wantRes: []Transaction{
3164 clientID: [2]byte{0, 2},
3165 Type: [2]byte{0, 0x71},
3167 NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3168 NewField(FieldUserName, []byte("UserA")),
3169 NewField(FieldUserID, []byte{0, 1}),
3173 clientID: [2]byte{0, 1},
3176 NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3177 NewField(FieldUserName, []byte("UserA")),
3178 NewField(FieldUserID, []byte{0, 1}),
3179 NewField(FieldUserIconID, []byte{0, 1}),
3180 NewField(FieldUserFlags, []byte{0, 0}),
3186 name: "when userA invites userB to new private chat, but UserB has refuse private chat enabled",
3191 Access: func() accessBitmap {
3192 var bits accessBitmap
3193 bits.Set(AccessOpenChat)
3197 UserName: []byte("UserA"),
3199 Flags: [2]byte{0, 0},
3201 ClientMgr: func() *MockClientMgr {
3202 m := MockClientMgr{}
3203 m.On("Get", ClientID{0, 2}).Return(&ClientConn{
3206 UserName: []byte("UserB"),
3207 Flags: [2]byte{255, 255},
3211 ChatMgr: func() *MockChatManager {
3212 m := MockChatManager{}
3213 m.On("New", mock.AnythingOfType("*hotline.ClientConn")).Return(ChatID{0x52, 0xfd, 0xfc, 0x07})
3219 TranInviteNewChat, [2]byte{0, 1},
3220 NewField(FieldUserID, []byte{0, 2}),
3223 wantRes: []Transaction{
3225 clientID: [2]byte{0, 1},
3226 Type: [2]byte{0, 0x68},
3228 NewField(FieldData, []byte("UserB does not accept private chats.")),
3229 NewField(FieldUserName, []byte("UserB")),
3230 NewField(FieldUserID, []byte{0, 2}),
3231 NewField(FieldOptions, []byte{0, 2}),
3235 clientID: [2]byte{0, 1},
3238 NewField(FieldChatID, []byte{0x52, 0xfd, 0xfc, 0x07}),
3239 NewField(FieldUserName, []byte("UserA")),
3240 NewField(FieldUserID, []byte{0, 1}),
3241 NewField(FieldUserIconID, []byte{0, 1}),
3242 NewField(FieldUserFlags, []byte{0, 0}),
3248 for _, tt := range tests {
3249 t.Run(tt.name, func(t *testing.T) {
3251 gotRes := HandleInviteNewChat(tt.args.cc, &tt.args.t)
3253 tranAssertEqual(t, tt.wantRes, gotRes)
3258 func TestHandleGetNewsArtData(t *testing.T) {
3266 wantRes []Transaction
3269 name: "when user does not have required permission",
3271 cc: &ClientConn{Account: &Account{}},
3273 TranGetNewsArtData, [2]byte{0, 1},
3276 wantRes: []Transaction{
3279 ErrorCode: [4]byte{0, 0, 0, 1},
3281 NewField(FieldError, []byte("You are not allowed to read news.")),
3287 name: "when user has required permission",
3291 Access: func() accessBitmap {
3292 var bits accessBitmap
3293 bits.Set(AccessNewsReadArt)
3298 ThreadedNewsMgr: func() *mockThreadNewsMgr {
3299 m := mockThreadNewsMgr{}
3300 m.On("GetArticle", []string{"Example Category"}, uint32(1)).Return(&NewsArtData{
3304 PrevArt: [4]byte{0, 0, 0, 1},
3305 NextArt: [4]byte{0, 0, 0, 2},
3306 ParentArt: [4]byte{0, 0, 0, 3},
3307 FirstChildArt: [4]byte{0, 0, 0, 4},
3308 DataFlav: []byte("text/plain"),
3309 Data: "article data",
3316 TranGetNewsArtData, [2]byte{0, 1},
3317 NewField(FieldNewsPath, []byte{
3319 0x00, 0x01, 0x00, 0x00, 0x10, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79,
3321 NewField(FieldNewsArtID, []byte{0, 1}),
3324 wantRes: []Transaction{
3328 NewField(FieldNewsArtTitle, []byte("title")),
3329 NewField(FieldNewsArtPoster, []byte("poster")),
3330 NewField(FieldNewsArtDate, []byte{0, 0, 0, 0, 0, 0, 0, 0}),
3331 NewField(FieldNewsArtPrevArt, []byte{0, 0, 0, 1}),
3332 NewField(FieldNewsArtNextArt, []byte{0, 0, 0, 2}),
3333 NewField(FieldNewsArtParentArt, []byte{0, 0, 0, 3}),
3334 NewField(FieldNewsArt1stChildArt, []byte{0, 0, 0, 4}),
3335 NewField(FieldNewsArtDataFlav, []byte("text/plain")),
3336 NewField(FieldNewsArtData, []byte("article data")),
3342 for _, tt := range tests {
3343 t.Run(tt.name, func(t *testing.T) {
3344 gotRes := HandleGetNewsArtData(tt.args.cc, &tt.args.t)
3345 tranAssertEqual(t, tt.wantRes, gotRes)
3350 func TestHandleGetNewsArtNameList(t *testing.T) {
3358 wantRes []Transaction
3361 name: "when user does not have required permission",
3365 Access: func() accessBitmap {
3366 var bits accessBitmap
3371 //Accounts: map[string]*Account{},
3375 TranGetNewsArtNameList, [2]byte{0, 1},
3378 wantRes: []Transaction{
3382 Type: [2]byte{0, 0},
3383 ErrorCode: [4]byte{0, 0, 0, 1},
3385 NewField(FieldError, []byte("You are not allowed to read news.")),
3391 // name: "when user has required access",
3394 // Account: &Account{
3395 // Access: func() accessBitmap {
3396 // var bits accessBitmap
3397 // bits.Set(AccessNewsReadArt)
3402 // ThreadedNewsMgr: func() *mockThreadNewsMgr {
3403 // m := mockThreadNewsMgr{}
3404 // m.On("ListArticles", []string{"Example Category"}).Return(NewsArtListData{
3405 // Name: []byte("testTitle"),
3406 // NewsArtList: []byte{},
3412 // t: NewTransaction(
3413 // TranGetNewsArtNameList,
3415 // // 00000000 00 01 00 00 10 45 78 61 6d 70 6c 65 20 43 61 74 |.....Example Cat|
3416 // // 00000010 65 67 6f 72 79 |egory|
3417 // NewField(FieldNewsPath, []byte{
3418 // 0x00, 0x01, 0x00, 0x00, 0x10, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79,
3422 // wantRes: []Transaction{
3426 // NewField(FieldNewsArtListData, []byte{
3427 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
3428 // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
3429 // 0x09, 0x74, 0x65, 0x73, 0x74, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x50,
3430 // 0x6f, 0x73, 0x74, 0x65, 0x72, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e,
3439 for _, tt := range tests {
3440 t.Run(tt.name, func(t *testing.T) {
3441 gotRes := HandleGetNewsArtNameList(tt.args.cc, &tt.args.t)
3443 tranAssertEqual(t, tt.wantRes, gotRes)
3448 func TestHandleNewNewsFldr(t *testing.T) {
3456 wantRes []Transaction
3459 name: "when user does not have required permission",
3463 Access: func() accessBitmap {
3464 var bits accessBitmap
3469 //Accounts: map[string]*Account{},
3473 TranGetNewsArtNameList, [2]byte{0, 1},
3476 wantRes: []Transaction{
3480 Type: [2]byte{0, 0},
3481 ErrorCode: [4]byte{0, 0, 0, 1},
3483 NewField(FieldError, []byte("You are not allowed to create news folders.")),
3489 name: "with a valid request",
3493 Access: func() accessBitmap {
3494 var bits accessBitmap
3495 bits.Set(AccessNewsCreateFldr)
3499 logger: NewTestLogger(),
3502 ThreadedNewsMgr: func() *mockThreadNewsMgr {
3503 m := mockThreadNewsMgr{}
3504 m.On("CreateGrouping", []string{"test"}, "testFolder", NewsBundle).Return(nil)
3510 TranGetNewsArtNameList, [2]byte{0, 1},
3511 NewField(FieldFileName, []byte("testFolder")),
3512 NewField(FieldNewsPath,
3517 0x74, 0x65, 0x73, 0x74,
3522 wantRes: []Transaction{
3524 clientID: [2]byte{0, 1},
3531 // Name: "when there is an error writing the threaded news file",
3534 // Account: &Account{
3535 // Access: func() accessBitmap {
3536 // var bits accessBitmap
3537 // bits.Set(AccessNewsCreateFldr)
3541 // logger: NewTestLogger(),
3542 // Type: [2]byte{0, 1},
3544 // ConfigDir: "/fakeConfigRoot",
3545 // FS: func() *MockFileStore {
3546 // mfs := &MockFileStore{}
3547 // mfs.On("WriteFile", "/fakeConfigRoot/ThreadedNews.yaml", mock.Anything, mock.Anything).Return(os.ErrNotExist)
3550 // ThreadedNews: &ThreadedNews{Categories: map[string]NewsCategoryListData15{
3552 // Type: []byte{0, 2},
3556 // SubCats: make(map[string]NewsCategoryListData15),
3561 // t: NewTransaction(
3562 // TranGetNewsArtNameList, [2]byte{0, 1},
3563 // NewField(FieldFileName, []byte("testFolder")),
3564 // NewField(FieldNewsPath,
3569 // 0x74, 0x65, 0x73, 0x74,
3574 // wantRes: []Transaction{
3576 // clientID: [2]byte{0, 1},
3579 // Type: [2]byte{0, 0},
3580 // ErrorCode: [4]byte{0, 0, 0, 1},
3582 // NewField(FieldError, []byte("Error creating news folder.")),
3587 for _, tt := range tests {
3588 t.Run(tt.name, func(t *testing.T) {
3589 gotRes := HandleNewNewsFldr(tt.args.cc, &tt.args.t)
3591 tranAssertEqual(t, tt.wantRes, gotRes)
3596 func TestHandleDownloadBanner(t *testing.T) {
3604 wantRes []Transaction
3606 // TODO: Add test cases.
3608 for _, tt := range tests {
3609 t.Run(tt.name, func(t *testing.T) {
3610 gotRes := HandleDownloadBanner(tt.args.cc, &tt.args.t)
3612 assert.Equalf(t, tt.wantRes, gotRes, "HandleDownloadBanner(%v, %v)", tt.args.cc, &tt.args.t)
3617 func TestHandlePostNewsArt(t *testing.T) {
3625 wantRes []Transaction
3628 name: "without required permission",
3632 Access: func() accessBitmap {
3633 var bits accessBitmap
3643 wantRes: []Transaction{
3646 ErrorCode: [4]byte{0, 0, 0, 1},
3648 NewField(FieldError, []byte("You are not allowed to post news articles.")),
3654 name: "with required permission",
3658 ThreadedNewsMgr: func() *mockThreadNewsMgr {
3659 m := mockThreadNewsMgr{}
3660 m.On("PostArticle", []string{"www"}, uint32(0), mock.AnythingOfType("hotline.NewsArtData")).Return(nil)
3665 Access: func() accessBitmap {
3666 var bits accessBitmap
3667 bits.Set(AccessNewsPostArt)
3675 NewField(FieldNewsPath, []byte{0x00, 0x01, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77}),
3676 NewField(FieldNewsArtID, []byte{0x00, 0x00, 0x00, 0x00}),
3679 wantRes: []Transaction{
3682 ErrorCode: [4]byte{0, 0, 0, 0},
3688 for _, tt := range tests {
3689 t.Run(tt.name, func(t *testing.T) {
3690 tranAssertEqual(t, tt.wantRes, HandlePostNewsArt(tt.args.cc, &tt.args.t))